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 <tqhbox.h>
00046 #include <tqvbox.h>
00047 #include <tqheader.h>
00048 #include <tqtoolbutton.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   Recent addresses (kmail) : 10  (see kmail/kmlineeditspell.cpp)
00059   LDAP: 50, 49, 48 etc.          (see ldapclient.cpp)
00060   KABC non-imap resources: 60    (see addresseelineedit.cpp and SimpleCompletionItem here)
00061   Distribution lists: 60         (see addresseelineedit.cpp and SimpleCompletionItem here)
00062   KABC imap resources: 80        (see kresources/imap/kabc/resourceimap.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( TQPtrCollection::Item s1, TQPtrCollection::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 TQString 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( TQString( "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 TQString& label, const TQString& identifier, int weight )
00115     : mLabel( label ), mIdentifier( identifier ) {
00116       KConfigGroup group( editor->configFile(), "CompletionWeights" );
00117       mWeight = group.readNumEntry( mIdentifier, weight );
00118     }
00119   virtual TQString 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   TQString 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 TQString& subResource )
00142     : mResource( resource ), mSubResource( subResource ), mWeight( completionWeight() ) {}
00143   virtual TQString label() const {
00144     return TQString( "%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   TQString mSubResource;
00158   int mWeight;
00159 };
00160 
00162 
00163 class CompletionViewItem : public TQListViewItem
00164 {
00165 public:
00166   CompletionViewItem( TQListView* lv, CompletionItem* item )
00167     : TQListViewItem( 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                                               TQWidget* 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   TQValueList< LdapClient* > ldapClients = ldapSearch->clients();
00183   for( TQValueList<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   TQPtrList<KABC::Resource> resources = addressBook->resources();
00189   for( TQPtrListIterator<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 TQStringList subresources = res->subresources();
00194       for( TQStringList::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(), 60 ) );
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" ), 60 );
00206 #endif
00207 
00208   mItems.append( new SimpleCompletionItem( this, i18n( "Recent Addresses" ), "Recent Addresses", 10 ) );
00209 
00210   // Now sort the items, then create the GUI
00211   mItems.sort();
00212 
00213   TQHBox* page = makeHBoxMainWidget();
00214   mListView = new KListView( page );
00215   mListView->setSorting( -1 );
00216   mListView->addColumn( TQString() );
00217   mListView->header()->hide();
00218 
00219   for( TQPtrListIterator<CompletionItem> compit( mItems ); *compit; ++compit ) {
00220     new CompletionViewItem( mListView, *compit );
00221     kdDebug(5300) << "  " << (*compit)->label() << " " << (*compit)->completionWeight() << endl;
00222   }
00223 
00224   TQVBox* upDownBox = new TQVBox( page );
00225   mUpButton = new KPushButton( upDownBox, "mUpButton" );
00226   mUpButton->setIconSet( BarIconSet( "up", KIcon::SizeSmall ) );
00227   mUpButton->setEnabled( false ); // b/c no item is selected yet
00228   mUpButton->setFocusPolicy( TQ_StrongFocus );
00229 
00230   mDownButton = new KPushButton( upDownBox, "mDownButton" );
00231   mDownButton->setIconSet( BarIconSet( "down", KIcon::SizeSmall ) );
00232   mDownButton->setEnabled( false ); // b/c no item is selected yet
00233   mDownButton->setFocusPolicy( TQ_StrongFocus );
00234 
00235   TQWidget* spacer = new TQWidget( upDownBox );
00236   upDownBox->setStretchFactor( spacer, 100 );
00237 
00238   connect( mListView, TQT_SIGNAL( selectionChanged( TQListViewItem* ) ),
00239            TQT_SLOT( slotSelectionChanged( TQListViewItem* ) ) );
00240   connect( mUpButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotMoveUp() ) );
00241   connect( mDownButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotMoveDown() ) );
00242 }
00243 
00244 CompletionOrderEditor::~CompletionOrderEditor()
00245 {
00246 }
00247 
00248 void CompletionOrderEditor::slotSelectionChanged( TQListViewItem *item )
00249 {
00250   mDownButton->setEnabled( item && item->itemBelow() );
00251   mUpButton->setEnabled( item && item->itemAbove() );
00252 }
00253 
00254 static void swapItems( CompletionViewItem *one, CompletionViewItem *other )
00255 {
00256   CompletionItem* i = one->item();
00257   one->setItem( other->item() );
00258   other->setItem( i );
00259 }
00260 
00261 void CompletionOrderEditor::slotMoveUp()
00262 {
00263   CompletionViewItem *item = static_cast<CompletionViewItem *>( mListView->selectedItem() );
00264   if ( !item ) return;
00265   CompletionViewItem *above = static_cast<CompletionViewItem *>( item->itemAbove() );
00266   if ( !above ) return;
00267   swapItems( item, above );
00268   mListView->setCurrentItem( above );
00269   mListView->setSelected( above, true );
00270   mDirty = true;
00271 }
00272 
00273 void CompletionOrderEditor::slotMoveDown()
00274 {
00275   CompletionViewItem *item = static_cast<CompletionViewItem *>( mListView->selectedItem() );
00276   if ( !item ) return;
00277   CompletionViewItem *below = static_cast<CompletionViewItem *>( item->itemBelow() );
00278   if ( !below ) return;
00279   swapItems( item, below );
00280   mListView->setCurrentItem( below );
00281   mListView->setSelected( below, true );
00282   mDirty = true;
00283 }
00284 
00285 void CompletionOrderEditor::slotOk()
00286 {
00287   if ( mDirty ) {
00288     int w = 100;
00289     for ( TQListViewItem* it = mListView->firstChild(); it; it = it->nextSibling() ) {
00290       CompletionViewItem *item = static_cast<CompletionViewItem *>( it );
00291       item->item()->setCompletionWeight( w );
00292       item->item()->save( this );
00293       kdDebug(5300) << "slotOk:   " << item->item()->label() << " " << w << endl;
00294       --w;
00295     }
00296 
00297     // Emit DCOP signal
00298     // The emitter is always set to KPIM::IMAPCompletionOrder, so that the connect works
00299     // This is why we can't use k_dcop_signals here, but need to use emitDCOPSignal
00300     kapp->dcopClient()->emitDCOPSignal( "KPIM::IMAPCompletionOrder", "orderChanged()", TQByteArray() );
00301   }
00302   KDialogBase::slotOk();
00303 }
00304 
00305 } // namespace KPIM
00306 
00307 #include "completionordereditor.moc"