kmail

rulewidgethandlermanager.cpp

Go to the documentation of this file.
00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002     rulewidgethandlermanager.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org>
00006 
00007     KMail is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     KMail is distributed in the hope that it will be useful, but
00013     WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "rulewidgethandlermanager.h"
00038 
00039 #include "interfaces/rulewidgethandler.h"
00040 #include "stl_util.h"
00041 
00042 #include <kdebug.h>
00043 #include <kiconloader.h>
00044 
00045 #include <qwidgetstack.h>
00046 #include <qstring.h>
00047 #include <qcstring.h>
00048 #include <qobject.h>
00049 #include <qobjectlist.h>
00050 
00051 #include <assert.h>
00052 
00053 #include <algorithm>
00054 using std::for_each;
00055 using std::remove;
00056 
00057 KMail::RuleWidgetHandlerManager * KMail::RuleWidgetHandlerManager::self = 0;
00058 
00059 namespace {
00060   class TextRuleWidgetHandler : public KMail::RuleWidgetHandler {
00061   public:
00062     TextRuleWidgetHandler() : KMail::RuleWidgetHandler() {}
00063     ~TextRuleWidgetHandler() {}
00064 
00065     QWidget * createFunctionWidget( int number,
00066                                     QWidgetStack *functionStack,
00067                                     const QObject *receiver ) const;
00068     QWidget * createValueWidget( int number,
00069                                  QWidgetStack *valueStack,
00070                                  const QObject *receiver ) const;
00071     KMSearchRule::Function function( const QCString & field,
00072                                      const QWidgetStack *functionStack ) const;
00073     QString value( const QCString & field,
00074                    const QWidgetStack *functionStack,
00075                    const QWidgetStack *valueStack ) const;
00076     QString prettyValue( const QCString & field,
00077                          const QWidgetStack *functionStack,
00078                          const QWidgetStack *valueStack ) const;
00079     bool handlesField( const QCString & field ) const;
00080     void reset( QWidgetStack *functionStack,
00081                 QWidgetStack *valueStack ) const;
00082     bool setRule( QWidgetStack *functionStack,
00083                   QWidgetStack *valueStack,
00084                   const KMSearchRule *rule ) const;
00085     bool update( const QCString & field,
00086                  QWidgetStack *functionStack,
00087                  QWidgetStack *valueStack ) const;
00088 
00089  private:
00090     KMSearchRule::Function currentFunction( const QWidgetStack *functionStack ) const;
00091     QString currentValue( const QWidgetStack *valueStack,
00092                           KMSearchRule::Function func ) const;
00093   };
00094 
00095   class MessageRuleWidgetHandler : public KMail::RuleWidgetHandler {
00096   public:
00097     MessageRuleWidgetHandler() : KMail::RuleWidgetHandler() {}
00098     ~MessageRuleWidgetHandler() {}
00099 
00100     QWidget * createFunctionWidget( int number,
00101                                     QWidgetStack *functionStack,
00102                                     const QObject *receiver ) const;
00103     QWidget * createValueWidget( int number,
00104                                  QWidgetStack *valueStack,
00105                                  const QObject *receiver ) const;
00106     KMSearchRule::Function function( const QCString & field,
00107                                      const QWidgetStack *functionStack ) const;
00108     QString value( const QCString & field,
00109                    const QWidgetStack *functionStack,
00110                    const QWidgetStack *valueStack ) const;
00111     QString prettyValue( const QCString & field,
00112                          const QWidgetStack *functionStack,
00113                          const QWidgetStack *valueStack ) const;
00114     bool handlesField( const QCString & field ) const;
00115     void reset( QWidgetStack *functionStack,
00116                 QWidgetStack *valueStack ) const;
00117     bool setRule( QWidgetStack *functionStack,
00118                   QWidgetStack *valueStack,
00119                   const KMSearchRule *rule ) const;
00120     bool update( const QCString & field,
00121                  QWidgetStack *functionStack,
00122                  QWidgetStack *valueStack ) const;
00123 
00124  private:
00125     KMSearchRule::Function currentFunction( const QWidgetStack *functionStack ) const;
00126     QString currentValue( const QWidgetStack *valueStack,
00127                           KMSearchRule::Function func ) const;
00128   };
00129 
00130 
00131   class StatusRuleWidgetHandler : public KMail::RuleWidgetHandler {
00132   public:
00133     StatusRuleWidgetHandler() : KMail::RuleWidgetHandler() {}
00134     ~StatusRuleWidgetHandler() {}
00135 
00136     QWidget * createFunctionWidget( int number,
00137                                     QWidgetStack *functionStack,
00138                                     const QObject *receiver ) const;
00139     QWidget * createValueWidget( int number,
00140                                  QWidgetStack *valueStack,
00141                                  const QObject *receiver ) const;
00142     KMSearchRule::Function function( const QCString & field,
00143                                      const QWidgetStack *functionStack ) const;
00144     QString value( const QCString & field,
00145                    const QWidgetStack *functionStack,
00146                    const QWidgetStack *valueStack ) const;
00147     QString prettyValue( const QCString & field,
00148                          const QWidgetStack *functionStack,
00149                          const QWidgetStack *valueStack ) const;
00150     bool handlesField( const QCString & field ) const;
00151     void reset( QWidgetStack *functionStack,
00152                 QWidgetStack *valueStack ) const;
00153     bool setRule( QWidgetStack *functionStack,
00154                   QWidgetStack *valueStack,
00155                   const KMSearchRule *rule ) const;
00156     bool update( const QCString & field,
00157                  QWidgetStack *functionStack,
00158                  QWidgetStack *valueStack ) const;
00159 
00160   private:
00161     KMSearchRule::Function currentFunction( const QWidgetStack *functionStack ) const;
00162     int currentStatusValue( const QWidgetStack *valueStack ) const;
00163   };
00164 
00165   class NumericRuleWidgetHandler : public KMail::RuleWidgetHandler {
00166   public:
00167     NumericRuleWidgetHandler() : KMail::RuleWidgetHandler() {}
00168     ~NumericRuleWidgetHandler() {}
00169 
00170     QWidget * createFunctionWidget( int number,
00171                                     QWidgetStack *functionStack,
00172                                     const QObject *receiver ) const;
00173     QWidget * createValueWidget( int number,
00174                                  QWidgetStack *valueStack,
00175                                  const QObject *receiver ) const;
00176     KMSearchRule::Function function( const QCString & field,
00177                                      const QWidgetStack *functionStack ) const;
00178     QString value( const QCString & field,
00179                    const QWidgetStack *functionStack,
00180                    const QWidgetStack *valueStack ) const;
00181     QString prettyValue( const QCString & field,
00182                          const QWidgetStack *functionStack,
00183                          const QWidgetStack *valueStack ) const;
00184     bool handlesField( const QCString & field ) const;
00185     void reset( QWidgetStack *functionStack,
00186                 QWidgetStack *valueStack ) const;
00187     bool setRule( QWidgetStack *functionStack,
00188                   QWidgetStack *valueStack,
00189                   const KMSearchRule *rule ) const;
00190     bool update( const QCString & field,
00191                  QWidgetStack *functionStack,
00192                  QWidgetStack *valueStack ) const;
00193 
00194   private:
00195     KMSearchRule::Function currentFunction( const QWidgetStack *functionStack ) const;
00196     QString currentValue( const QWidgetStack *valueStack ) const;
00197   };
00198 }
00199 
00200 KMail::RuleWidgetHandlerManager::RuleWidgetHandlerManager()
00201 {
00202   registerHandler( new NumericRuleWidgetHandler() );
00203   registerHandler( new StatusRuleWidgetHandler() );
00204   registerHandler( new MessageRuleWidgetHandler() );
00205    // the TextRuleWidgetHandler is the fallback handler, so it has to be added
00206   // as last handler
00207   registerHandler( new TextRuleWidgetHandler() );
00208 }
00209 
00210 KMail::RuleWidgetHandlerManager::~RuleWidgetHandlerManager()
00211 {
00212   for_each( mHandlers.begin(), mHandlers.end(),
00213         DeleteAndSetToZero<RuleWidgetHandler>() );
00214 }
00215 
00216 void KMail::RuleWidgetHandlerManager::registerHandler( const RuleWidgetHandler * handler )
00217 {
00218   if ( !handler )
00219     return;
00220   unregisterHandler( handler ); // don't produce duplicates
00221   mHandlers.push_back( handler );
00222 }
00223 
00224 void KMail::RuleWidgetHandlerManager::unregisterHandler( const RuleWidgetHandler * handler )
00225 {
00226   // don't delete them, only remove them from the list!
00227   mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00228 }
00229 
00230 namespace {
00234   int childCount( const QObject *parent, const char *objName )
00235   {
00236     QObjectList *list = parent->queryList( 0, objName, false, false );
00237     if ( !list )
00238       return 0;
00239     const int count = list->count();
00240     delete list; list = 0;
00241     return count;
00242   }
00243 }
00244 
00245 void KMail::RuleWidgetHandlerManager::createWidgets( QWidgetStack *functionStack,
00246                                                      QWidgetStack *valueStack,
00247                                                      const QObject *receiver ) const
00248 {
00249   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00250     QWidget *w = 0;
00251     for ( int i = 0;
00252           ( w = (*it)->createFunctionWidget( i, functionStack, receiver ) );
00253           ++i ) {
00254       if ( childCount( functionStack, w->name() ) < 2 ) {
00255         // there wasn't already a widget with this name, so add this widget
00256         functionStack->addWidget( w );
00257       }
00258       else {
00259         // there was already a widget with this name, so discard this widget
00260         kdDebug(5006) << "RuleWidgetHandlerManager::createWidgets: "
00261                       << w->name() << " already exists in functionStack"
00262                       << endl;
00263         delete w; w = 0;
00264       }
00265     }
00266     for ( int i = 0;
00267           ( w = (*it)->createValueWidget( i, valueStack, receiver ) );
00268           ++i ) {
00269       if ( childCount( valueStack, w->name() ) < 2 ) {
00270         // there wasn't already a widget with this name, so add this widget
00271         valueStack->addWidget( w );
00272       }
00273       else {
00274         // there was already a widget with this name, so discard this widget
00275         kdDebug(5006) << "RuleWidgetHandlerManager::createWidgets: "
00276                       << w->name() << " already exists in valueStack"
00277                       << endl;
00278         delete w; w = 0;
00279       }
00280     }
00281   }
00282 }
00283 
00284 KMSearchRule::Function KMail::RuleWidgetHandlerManager::function( const QCString& field,
00285                                                                   const QWidgetStack *functionStack ) const
00286 {
00287   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00288     const KMSearchRule::Function func = (*it)->function( field,
00289                                                          functionStack );
00290     if ( func != KMSearchRule::FuncNone )
00291       return func;
00292   }
00293   return KMSearchRule::FuncNone;
00294 }
00295 
00296 QString KMail::RuleWidgetHandlerManager::value( const QCString& field,
00297                                                 const QWidgetStack *functionStack,
00298                                                 const QWidgetStack *valueStack ) const
00299 {
00300   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00301     const QString val = (*it)->value( field, functionStack, valueStack );
00302     if ( !val.isEmpty() )
00303       return val;
00304   }
00305   return QString::null;
00306 }
00307 
00308 QString KMail::RuleWidgetHandlerManager::prettyValue( const QCString& field,
00309                                                       const QWidgetStack *functionStack,
00310                                                       const QWidgetStack *valueStack ) const
00311 {
00312   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00313     const QString val = (*it)->prettyValue( field, functionStack, valueStack );
00314     if ( !val.isEmpty() )
00315       return val;
00316   }
00317   return QString::null;
00318 }
00319 
00320 void KMail::RuleWidgetHandlerManager::reset( QWidgetStack *functionStack,
00321                                              QWidgetStack *valueStack ) const
00322 {
00323   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00324     (*it)->reset( functionStack, valueStack );
00325   }
00326   update( "", functionStack, valueStack );
00327 }
00328 
00329 void KMail::RuleWidgetHandlerManager::setRule( QWidgetStack *functionStack,
00330                                                QWidgetStack *valueStack,
00331                                                const KMSearchRule *rule ) const
00332 {
00333   assert( rule );
00334   reset( functionStack, valueStack );
00335   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00336     if ( (*it)->setRule( functionStack, valueStack, rule ) )
00337       return;
00338   }
00339 }
00340 
00341 void KMail::RuleWidgetHandlerManager::update( const QCString &field,
00342                                               QWidgetStack *functionStack,
00343                                               QWidgetStack *valueStack ) const
00344 {
00345   //kdDebug(5006) << "RuleWidgetHandlerManager::update( \"" << field
00346   //              << "\", ... )" << endl;
00347   for ( const_iterator it = mHandlers.begin(); it != mHandlers.end(); ++it ) {
00348     if ( (*it)->update( field, functionStack, valueStack ) )
00349       return;
00350   }
00351 }
00352 
00353 //-----------------------------------------------------------------------------
00354 
00355 namespace {
00356   // FIXME (Qt >= 4.0):
00357   // This is a simplified and constified copy of QObject::child(). According
00358   // to a comment in qobject.h QObject::child() will be made const in Qt 4.0.
00359   // So once we require Qt 4.0 this can be removed.
00360   QObject* QObject_child_const( const QObject *parent,
00361                                 const char *objName )
00362   {
00363     const QObjectList *list = parent->children();
00364     if ( !list )
00365       return 0;
00366 
00367     QObjectListIterator it( *list );
00368     QObject *obj;
00369     while ( ( obj = it.current() ) ) {
00370       ++it;
00371       if ( !objName || qstrcmp( objName, obj->name() ) == 0 )
00372         break;
00373     }
00374     return obj;
00375   }
00376 }
00377 
00378 //-----------------------------------------------------------------------------
00379 
00380 // these includes are temporary and should not be needed for the code
00381 // above this line, so they appear only here:
00382 #include "kmaddrbook.h"
00383 #include "kmsearchpattern.h"
00384 #include "regexplineedit.h"
00385 using KMail::RegExpLineEdit;
00386 
00387 #include <klocale.h>
00388 #include <knuminput.h>
00389 
00390 #include <qcombobox.h>
00391 #include <qlabel.h>
00392 
00393 //=============================================================================
00394 //
00395 // class TextRuleWidgetHandler
00396 //
00397 //=============================================================================
00398 
00399 namespace {
00400   // also see KMSearchRule::matches() and KMSearchRule::Function
00401   // if you change the following strings!
00402   static const struct {
00403     const KMSearchRule::Function id;
00404     const char *displayName;
00405   } TextFunctions[] = {
00406     { KMSearchRule::FuncContains,           I18N_NOOP( "contains" )          },
00407     { KMSearchRule::FuncContainsNot,        I18N_NOOP( "does not contain" )   },
00408     { KMSearchRule::FuncEquals,             I18N_NOOP( "equals" )            },
00409     { KMSearchRule::FuncNotEqual,           I18N_NOOP( "does not equal" )     },
00410     { KMSearchRule::FuncRegExp,             I18N_NOOP( "matches regular expr." ) },
00411     { KMSearchRule::FuncNotRegExp,          I18N_NOOP( "does not match reg. expr." ) },
00412     { KMSearchRule::FuncIsInAddressbook,    I18N_NOOP( "is in address book" ) },
00413     { KMSearchRule::FuncIsNotInAddressbook, I18N_NOOP( "is not in address book" ) },
00414     { KMSearchRule::FuncIsInCategory,       I18N_NOOP( "is in category" ) },
00415     { KMSearchRule::FuncIsNotInCategory,    I18N_NOOP( "is not in category" ) }
00416   };
00417   static const int TextFunctionCount =
00418     sizeof( TextFunctions ) / sizeof( *TextFunctions );
00419 
00420   //---------------------------------------------------------------------------
00421 
00422   QWidget * TextRuleWidgetHandler::createFunctionWidget( int number,
00423                                                          QWidgetStack *functionStack,
00424                                                          const QObject *receiver ) const
00425   {
00426     if ( number != 0 )
00427       return 0;
00428 
00429     QComboBox *funcCombo = new QComboBox( functionStack, "textRuleFuncCombo" );
00430     for ( int i = 0; i < TextFunctionCount; ++i ) {
00431       funcCombo->insertItem( i18n( TextFunctions[i].displayName ) );
00432     }
00433     funcCombo->adjustSize();
00434     QObject::connect( funcCombo, SIGNAL( activated( int ) ),
00435                       receiver, SLOT( slotFunctionChanged() ) );
00436     return funcCombo;
00437   }
00438 
00439   //---------------------------------------------------------------------------
00440 
00441   QWidget * TextRuleWidgetHandler::createValueWidget( int number,
00442                                                       QWidgetStack *valueStack,
00443                                                       const QObject *receiver ) const
00444   {
00445     if ( number == 0 ) {
00446       RegExpLineEdit *lineEdit =
00447         new RegExpLineEdit( valueStack, "regExpLineEdit" );
00448       QObject::connect( lineEdit, SIGNAL( textChanged( const QString & ) ),
00449                         receiver, SLOT( slotValueChanged() ) );
00450       return lineEdit;
00451     }
00452 
00453     // blank QLabel to hide value widget for in-address-book rule
00454     if ( number == 1 ) {
00455       return new QLabel( valueStack, "textRuleValueHider" );
00456     }
00457 
00458     if ( number == 2 ) {
00459       QComboBox *combo =  new QComboBox( valueStack, "categoryCombo" );
00460       QStringList categories = KabcBridge::categories();
00461       combo->insertStringList( categories );
00462       QObject::connect( combo, SIGNAL( activated( int ) ),
00463                         receiver, SLOT( slotValueChanged() ) );
00464       return combo;
00465     }
00466 
00467     return 0;
00468   }
00469 
00470   //---------------------------------------------------------------------------
00471 
00472   KMSearchRule::Function TextRuleWidgetHandler::currentFunction( const QWidgetStack *functionStack ) const
00473   {
00474     const QComboBox *funcCombo =
00475       dynamic_cast<QComboBox*>( QObject_child_const( functionStack,
00476                                                      "textRuleFuncCombo" ) );
00477     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
00478     //  dynamic_cast<QComboBox*>( functionStack->child( "textRuleFuncCombo",
00479     //                                                  0, false ) );
00480     if ( funcCombo ) {
00481       return TextFunctions[funcCombo->currentItem()].id;
00482     }
00483     else
00484       kdDebug(5006) << "TextRuleWidgetHandler::currentFunction: "
00485                        "textRuleFuncCombo not found." << endl;
00486     return KMSearchRule::FuncNone;
00487   }
00488 
00489   //---------------------------------------------------------------------------
00490 
00491   KMSearchRule::Function TextRuleWidgetHandler::function( const QCString &,
00492                                                           const QWidgetStack *functionStack ) const
00493   {
00494     return currentFunction( functionStack );
00495   }
00496 
00497   //---------------------------------------------------------------------------
00498 
00499   QString TextRuleWidgetHandler::currentValue( const QWidgetStack *valueStack,
00500                                                KMSearchRule::Function func ) const
00501   {
00502     // here we gotta check the combobox which contains the categories
00503     if ( func  == KMSearchRule::FuncIsInCategory ||
00504          func  == KMSearchRule::FuncIsNotInCategory ) {
00505       const QComboBox *combo=
00506         dynamic_cast<QComboBox*>( QObject_child_const( valueStack,
00507                                                        "categoryCombo" ) );
00508     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
00509     //  dynamic_cast<QComboBox*>( valueStack->child( "categoryCombo",
00510     //                                               0, false ) );
00511       if ( combo ) {
00512         return combo->currentText();
00513       }
00514       else {
00515         kdDebug(5006) << "TextRuleWidgetHandler::currentValue: "
00516                          "categoryCombo not found." << endl;
00517         return QString::null;
00518       }
00519     }
00520 
00521     //in other cases of func it is a lineedit
00522     const RegExpLineEdit *lineEdit =
00523       dynamic_cast<RegExpLineEdit*>( QObject_child_const( valueStack,
00524                                                           "regExpLineEdit" ) );
00525     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
00526     //  dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00527     //                                                    0, false ) );
00528     if ( lineEdit ) {
00529       return lineEdit->text();
00530       }
00531     else
00532       kdDebug(5006) << "TextRuleWidgetHandler::currentValue: "
00533                        "regExpLineEdit not found." << endl;
00534 
00535     // or anything else, like addressbook
00536     return QString::null;
00537   }
00538 
00539   //---------------------------------------------------------------------------
00540 
00541   QString TextRuleWidgetHandler::value( const QCString &,
00542                                         const QWidgetStack *functionStack,
00543                                         const QWidgetStack *valueStack ) const
00544   {
00545     KMSearchRule::Function func = currentFunction( functionStack );
00546     if ( func == KMSearchRule::FuncIsInAddressbook )
00547       return "is in address book"; // just a non-empty dummy value
00548     else if ( func == KMSearchRule::FuncIsNotInAddressbook )
00549       return "is not in address book"; // just a non-empty dummy value
00550     else
00551       return currentValue( valueStack, func );
00552   }
00553 
00554   //---------------------------------------------------------------------------
00555 
00556   QString TextRuleWidgetHandler::prettyValue( const QCString &,
00557                                               const QWidgetStack *functionStack,
00558                                               const QWidgetStack *valueStack ) const
00559   {
00560     KMSearchRule::Function func = currentFunction( functionStack );
00561     if ( func == KMSearchRule::FuncIsInAddressbook )
00562       return i18n( "is in address book" );
00563     else if ( func == KMSearchRule::FuncIsNotInAddressbook )
00564       return i18n( "is not in address book" );
00565     else
00566       return currentValue( valueStack, func );
00567   }
00568 
00569   //---------------------------------------------------------------------------
00570 
00571   bool TextRuleWidgetHandler::handlesField( const QCString & ) const
00572   {
00573     return true; // we handle all fields (as fallback)
00574   }
00575 
00576   //---------------------------------------------------------------------------
00577 
00578   void TextRuleWidgetHandler::reset( QWidgetStack *functionStack,
00579                                      QWidgetStack *valueStack ) const
00580   {
00581     // reset the function combo box
00582     QComboBox *funcCombo =
00583       dynamic_cast<QComboBox*>( functionStack->child( "textRuleFuncCombo",
00584                                                       0, false ) );
00585     if ( funcCombo ) {
00586       funcCombo->blockSignals( true );
00587       funcCombo->setCurrentItem( 0 );
00588       funcCombo->blockSignals( false );
00589     }
00590 
00591     // reset the value widget
00592     RegExpLineEdit *lineEdit =
00593       dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00594                                                         0, false ) );
00595     if ( lineEdit ) {
00596       lineEdit->blockSignals( true );
00597       lineEdit->clear();
00598       lineEdit->blockSignals( false );
00599       lineEdit->showEditButton( false );
00600       valueStack->raiseWidget( lineEdit );
00601     }
00602 
00603     QComboBox *combo =
00604       dynamic_cast<QComboBox*>( valueStack->child( "categoryCombo",
00605                                                    0, false ) );
00606     if (combo) {
00607       combo->blockSignals( true );
00608       combo->setCurrentItem( 0 );
00609       combo->blockSignals( false );
00610     }
00611   }
00612 
00613   //---------------------------------------------------------------------------
00614 
00615   bool TextRuleWidgetHandler::setRule( QWidgetStack *functionStack,
00616                                        QWidgetStack *valueStack,
00617                                        const KMSearchRule *rule ) const
00618   {
00619     if ( !rule ) {
00620       reset( functionStack, valueStack );
00621       return false;
00622     }
00623 
00624     const KMSearchRule::Function func = rule->function();
00625     int i = 0;
00626     for ( ; i < TextFunctionCount; ++i )
00627       if ( func == TextFunctions[i].id )
00628         break;
00629     QComboBox *funcCombo =
00630       dynamic_cast<QComboBox*>( functionStack->child( "textRuleFuncCombo",
00631                                                       0, false ) );
00632     if ( funcCombo ) {
00633       funcCombo->blockSignals( true );
00634       if ( i < TextFunctionCount )
00635         funcCombo->setCurrentItem( i );
00636       else {
00637         kdDebug(5006) << "TextRuleWidgetHandler::setRule( "
00638                       << rule->asString()
00639                       << " ): unhandled function" << endl;
00640         funcCombo->setCurrentItem( 0 );
00641       }
00642       funcCombo->blockSignals( false );
00643       functionStack->raiseWidget( funcCombo );
00644     }
00645 
00646     if ( func == KMSearchRule::FuncIsInAddressbook ||
00647          func == KMSearchRule::FuncIsNotInAddressbook ) {
00648       QWidget *w =
00649         static_cast<QWidget*>( valueStack->child( "textRuleValueHider",
00650                                                   0, false ) );
00651       valueStack->raiseWidget( w );
00652     }
00653     else if ( func == KMSearchRule::FuncIsInCategory ||
00654               func == KMSearchRule::FuncIsNotInCategory) {
00655       QComboBox *combo =
00656         static_cast<QComboBox*>( valueStack->child( "categoryCombo",
00657                                                     0, false ) );
00658       combo->blockSignals( true );
00659       for ( i = 0; i < combo->count(); ++i )
00660         if ( rule->contents() == combo->text( i ) ) {
00661           combo->setCurrentItem( i );
00662           break;
00663         }
00664       if ( i == combo->count() )
00665         combo->setCurrentItem( 0 );
00666 
00667       combo->blockSignals( false );
00668       valueStack->raiseWidget( combo );
00669     }
00670     else {
00671       RegExpLineEdit *lineEdit =
00672         dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00673                                                           0, false ) );
00674       if ( lineEdit ) {
00675         lineEdit->blockSignals( true );
00676         lineEdit->setText( rule->contents() );
00677         lineEdit->blockSignals( false );
00678         lineEdit->showEditButton( func == KMSearchRule::FuncRegExp ||
00679                                   func == KMSearchRule::FuncNotRegExp );
00680         valueStack->raiseWidget( lineEdit );
00681       }
00682     }
00683     return true;
00684   }
00685 
00686 
00687   //---------------------------------------------------------------------------
00688 
00689   bool TextRuleWidgetHandler::update( const QCString &,
00690                                       QWidgetStack *functionStack,
00691                                       QWidgetStack *valueStack ) const
00692   {
00693     // raise the correct function widget
00694     functionStack->raiseWidget(
00695       static_cast<QWidget*>( functionStack->child( "textRuleFuncCombo",
00696                                                    0, false ) ) );
00697 
00698     // raise the correct value widget
00699     KMSearchRule::Function func = currentFunction( functionStack );
00700     if ( func == KMSearchRule::FuncIsInAddressbook ||
00701          func == KMSearchRule::FuncIsNotInAddressbook ) {
00702       valueStack->raiseWidget(
00703         static_cast<QWidget*>( valueStack->child( "textRuleValueHider",
00704                                                   0, false ) ) );
00705     }
00706     else if ( func == KMSearchRule::FuncIsInCategory ||
00707               func == KMSearchRule::FuncIsNotInCategory) {
00708       valueStack->raiseWidget(
00709         static_cast<QWidget*>( valueStack->child( "categoryCombo",
00710                                                   0, false ) ) );
00711     }
00712     else {
00713       RegExpLineEdit *lineEdit =
00714         dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00715                                                           0, false ) );
00716       if ( lineEdit ) {
00717         lineEdit->showEditButton( func == KMSearchRule::FuncRegExp ||
00718                                   func == KMSearchRule::FuncNotRegExp );
00719         valueStack->raiseWidget( lineEdit );
00720       }
00721     }
00722     return true;
00723   }
00724 
00725 } // anonymous namespace for TextRuleWidgetHandler
00726 
00727 
00728 //=============================================================================
00729 //
00730 // class MessageRuleWidgetHandler
00731 //
00732 //=============================================================================
00733 
00734 namespace {
00735   // also see KMSearchRule::matches() and KMSearchRule::Function
00736   // if you change the following strings!
00737   static const struct {
00738     const KMSearchRule::Function id;
00739     const char *displayName;
00740   } MessageFunctions[] = {
00741     { KMSearchRule::FuncContains,        I18N_NOOP( "contains" )          },
00742     { KMSearchRule::FuncContainsNot,     I18N_NOOP( "does not contain" )  },
00743     { KMSearchRule::FuncRegExp,          I18N_NOOP( "matches regular expr." ) },
00744     { KMSearchRule::FuncNotRegExp,       I18N_NOOP( "does not match reg. expr." ) },
00745     { KMSearchRule::FuncHasAttachment,   I18N_NOOP( "has an attachment" ) },
00746     { KMSearchRule::FuncHasNoAttachment, I18N_NOOP( "has no attachment" ) },
00747   };
00748   static const int MessageFunctionCount =
00749     sizeof( MessageFunctions ) / sizeof( *MessageFunctions );
00750 
00751   //---------------------------------------------------------------------------
00752 
00753   QWidget * MessageRuleWidgetHandler::createFunctionWidget( int number,
00754                                                             QWidgetStack *functionStack,
00755                                                             const QObject *receiver ) const
00756   {
00757     if ( number != 0 )
00758       return 0;
00759 
00760     QComboBox *funcCombo = new QComboBox( functionStack, "messageRuleFuncCombo" );
00761     for ( int i = 0; i < MessageFunctionCount; ++i ) {
00762       funcCombo->insertItem( i18n( MessageFunctions[i].displayName ) );
00763     }
00764     funcCombo->adjustSize();
00765     QObject::connect( funcCombo, SIGNAL( activated( int ) ),
00766                       receiver, SLOT( slotFunctionChanged() ) );
00767     return funcCombo;
00768   }
00769 
00770   //---------------------------------------------------------------------------
00771 
00772   QWidget * MessageRuleWidgetHandler::createValueWidget( int number,
00773                                                          QWidgetStack *valueStack,
00774                                                          const QObject *receiver ) const
00775   {
00776     if ( number == 0 ) {
00777       RegExpLineEdit *lineEdit =
00778         new RegExpLineEdit( valueStack, "regExpLineEdit" );
00779       QObject::connect( lineEdit, SIGNAL( textChanged( const QString & ) ),
00780                         receiver, SLOT( slotValueChanged() ) );
00781       return lineEdit;
00782     }
00783 
00784     // blank QLabel to hide value widget for has-attachment rule
00785     if ( number == 1 ) {
00786       return new QLabel( valueStack, "textRuleValueHider" );
00787     }
00788 
00789     return 0;
00790   }
00791 
00792   //---------------------------------------------------------------------------
00793 
00794   KMSearchRule::Function MessageRuleWidgetHandler::currentFunction( const QWidgetStack *functionStack ) const
00795   {
00796     const QComboBox *funcCombo =
00797       dynamic_cast<QComboBox*>( QObject_child_const( functionStack,
00798                                                      "messageRuleFuncCombo" ) );
00799     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
00800     //  dynamic_cast<QComboBox*>( functionStack->child( "messageRuleFuncCombo",
00801     //                                                  0, false ) );
00802     if ( funcCombo ) {
00803       return MessageFunctions[funcCombo->currentItem()].id;
00804     }
00805     else
00806       kdDebug(5006) << "MessageRuleWidgetHandler::currentFunction: "
00807                        "messageRuleFuncCombo not found." << endl;
00808     return KMSearchRule::FuncNone;
00809   }
00810 
00811   //---------------------------------------------------------------------------
00812 
00813   KMSearchRule::Function MessageRuleWidgetHandler::function( const QCString & field,
00814                                                              const QWidgetStack *functionStack ) const
00815   {
00816     if ( !handlesField( field ) )
00817       return KMSearchRule::FuncNone;
00818 
00819     return currentFunction( functionStack );
00820   }
00821 
00822   //---------------------------------------------------------------------------
00823 
00824   QString MessageRuleWidgetHandler::currentValue( const QWidgetStack *valueStack,
00825                                                   KMSearchRule::Function ) const
00826   {
00827     const RegExpLineEdit *lineEdit =
00828       dynamic_cast<RegExpLineEdit*>( QObject_child_const( valueStack,
00829                                                           "regExpLineEdit" ) );
00830     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
00831     //  dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00832     //                                                    0, false ) );
00833     if ( lineEdit ) {
00834       return lineEdit->text();
00835     }
00836     else
00837       kdDebug(5006) << "MessageRuleWidgetHandler::currentValue: "
00838                        "regExpLineEdit not found." << endl;
00839 
00840     return QString::null;
00841   }
00842 
00843   //---------------------------------------------------------------------------
00844 
00845   QString MessageRuleWidgetHandler::value( const QCString & field,
00846                                            const QWidgetStack *functionStack,
00847                                            const QWidgetStack *valueStack ) const
00848   {
00849     if ( !handlesField( field ) )
00850       return QString::null;
00851 
00852     KMSearchRule::Function func = currentFunction( functionStack );
00853     if ( func == KMSearchRule::FuncHasAttachment )
00854       return "has an attachment"; // just a non-empty dummy value
00855     else if ( func == KMSearchRule::FuncHasNoAttachment )
00856       return "has no attachment"; // just a non-empty dummy value
00857     else
00858       return currentValue( valueStack, func );
00859   }
00860 
00861   //---------------------------------------------------------------------------
00862 
00863   QString MessageRuleWidgetHandler::prettyValue( const QCString & field,
00864                                                  const QWidgetStack *functionStack,
00865                                                  const QWidgetStack *valueStack ) const
00866   {
00867     if ( !handlesField( field ) )
00868       return QString::null;
00869 
00870     KMSearchRule::Function func = currentFunction( functionStack );
00871     if ( func == KMSearchRule::FuncHasAttachment )
00872       return i18n( "has an attachment" );
00873     else if ( func == KMSearchRule::FuncHasNoAttachment )
00874       return i18n( "has no attachment" );
00875     else
00876       return currentValue( valueStack, func );
00877   }
00878 
00879   //---------------------------------------------------------------------------
00880 
00881   bool MessageRuleWidgetHandler::handlesField( const QCString & field ) const
00882   {
00883     return ( field == "<message>" );
00884   }
00885 
00886   //---------------------------------------------------------------------------
00887 
00888   void MessageRuleWidgetHandler::reset( QWidgetStack *functionStack,
00889                                         QWidgetStack *valueStack ) const
00890   {
00891     // reset the function combo box
00892     QComboBox *funcCombo =
00893       dynamic_cast<QComboBox*>( functionStack->child( "messageRuleFuncCombo",
00894                                                       0, false ) );
00895     if ( funcCombo ) {
00896       funcCombo->blockSignals( true );
00897       funcCombo->setCurrentItem( 0 );
00898       funcCombo->blockSignals( false );
00899     }
00900 
00901     // reset the value widget
00902     RegExpLineEdit *lineEdit =
00903       dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00904                                                         0, false ) );
00905     if ( lineEdit ) {
00906       lineEdit->blockSignals( true );
00907       lineEdit->clear();
00908       lineEdit->blockSignals( false );
00909       lineEdit->showEditButton( false );
00910       valueStack->raiseWidget( lineEdit );
00911     }
00912   }
00913 
00914   //---------------------------------------------------------------------------
00915 
00916   bool MessageRuleWidgetHandler::setRule( QWidgetStack *functionStack,
00917                                           QWidgetStack *valueStack,
00918                                           const KMSearchRule *rule ) const
00919   {
00920     if ( !rule || !handlesField( rule->field() ) ) {
00921       reset( functionStack, valueStack );
00922       return false;
00923     }
00924 
00925     const KMSearchRule::Function func = rule->function();
00926     int i = 0;
00927     for ( ; i < MessageFunctionCount; ++i )
00928       if ( func == MessageFunctions[i].id )
00929         break;
00930     QComboBox *funcCombo =
00931       dynamic_cast<QComboBox*>( functionStack->child( "messageRuleFuncCombo",
00932                                                       0, false ) );
00933     if ( funcCombo ) {
00934       funcCombo->blockSignals( true );
00935       if ( i < MessageFunctionCount )
00936         funcCombo->setCurrentItem( i );
00937       else {
00938         kdDebug(5006) << "MessageRuleWidgetHandler::setRule( "
00939                       << rule->asString()
00940                       << " ): unhandled function" << endl;
00941         funcCombo->setCurrentItem( 0 );
00942       }
00943       funcCombo->blockSignals( false );
00944       functionStack->raiseWidget( funcCombo );
00945     }
00946 
00947     if ( func == KMSearchRule::FuncHasAttachment  ||
00948          func == KMSearchRule::FuncHasNoAttachment ) {
00949       QWidget *w =
00950         static_cast<QWidget*>( valueStack->child( "textRuleValueHider",
00951                                                   0, false ) );
00952       valueStack->raiseWidget( w );
00953     }
00954     else {
00955       RegExpLineEdit *lineEdit =
00956         dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00957                                                           0, false ) );
00958       if ( lineEdit ) {
00959         lineEdit->blockSignals( true );
00960         lineEdit->setText( rule->contents() );
00961         lineEdit->blockSignals( false );
00962         lineEdit->showEditButton( func == KMSearchRule::FuncRegExp ||
00963                                   func == KMSearchRule::FuncNotRegExp );
00964         valueStack->raiseWidget( lineEdit );
00965       }
00966     }
00967     return true;
00968   }
00969 
00970 
00971   //---------------------------------------------------------------------------
00972 
00973   bool MessageRuleWidgetHandler::update( const QCString & field,
00974                                       QWidgetStack *functionStack,
00975                                       QWidgetStack *valueStack ) const
00976   {
00977     if ( !handlesField( field ) )
00978       return false;
00979     // raise the correct function widget
00980     functionStack->raiseWidget(
00981       static_cast<QWidget*>( functionStack->child( "messageRuleFuncCombo",
00982                                                    0, false ) ) );
00983 
00984     // raise the correct value widget
00985     KMSearchRule::Function func = currentFunction( functionStack );
00986     if ( func == KMSearchRule::FuncHasAttachment  ||
00987          func == KMSearchRule::FuncHasNoAttachment ) {
00988       QWidget *w =
00989         static_cast<QWidget*>( valueStack->child( "textRuleValueHider",
00990                                                   0, false ) );
00991       valueStack->raiseWidget( w );
00992     }
00993     else {
00994       RegExpLineEdit *lineEdit =
00995         dynamic_cast<RegExpLineEdit*>( valueStack->child( "regExpLineEdit",
00996                                                           0, false ) );
00997       if ( lineEdit ) {
00998         lineEdit->showEditButton( func == KMSearchRule::FuncRegExp ||
00999                                   func == KMSearchRule::FuncNotRegExp );
01000         valueStack->raiseWidget( lineEdit );
01001       }
01002     }
01003     return true;
01004   }
01005 
01006 } // anonymous namespace for MessageRuleWidgetHandler
01007 
01008 
01009 //=============================================================================
01010 //
01011 // class StatusRuleWidgetHandler
01012 //
01013 //=============================================================================
01014 
01015 namespace {
01016   static const struct {
01017     const KMSearchRule::Function id;
01018     const char *displayName;
01019   } StatusFunctions[] = {
01020     { KMSearchRule::FuncContains,    I18N_NOOP( "is" )    },
01021     { KMSearchRule::FuncContainsNot, I18N_NOOP( "is not" ) }
01022   };
01023   static const int StatusFunctionCount =
01024     sizeof( StatusFunctions ) / sizeof( *StatusFunctions );
01025 
01026   //---------------------------------------------------------------------------
01027 
01028   QWidget * StatusRuleWidgetHandler::createFunctionWidget( int number,
01029                                                            QWidgetStack *functionStack,
01030                                                            const QObject *receiver ) const
01031   {
01032     if ( number != 0 )
01033       return 0;
01034 
01035     QComboBox *funcCombo = new QComboBox( functionStack,
01036                                           "statusRuleFuncCombo" );
01037     for ( int i = 0; i < StatusFunctionCount; ++i ) {
01038       funcCombo->insertItem( i18n( StatusFunctions[i].displayName ) );
01039     }
01040     funcCombo->adjustSize();
01041     QObject::connect( funcCombo, SIGNAL( activated( int ) ),
01042                       receiver, SLOT( slotFunctionChanged() ) );
01043     return funcCombo;
01044   }
01045 
01046   //---------------------------------------------------------------------------
01047 
01048   QWidget * StatusRuleWidgetHandler::createValueWidget( int number,
01049                                                         QWidgetStack *valueStack,
01050                                                         const QObject *receiver ) const
01051   {
01052     if ( number != 0 )
01053       return 0;
01054 
01055     QComboBox *statusCombo = new QComboBox( valueStack,
01056                                             "statusRuleValueCombo" );
01057     for ( int i = 0; i < KMail::StatusValueCountWithoutHidden; ++i ) {
01058       statusCombo->insertItem( UserIcon( KMail::StatusValues[ i ].icon ), i18n( KMail::StatusValues[ i ].text ) );
01059     }
01060     statusCombo->adjustSize();
01061     QObject::connect( statusCombo, SIGNAL( activated( int ) ),
01062                       receiver, SLOT( slotValueChanged() ) );
01063     return statusCombo;
01064   }
01065 
01066   //---------------------------------------------------------------------------
01067 
01068   KMSearchRule::Function StatusRuleWidgetHandler::currentFunction( const QWidgetStack *functionStack ) const
01069   {
01070     const QComboBox *funcCombo =
01071       dynamic_cast<QComboBox*>( QObject_child_const( functionStack,
01072                                                      "statusRuleFuncCombo" ) );
01073     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
01074     //  dynamic_cast<QComboBox*>( functionStack->child( "statusRuleFuncCombo",
01075     //                                                  0, false ) );
01076     if ( funcCombo ) {
01077       return StatusFunctions[funcCombo->currentItem()].id;
01078     }
01079     else
01080       kdDebug(5006) << "StatusRuleWidgetHandler::currentFunction: "
01081                        "statusRuleFuncCombo not found." << endl;
01082     return KMSearchRule::FuncNone;
01083   }
01084 
01085   //---------------------------------------------------------------------------
01086 
01087   KMSearchRule::Function StatusRuleWidgetHandler::function( const QCString & field,
01088                                                             const QWidgetStack *functionStack ) const
01089   {
01090     if ( !handlesField( field ) )
01091       return KMSearchRule::FuncNone;
01092 
01093     return currentFunction( functionStack );
01094   }
01095 
01096   //---------------------------------------------------------------------------
01097 
01098   int StatusRuleWidgetHandler::currentStatusValue( const QWidgetStack *valueStack ) const
01099   {
01100     const QComboBox *statusCombo =
01101       dynamic_cast<QComboBox*>( QObject_child_const( valueStack,
01102                                                      "statusRuleValueCombo" ) );
01103     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
01104     //  dynamic_cast<QComboBox*>( valueStack->child( "statusRuleValueCombo",
01105     //                                               0, false ) );
01106     if ( statusCombo ) {
01107       return statusCombo->currentItem();
01108     }
01109     else
01110       kdDebug(5006) << "StatusRuleWidgetHandler::currentStatusValue: "
01111                        "statusRuleValueCombo not found." << endl;
01112     return -1;
01113   }
01114 
01115   //---------------------------------------------------------------------------
01116 
01117   QString StatusRuleWidgetHandler::value( const QCString & field,
01118                                           const QWidgetStack *,
01119                                           const QWidgetStack *valueStack ) const
01120   {
01121     if ( !handlesField( field ) )
01122       return QString::null;
01123 
01124     const int status = currentStatusValue( valueStack );
01125     if ( status != -1 )
01126       return QString::fromLatin1( KMail::StatusValues[ status ].text );
01127     else
01128       return QString::null;
01129   }
01130 
01131   //---------------------------------------------------------------------------
01132 
01133   QString StatusRuleWidgetHandler::prettyValue( const QCString & field,
01134                                                 const QWidgetStack *,
01135                                                 const QWidgetStack *valueStack ) const
01136   {
01137     if ( !handlesField( field ) )
01138       return QString::null;
01139 
01140     const int status = currentStatusValue( valueStack );
01141     if ( status != -1 )
01142       return i18n( KMail::StatusValues[ status ].text );
01143     else
01144       return QString::null;
01145   }
01146 
01147   //---------------------------------------------------------------------------
01148 
01149   bool StatusRuleWidgetHandler::handlesField( const QCString & field ) const
01150   {
01151     return ( field == "<status>" );
01152   }
01153 
01154   //---------------------------------------------------------------------------
01155 
01156   void StatusRuleWidgetHandler::reset( QWidgetStack *functionStack,
01157                                        QWidgetStack *valueStack ) const
01158   {
01159     // reset the function combo box
01160     QComboBox *funcCombo =
01161       dynamic_cast<QComboBox*>( functionStack->child( "statusRuleFuncCombo",
01162                                                       0, false ) );
01163     if ( funcCombo ) {
01164       funcCombo->blockSignals( true );
01165       funcCombo->setCurrentItem( 0 );
01166       funcCombo->blockSignals( false );
01167     }
01168 
01169     // reset the status value combo box
01170     QComboBox *statusCombo =
01171       dynamic_cast<QComboBox*>( valueStack->child( "statusRuleValueCombo",
01172                                                    0, false ) );
01173     if ( statusCombo ) {
01174       statusCombo->blockSignals( true );
01175       statusCombo->setCurrentItem( 0 );
01176       statusCombo->blockSignals( false );
01177     }
01178   }
01179 
01180   //---------------------------------------------------------------------------
01181 
01182   bool StatusRuleWidgetHandler::setRule( QWidgetStack *functionStack,
01183                                          QWidgetStack *valueStack,
01184                                          const KMSearchRule *rule ) const
01185   {
01186     if ( !rule || !handlesField( rule->field() ) ) {
01187       reset( functionStack, valueStack );
01188       return false;
01189     }
01190 
01191     // set the function
01192     const KMSearchRule::Function func = rule->function();
01193     int funcIndex = 0;
01194     for ( ; funcIndex < StatusFunctionCount; ++funcIndex )
01195       if ( func == StatusFunctions[funcIndex].id )
01196         break;
01197     QComboBox *funcCombo =
01198       dynamic_cast<QComboBox*>( functionStack->child( "statusRuleFuncCombo",
01199                                                       0, false ) );
01200     if ( funcCombo ) {
01201       funcCombo->blockSignals( true );
01202       if ( funcIndex < StatusFunctionCount )
01203         funcCombo->setCurrentItem( funcIndex );
01204       else {
01205         kdDebug(5006) << "StatusRuleWidgetHandler::setRule( "
01206                       << rule->asString()
01207                       << " ): unhandled function" << endl;
01208         funcCombo->setCurrentItem( 0 );
01209       }
01210       funcCombo->blockSignals( false );
01211       functionStack->raiseWidget( funcCombo );
01212     }
01213 
01214     // set the value
01215     const QString value = rule->contents();
01216     int valueIndex = 0;
01217     for ( ; valueIndex < KMail::StatusValueCountWithoutHidden; ++valueIndex )
01218       if ( value == QString::fromLatin1(
01219                KMail::StatusValues[ valueIndex ].text ) )
01220         break;
01221     QComboBox *statusCombo =
01222       dynamic_cast<QComboBox*>( valueStack->child( "statusRuleValueCombo",
01223                                                    0, false ) );
01224     if ( statusCombo ) {
01225       statusCombo->blockSignals( true );
01226       if ( valueIndex < KMail::StatusValueCountWithoutHidden )
01227         statusCombo->setCurrentItem( valueIndex );
01228       else {
01229         kdDebug(5006) << "StatusRuleWidgetHandler::setRule( "
01230                       << rule->asString()
01231                       << " ): unhandled value" << endl;
01232         statusCombo->setCurrentItem( 0 );
01233       }
01234       statusCombo->blockSignals( false );
01235       valueStack->raiseWidget( statusCombo );
01236     }
01237     return true;
01238   }
01239 
01240 
01241   //---------------------------------------------------------------------------
01242 
01243   bool StatusRuleWidgetHandler::update( const QCString &field,
01244                                         QWidgetStack *functionStack,
01245                                         QWidgetStack *valueStack ) const
01246   {
01247     if ( !handlesField( field ) )
01248       return false;
01249 
01250     // raise the correct function widget
01251     functionStack->raiseWidget(
01252       static_cast<QWidget*>( functionStack->child( "statusRuleFuncCombo",
01253                                                    0, false ) ) );
01254 
01255     // raise the correct value widget
01256     valueStack->raiseWidget(
01257       static_cast<QWidget*>( valueStack->child( "statusRuleValueCombo",
01258                                                 0, false ) ) );
01259     return true;
01260   }
01261 
01262 } // anonymous namespace for StatusRuleWidgetHandler
01263 
01264 
01265 //=============================================================================
01266 //
01267 // class NumericRuleWidgetHandler
01268 //
01269 //=============================================================================
01270 
01271 namespace {
01272   static const struct {
01273     const KMSearchRule::Function id;
01274     const char *displayName;
01275   } NumericFunctions[] = {
01276     { KMSearchRule::FuncEquals,           I18N_NOOP( "is equal to" )         },
01277     { KMSearchRule::FuncNotEqual,         I18N_NOOP( "is not equal to" )      },
01278     { KMSearchRule::FuncIsGreater,        I18N_NOOP( "is greater than" )     },
01279     { KMSearchRule::FuncIsLessOrEqual,    I18N_NOOP( "is less than or equal to" ) },
01280     { KMSearchRule::FuncIsLess,           I18N_NOOP( "is less than" )        },
01281     { KMSearchRule::FuncIsGreaterOrEqual, I18N_NOOP( "is greater than or equal to" ) }
01282   };
01283   static const int NumericFunctionCount =
01284     sizeof( NumericFunctions ) / sizeof( *NumericFunctions );
01285 
01286   //---------------------------------------------------------------------------
01287 
01288   QWidget * NumericRuleWidgetHandler::createFunctionWidget( int number,
01289                                                             QWidgetStack *functionStack,
01290                                                             const QObject *receiver ) const
01291   {
01292     if ( number != 0 )
01293       return 0;
01294 
01295     QComboBox *funcCombo = new QComboBox( functionStack,
01296                                           "numericRuleFuncCombo" );
01297     for ( int i = 0; i < NumericFunctionCount; ++i ) {
01298       funcCombo->insertItem( i18n( NumericFunctions[i].displayName ) );
01299     }
01300     funcCombo->adjustSize();
01301     QObject::connect( funcCombo, SIGNAL( activated( int ) ),
01302                       receiver, SLOT( slotFunctionChanged() ) );
01303     return funcCombo;
01304   }
01305 
01306   //---------------------------------------------------------------------------
01307 
01308   QWidget * NumericRuleWidgetHandler::createValueWidget( int number,
01309                                                          QWidgetStack *valueStack,
01310                                                          const QObject *receiver ) const
01311   {
01312     if ( number != 0 )
01313       return 0;
01314 
01315     KIntNumInput *numInput = new KIntNumInput( valueStack, "KIntNumInput" );
01316     QObject::connect( numInput, SIGNAL( valueChanged( int ) ),
01317                       receiver, SLOT( slotValueChanged() ) );
01318     return numInput;
01319   }
01320 
01321   //---------------------------------------------------------------------------
01322 
01323   KMSearchRule::Function NumericRuleWidgetHandler::currentFunction( const QWidgetStack *functionStack ) const
01324   {
01325     const QComboBox *funcCombo =
01326       dynamic_cast<QComboBox*>( QObject_child_const( functionStack,
01327                                                      "numericRuleFuncCombo" ) );
01328     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
01329     //  dynamic_cast<QComboBox*>( functionStack->child( "numericRuleFuncCombo",
01330     //                                                  0, false ) );
01331     if ( funcCombo ) {
01332       return NumericFunctions[funcCombo->currentItem()].id;
01333     }
01334     else
01335       kdDebug(5006) << "NumericRuleWidgetHandler::currentFunction: "
01336                        "numericRuleFuncCombo not found." << endl;
01337     return KMSearchRule::FuncNone;
01338   }
01339 
01340   //---------------------------------------------------------------------------
01341 
01342   KMSearchRule::Function NumericRuleWidgetHandler::function( const QCString & field,
01343                                                              const QWidgetStack *functionStack ) const
01344   {
01345     if ( !handlesField( field ) )
01346       return KMSearchRule::FuncNone;
01347 
01348     return currentFunction( functionStack );
01349   }
01350 
01351   //---------------------------------------------------------------------------
01352 
01353   QString NumericRuleWidgetHandler::currentValue( const QWidgetStack *valueStack ) const
01354   {
01355     const KIntNumInput *numInput =
01356       dynamic_cast<KIntNumInput*>( QObject_child_const( valueStack,
01357                                                         "KIntNumInput" ) );
01358     // FIXME (Qt >= 4.0): Use the following when QObject::child() is const.
01359     //  dynamic_cast<KIntNumInput*>( valueStack->child( "KIntNumInput",
01360     //                                                  0, false ) );
01361     if ( numInput ) {
01362       return QString::number( numInput->value() );
01363     }
01364     else
01365       kdDebug(5006) << "NumericRuleWidgetHandler::currentValue: "
01366                        "KIntNumInput not found." << endl;
01367     return QString::null;
01368   }
01369 
01370   //---------------------------------------------------------------------------
01371 
01372   QString NumericRuleWidgetHandler::value( const QCString & field,
01373                                            const QWidgetStack *,
01374                                            const QWidgetStack *valueStack ) const
01375   {
01376     if ( !handlesField( field ) )
01377       return QString::null;
01378 
01379     return currentValue( valueStack );
01380   }
01381 
01382   //---------------------------------------------------------------------------
01383 
01384   QString NumericRuleWidgetHandler::prettyValue( const QCString & field,
01385                                                  const QWidgetStack *,
01386                                                  const QWidgetStack *valueStack ) const
01387   {
01388     if ( !handlesField( field ) )
01389       return QString::null;
01390 
01391     return currentValue( valueStack );
01392   }
01393 
01394   //---------------------------------------------------------------------------
01395 
01396   bool NumericRuleWidgetHandler::handlesField( const QCString & field ) const
01397   {
01398     return ( field == "<size>" || field == "<age in days>" );
01399   }
01400 
01401   //---------------------------------------------------------------------------
01402 
01403   void NumericRuleWidgetHandler::reset( QWidgetStack *functionStack,
01404                                         QWidgetStack *valueStack ) const
01405   {
01406     // reset the function combo box
01407     QComboBox *funcCombo =
01408       dynamic_cast<QComboBox*>( functionStack->child( "numericRuleFuncCombo",
01409                                                       0, false ) );
01410     if ( funcCombo ) {
01411       funcCombo->blockSignals( true );
01412       funcCombo->setCurrentItem( 0 );
01413       funcCombo->blockSignals( false );
01414     }
01415 
01416     // reset the value widget
01417     KIntNumInput *numInput =
01418       dynamic_cast<KIntNumInput*>( valueStack->child( "KIntNumInput",
01419                                                       0, false ) );
01420     if ( numInput ) {
01421       numInput->blockSignals( true );
01422       numInput->setValue( 0 );
01423       numInput->blockSignals( false );
01424     }
01425   }
01426 
01427   //---------------------------------------------------------------------------
01428 
01429   void initNumInput( KIntNumInput *numInput, const QCString &field )
01430   {
01431     if ( field == "<size>" ) {
01432       numInput->setMinValue( 0 );
01433       numInput->setSuffix( i18n( " bytes" ) );
01434     }
01435     else {
01436       numInput->setMinValue( -10000 );
01437       numInput->setSuffix( i18n( " days" ) );
01438     }
01439   }
01440 
01441   //---------------------------------------------------------------------------
01442 
01443   bool NumericRuleWidgetHandler::setRule( QWidgetStack *functionStack,
01444                                           QWidgetStack *valueStack,
01445                                           const KMSearchRule *rule ) const
01446   {
01447     if ( !rule || !handlesField( rule->field() ) ) {
01448       reset( functionStack, valueStack );
01449       return false;
01450     }
01451 
01452     // set the function
01453     const KMSearchRule::Function func = rule->function();
01454     int funcIndex = 0;
01455     for ( ; funcIndex < NumericFunctionCount; ++funcIndex )
01456       if ( func == NumericFunctions[funcIndex].id )
01457         break;
01458     QComboBox *funcCombo =
01459       dynamic_cast<QComboBox*>( functionStack->child( "numericRuleFuncCombo",
01460                                                       0, false ) );
01461     if ( funcCombo ) {
01462       funcCombo->blockSignals( true );
01463       if ( funcIndex < NumericFunctionCount )
01464         funcCombo->setCurrentItem( funcIndex );
01465       else {
01466         kdDebug(5006) << "NumericRuleWidgetHandler::setRule( "
01467                       << rule->asString()
01468                       << " ): unhandled function" << endl;
01469         funcCombo->setCurrentItem( 0 );
01470       }
01471       funcCombo->blockSignals( false );
01472       functionStack->raiseWidget( funcCombo );
01473     }
01474 
01475     // set the value
01476     bool ok;
01477     int value = rule->contents().toInt( &ok );
01478     if ( !ok )
01479       value = 0;
01480     KIntNumInput *numInput =
01481       dynamic_cast<KIntNumInput*>( valueStack->child( "KIntNumInput",
01482                                                       0, false ) );
01483     if ( numInput ) {
01484       initNumInput( numInput, rule->field() );
01485       numInput->blockSignals( true );
01486       numInput->setValue( value );
01487       numInput->blockSignals( false );
01488       valueStack->raiseWidget( numInput );
01489     }
01490     return true;
01491   }
01492 
01493 
01494   //---------------------------------------------------------------------------
01495 
01496   bool NumericRuleWidgetHandler::update( const QCString &field,
01497                                          QWidgetStack *functionStack,
01498                                          QWidgetStack *valueStack ) const
01499   {
01500     if ( !handlesField( field ) )
01501       return false;
01502 
01503     // raise the correct function widget
01504     functionStack->raiseWidget(
01505       static_cast<QWidget*>( functionStack->child( "numericRuleFuncCombo",
01506                                                    0, false ) ) );
01507 
01508     // raise the correct value widget
01509     KIntNumInput *numInput =
01510       dynamic_cast<KIntNumInput*>( valueStack->child( "KIntNumInput",
01511                                                       0, false ) );
01512     if ( numInput ) {
01513       initNumInput( numInput, field );
01514       valueStack->raiseWidget( numInput );
01515     }
01516     return true;
01517   }
01518 
01519 } // anonymous namespace for NumericRuleWidgetHandler
01520