libkdepim Library API Documentation

completionordereditor.cpp

00001 
00031 #include "completionordereditor.h"
00032 #include "ldapclient.h"
00033 #include "resourceabc.h"
00034 
00035 #include <kabc/stdaddressbook.h>
00036 #include <kabc/resource.h>
00037 
00038 #include <kdebug.h>
00039 #include <klocale.h>
00040 #include <kiconloader.h>
00041 #include <klistview.h>
00042 
00043 #include <qhbox.h>
00044 #include <qvbox.h>
00045 #include <qheader.h>
00046 #include <qtoolbutton.h>
00047 #include <qcheckbox.h>
00048 #include <kapplication.h>
00049 #include <dcopclient.h>
00050 
00051 /*
00052 
00053 Several items are used in addresseelineedit's completion object:
00054   LDAP servers, KABC resources (imap and non-imap), Recent addresses (in kmail only).
00055 
00056 The default completion weights are as follow:
00057   LDAP: 50, 49, 48 etc.          (see ldapclient.cpp)
00058   KABC non-imap resources: 60    (see addresseelineedit.cpp and SimpleCompletionItem here)
00059   Distribution lists: 60         (see addresseelineedit.cpp and SimpleCompletionItem here)
00060   KABC imap resources: 80        (see kresources/imap/kabc/resourceimap.cpp)
00061   Recent addresses (kmail) : 120 (see kmail/kmcomposewin.cpp)
00062 
00063 This dialog allows to change those weights, by showing one item per:
00064  - LDAP server
00065  - KABC non-imap resource
00066  - KABC imap subresource
00067  plus one item for Distribution Lists.
00068 
00069  Maybe 'recent addresses' should be configurable too, but first it might
00070  be better to add support for them in korganizer too.
00071 
00072  The dialog also allows to disable the whole business of weighted completion 
00073  sources and use straight up alphabetical sorting instead.
00074 
00075 */
00076 
00077 using namespace KPIM;
00078 
00079 namespace KPIM {
00080 
00081 int CompletionItemList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
00082 {
00083   int w1 = ( (CompletionItem*)s1 )->completionWeight();
00084   int w2 = ( (CompletionItem*)s2 )->completionWeight();
00085   // s1 < s2 if it has a higher completion value, i.e. w1 > w2.
00086   return w2 - w1;
00087 }
00088 
00089 class LDAPCompletionItem : public CompletionItem
00090 {
00091 public:
00092   LDAPCompletionItem( LdapClient* ldapClient ) : mLdapClient( ldapClient ) {}
00093   virtual QString label() const { return i18n( "LDAP server %1" ).arg( mLdapClient->host() ); }
00094   virtual int completionWeight() const { return mLdapClient->completionWeight(); }
00095   virtual void save( CompletionOrderEditor* );
00096 protected:
00097   virtual void setCompletionWeight( int weight ) { mWeight = weight; }
00098 private:
00099   LdapClient* mLdapClient;
00100   int mWeight;
00101 };
00102 
00103 void LDAPCompletionItem::save( CompletionOrderEditor* )
00104 {
00105   KConfig config( "kabldaprc" );
00106   config.setGroup( "LDAP" );
00107   config.writeEntry( QString( "SelectedCompletionWeight%1" ).arg( mLdapClient->clientNumber() ),
00108                      mWeight );
00109   config.sync();
00110 }
00111 
00112 // A simple item saved into kpimcompletionorder (no subresources, just name/identifier/weight)
00113 class SimpleCompletionItem : public CompletionItem
00114 {
00115 public:
00116   SimpleCompletionItem( CompletionOrderEditor* editor, const QString& label, const QString& identifier )
00117     : mLabel( label ), mIdentifier( identifier ) {
00118       KConfigGroup group( editor->configFile(), "CompletionWeights" );
00119       mWeight = group.readNumEntry( mIdentifier, 60 );
00120     }
00121   virtual QString label() const { return mLabel; }
00122   virtual int completionWeight() const { return mWeight; }
00123   virtual void save( CompletionOrderEditor* );
00124 protected:
00125   virtual void setCompletionWeight( int weight ) { mWeight = weight; }
00126 private:
00127   QString mLabel, mIdentifier;
00128   int mWeight;
00129 };
00130 
00131 void SimpleCompletionItem::save( CompletionOrderEditor* editor )
00132 {
00133   // Maybe KABC::Resource could have a completionWeight setting (for readConfig/writeConfig)
00134   // But for kdelibs-3.2 compat purposes I can't do that.
00135   KConfigGroup group( editor->configFile(), "CompletionWeights" );
00136   group.writeEntry( mIdentifier, mWeight );
00137 }
00138 
00139 // An imap subresource for kabc
00140 class KABCImapSubResCompletionItem : public CompletionItem
00141 {
00142 public:
00143   KABCImapSubResCompletionItem( ResourceABC* resource, const QString& subResource )
00144     : mResource( resource ), mSubResource( subResource ), mWeight( completionWeight() ) {}
00145   virtual QString label() const {
00146     return QString( "%1 %2" ).arg( mResource->resourceName() ).arg( mResource->subresourceLabel( mSubResource ) );
00147   }
00148   virtual int completionWeight() const {
00149     return mResource->subresourceCompletionWeight( mSubResource );
00150   }
00151   virtual void setCompletionWeight( int weight ) {
00152     mWeight = weight;
00153   }
00154   virtual void save( CompletionOrderEditor* ) {
00155     mResource->setSubresourceCompletionWeight( mSubResource, mWeight );
00156   }
00157 private:
00158   ResourceABC* mResource;
00159   QString mSubResource;
00160   int mWeight;
00161 };
00162 
00164 
00165 class CompletionViewItem : public QListViewItem
00166 {
00167 public:
00168   CompletionViewItem( QListView* lv, CompletionItem* item )
00169     : QListViewItem( lv, lv->lastItem(), item->label() ), mItem( item ) {}
00170   CompletionItem* item() const { return mItem; }
00171   void setItem( CompletionItem* i ) { mItem = i; setText( 0, mItem->label() ); }
00172 
00173 private:
00174   CompletionItem* mItem;
00175 };
00176 
00177 CompletionOrderEditor::CompletionOrderEditor( KPIM::LdapSearch* ldapSearch,
00178                                               QWidget* parent, const char* name )
00179   : KDialogBase( parent, name, true, i18n("Edit Completion Order"), Ok|Cancel, Ok, true ),
00180     mConfig( "kpimcompletionorder" ), mDirty( false )
00181 {
00182   mItems.setAutoDelete( true );
00183   // The first step is to gather all the data, creating CompletionItem objects
00184   QValueList< LdapClient* > ldapClients = ldapSearch->clients();
00185   for( QValueList<LdapClient*>::const_iterator it = ldapClients.begin(); it != ldapClients.end(); ++it ) {
00186     //kdDebug(5300) << "LDAP: host " << (*it)->host() << " weight " << (*it)->completionWeight() << endl;
00187     mItems.append( new LDAPCompletionItem( *it ) );
00188   }
00189   KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00190   QPtrList<KABC::Resource> resources = addressBook->resources();
00191   for( QPtrListIterator<KABC::Resource> resit( resources ); *resit; ++resit ) {
00192     //kdDebug(5300) << "KABC Resource: " << (*resit)->className() << endl;
00193     ResourceABC* res = dynamic_cast<ResourceABC *>( *resit );
00194     if ( res ) { // IMAP KABC resource
00195       const QStringList subresources = res->subresources();
00196       for( QStringList::const_iterator it = subresources.begin(); it != subresources.end(); ++it ) {
00197         mItems.append( new KABCImapSubResCompletionItem( res, *it ) );
00198       }
00199     } else { // non-IMAP KABC resource
00200       mItems.append( new SimpleCompletionItem( this, (*resit)->resourceName(),
00201                                                (*resit)->identifier() ) );
00202     }
00203   }
00204 
00205 #if 0 // done with the normal contacts now
00206   // Add an item for distribution lists
00207   mItems.append( new SimpleCompletionItem( this, i18n( "Distribution Lists" ), "DistributionLists" ) );
00208 #endif
00209 
00210   // Now sort the items, then create the GUI
00211   mItems.sort();
00212 
00213   QVBox* page = makeVBoxMainWidget();
00214   mListViewAndButtons = new QHBox( page );
00215   mListView = new KListView( mListViewAndButtons );
00216   mListView->setSorting( -1 );
00217   mListView->addColumn( QString::null );
00218   mListView->header()->hide();
00219 
00220   for( QPtrListIterator<CompletionItem> compit( mItems ); *compit; ++compit ) {
00221     new CompletionViewItem( mListView, *compit );
00222     kdDebug(5300) << "  " << (*compit)->label() << " " << (*compit)->completionWeight() << endl;
00223   }
00224 
00225   QVBox* upDownBox = new QVBox( mListViewAndButtons );
00226   mUpButton = new QToolButton( upDownBox, "mUpButton" );
00227   mUpButton->setPixmap( BarIcon( "up", KIcon::SizeSmall ) );
00228   mUpButton->setEnabled( false ); // b/c no item is selected yet
00229   mUpButton->setFocusPolicy( StrongFocus );
00230 
00231   mDownButton = new QToolButton( upDownBox, "mDownButton" );
00232   mDownButton->setPixmap( BarIcon( "down", KIcon::SizeSmall ) );
00233   mDownButton->setEnabled( false ); // b/c no item is selected yet
00234   mDownButton->setFocusPolicy( StrongFocus );
00235 
00236   QWidget* spacer = new QWidget( upDownBox );
00237   upDownBox->setStretchFactor( spacer, 100 );
00238 
00239   mUseSortedInsteadOfWeighted = new QCheckBox( i18n( "Use alphabetical sorting" ),  page );
00240   mConfig.setGroup( "General" );
00241   const bool sorted = ( mConfig.readEntry( "CompletionOrder", "Weighted" ) == "Sorted" );
00242   mUseSortedInsteadOfWeighted->setChecked( sorted );
00243   connect ( mUseSortedInsteadOfWeighted, SIGNAL( toggled( bool ) ),
00244             this, SLOT( slotUseSortedInsteadOfWeightedToggled( bool ) ) );
00245   mListViewAndButtons->setEnabled( !sorted );
00246 
00247   connect( mListView, SIGNAL( selectionChanged( QListViewItem* ) ),
00248            SLOT( slotSelectionChanged( QListViewItem* ) ) );
00249   connect( mUpButton, SIGNAL( clicked() ), this, SLOT( slotMoveUp() ) );
00250   connect( mDownButton, SIGNAL( clicked() ), this, SLOT( slotMoveDown() ) );
00251 }
00252 
00253 CompletionOrderEditor::~CompletionOrderEditor()
00254 {
00255 }
00256 
00257 void CompletionOrderEditor::slotSelectionChanged( QListViewItem *item )
00258 {
00259   mDownButton->setEnabled( item && item->itemBelow() );
00260   mUpButton->setEnabled( item && item->itemAbove() );
00261 }
00262 
00263 static void swapItems( CompletionViewItem *one, CompletionViewItem *other )
00264 {
00265   CompletionItem* i = one->item();
00266   one->setItem( other->item() );
00267   other->setItem( i );
00268 }
00269 
00270 void CompletionOrderEditor::slotMoveUp()
00271 {
00272   CompletionViewItem *item = static_cast<CompletionViewItem *>( mListView->selectedItem() );
00273   if ( !item ) return;
00274   CompletionViewItem *above = static_cast<CompletionViewItem *>( item->itemAbove() );
00275   if ( !above ) return;
00276   swapItems( item, above );
00277   mListView->setCurrentItem( above );
00278   mListView->setSelected( above, true );
00279   mDirty = true;
00280 }
00281 
00282 void CompletionOrderEditor::slotMoveDown()
00283 {
00284   CompletionViewItem *item = static_cast<CompletionViewItem *>( mListView->selectedItem() );
00285   if ( !item ) return;
00286   CompletionViewItem *below = static_cast<CompletionViewItem *>( item->itemBelow() );
00287   if ( !below ) return;
00288   swapItems( item, below );
00289   mListView->setCurrentItem( below );
00290   mListView->setSelected( below, true );
00291   mDirty = true;
00292 }
00293 
00294 void CompletionOrderEditor::slotUseSortedInsteadOfWeightedToggled( bool on )
00295 {
00296   mListViewAndButtons->setEnabled( !on );
00297   mDirty = true;
00298 }
00299 
00300 void CompletionOrderEditor::slotOk()
00301 {
00302   if ( mDirty ) {
00303     int w = 100;
00304     for ( QListViewItem* it = mListView->firstChild(); it; it = it->nextSibling() ) {
00305       CompletionViewItem *item = static_cast<CompletionViewItem *>( it );
00306       item->item()->setCompletionWeight( w );
00307       item->item()->save( this );
00308       kdDebug(5300) << "slotOk:   " << item->item()->label() << " " << w << endl;
00309       --w;
00310     }
00311 
00312     mConfig.setGroup( "General" );
00313     const QString order = mUseSortedInsteadOfWeighted->isChecked()?"Sorted":"Weighted";
00314     mConfig.writeEntry( "CompletionOrder", order );
00315 
00316     // Emit DCOP signal
00317     // The emitter is always set to KPIM::IMAPCompletionOrder, so that the connect works
00318     // This is why we can't use k_dcop_signals here, but need to use emitDCOPSignal
00319     kapp->dcopClient()->emitDCOPSignal( "KPIM::IMAPCompletionOrder", "orderChanged()", QByteArray() );
00320   }
00321   KDialogBase::slotOk();
00322 }
00323 
00324 } // namespace KPIM
00325 
00326 #include "completionordereditor.moc"
KDE Logo
This file is part of the documentation for libkdepim Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 4 14:40:45 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003