libkdepim

completionordereditor.cpp

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