kaddressbook

resourceselection.cpp

00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of TQt, and distribute the resulting executable,
00021     without including the source code for TQt in the source distribution.
00022 */
00023 
00024 #include <tqlayout.h>
00025 #include <tqpopupmenu.h>
00026 #include <tqpushbutton.h>
00027 #include <tqtimer.h>
00028 #include <tqlabel.h>
00029 #include <tqheader.h>
00030 #include <tqtooltip.h>
00031 
00032 #include <tdeabc/resource.h>
00033 #include <kdialog.h>
00034 #include <tdeglobal.h>
00035 #include <kiconloader.h>
00036 #include <kinputdialog.h>
00037 #include <tdelocale.h>
00038 #include <tdemessagebox.h>
00039 #include <tderesources/configdialog.h>
00040 
00041 #include "core.h"
00042 
00043 #include "resourceselection.h"
00044 #include <libtdepim/resourceabc.h>
00045 
00046 class AddressBookWrapper : public TDEABC::AddressBook
00047 {
00048   public:
00049     AddressBookWrapper( TDEABC::AddressBook* );
00050 
00051     KRES::Manager<TDEABC::Resource>* getResourceManager()
00052     {
00053       return resourceManager();
00054     }
00055 };
00056 
00057 class ResourceItem : public TQCheckListItem
00058 {
00059   public:
00060     ResourceItem( TDEListView *parent, TDEABC::Resource *resource )
00061       : TQCheckListItem( parent, resource->resourceName(), CheckBox ),
00062         mResource( resource ), mChecked( false ),
00063         mIsSubresource( false ), mSubItemsCreated( false ),
00064         mResourceIdentifier()
00065     {
00066       setOn( resource->isActive() );
00067       setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "contents", TDEIcon::Small ) );
00068       mChecked = isOn();
00069     }
00070 
00071     ResourceItem( KPIM::ResourceABC *resourceABC, ResourceItem* parent,
00072                   const TQString& resourceIdent )
00073       : TQCheckListItem( parent, resourceABC->subresourceLabel( resourceIdent ), CheckBox ),
00074         mResource( resourceABC ), mChecked( false ),
00075         mIsSubresource( true ), mSubItemsCreated( false ),
00076         mResourceIdentifier( resourceIdent )
00077     {
00078       KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
00079       setOn( res->subresourceActive( mResourceIdentifier ) );
00080       setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "contents", TDEIcon::Small ) );
00081       mChecked = isOn();
00082     }
00083 
00084     void createSubresourceItems();
00085 
00086     void setChecked( bool state ) {
00087         mChecked = state;
00088         setOn(state);
00089     }
00090     bool checked() const { return mChecked; }
00091     TDEABC::Resource *resource() const { return mResource; }
00092     TQString resourceIdentifier() const { return mResourceIdentifier; }
00093     bool isSubResource() const { return mIsSubresource; }
00094 
00095     virtual void stateChange( bool active );
00096 
00097   private:
00098     TDEABC::Resource * const mResource;
00099     bool mChecked;
00100     const bool mIsSubresource;
00101     bool mSubItemsCreated;
00102     const TQString mResourceIdentifier;
00103 };
00104 
00105 // Comes from korganizer/resourceview.cpp
00106 void ResourceItem::createSubresourceItems()
00107 {
00108   KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
00109   TQStringList subresources;
00110   if ( res )
00111     subresources = res->subresources();
00112   if ( !subresources.isEmpty() ) {
00113     setOpen( true );
00114     setExpandable( true );
00115     // This resource has subresources
00116     TQStringList::ConstIterator it;
00117     for ( it = subresources.begin(); it != subresources.end(); ++it ) {
00118       (void)new ResourceItem( res, this, *it );
00119     }
00120   }
00121   mSubItemsCreated = true;
00122 }
00123 
00124 void ResourceItem::stateChange( bool active )
00125 {
00126   //kdDebug(5720) << k_funcinfo << this << " " << text( 0 ) << " active=" << active << endl;
00127   if ( active && !mIsSubresource ) {
00128     if ( !mSubItemsCreated )
00129       createSubresourceItems();
00130   }
00131 
00132   setOpen( active && childCount() > 0 );
00133 }
00134 
00136 
00137 ResourceSelection::ResourceSelection( KAB::Core *core, TQWidget *parent, const char *name )
00138   : KAB::ExtensionWidget( core, parent, name ), mManager( 0 )
00139 {
00140   initGUI();
00141 
00142   AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
00143   mManager = wrapper->getResourceManager();
00144 
00145   connect( mAddButton, TQT_SIGNAL( clicked() ), TQT_SLOT( add() ) );
00146   connect( mEditButton, TQT_SIGNAL( clicked() ), TQT_SLOT( edit() ) );
00147   connect( mRemoveButton, TQT_SIGNAL( clicked() ), TQT_SLOT( remove() ) );
00148 
00149   connect( mListView, TQT_SIGNAL( clicked( TQListViewItem* ) ),
00150            TQT_SLOT( currentChanged( TQListViewItem* ) ) );
00151 
00152   connect( mListView, TQT_SIGNAL( contextMenuRequested ( TQListViewItem *,
00153                                                      const TQPoint &, int ) ),
00154            TQT_SLOT( contextMenuRequested( TQListViewItem *, const TQPoint &,
00155                                        int ) ) );
00156 
00157   TQTimer::singleShot( 0, this, TQT_SLOT( updateView() ) );
00158 }
00159 
00160 ResourceSelection::~ResourceSelection()
00161 {
00162 }
00163 
00164 void ResourceSelection::contextMenuRequested ( TQListViewItem *i,
00165                                           const TQPoint &pos, int )
00166 {
00167   ResourceItem *item = static_cast<ResourceItem *>( i );
00168 
00169   TQPopupMenu *menu = new TQPopupMenu( this );
00170   connect( menu, TQT_SIGNAL( aboutToHide() ), menu, TQT_SLOT( deleteLater() ) );
00171   if ( item ) {
00172     int reloadId = menu->insertItem( i18n("Re&load"), this,
00173                                      TQT_SLOT( reloadResource() ) );
00174     menu->setItemEnabled( reloadId, item->resource()->isActive() );
00175     int saveId = menu->insertItem( i18n("&Save"), this,
00176                                    TQT_SLOT( saveResource() ) );
00177     menu->setItemEnabled( saveId, item->resource()->isActive() );
00178     menu->insertSeparator();
00179 
00180 //     menu->insertItem( i18n("Show &Info"), this, TQT_SLOT( showInfo() ) );
00181 
00182     menu->insertItem( i18n("&Edit..."), this, TQT_SLOT( edit() ) );
00183     menu->insertItem( i18n("&Remove"), this, TQT_SLOT( remove() ) );
00184 
00185     menu->insertSeparator();
00186  }
00187   menu->insertItem( i18n("&Add..."), this, TQT_SLOT( add() ) );
00188 
00189   menu->popup( pos );
00190 }
00191 
00192 void ResourceSelection::reloadResource()
00193 {
00194   ResourceItem *item = selectedItem();
00195   if ( !item ) return;
00196 
00197   TDEABC::Resource *r = item->resource();
00198   r->load();
00199 }
00200 
00201 void ResourceSelection::saveResource()
00202 {
00203   ResourceItem *item = selectedItem();
00204   if ( !item ) return;
00205 
00206   TDEABC::Resource *r = item->resource();
00207   TDEABC::Ticket *ticket = core()->addressBook()->requestSaveTicket( r );
00208   if ( ticket ) {
00209       r->save( ticket );
00210   }
00211 }
00212 
00213 void ResourceSelection::showInfo()
00214 {
00215   ResourceItem *item = selectedItem();
00216   if ( !item ) return;
00217 
00218 //   TQString txt = "<qt>" + item->resource()->infoText() + "</qt>";
00219 //   KMessageBox::information( this, txt );
00220 }
00221 
00222 TQString ResourceSelection::title() const
00223 {
00224   return i18n( "Address Books" );
00225 }
00226 
00227 TQString ResourceSelection::identifier() const
00228 {
00229   return "resourceselection";
00230 }
00231 
00232 void ResourceSelection::add()
00233 {
00234   TQStringList types = mManager->resourceTypeNames();
00235   TQStringList descs = mManager->resourceTypeDescriptions();
00236 
00237   bool ok = false;
00238   TQString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
00239                                         i18n( "Please select type of the new address book:" ),
00240                                         descs, 0, false, &ok, this );
00241   if ( !ok )
00242     return;
00243 
00244   TQString type = types[ descs.findIndex( desc ) ];
00245 
00246   // Create new resource
00247   TDEABC::Resource *resource = mManager->createResource( type );
00248   if ( !resource ) {
00249     KMessageBox::error( this, i18n("<qt>Unable to create an address book of type <b>%1</b>.</qt>")
00250                               .arg( type ) );
00251     return;
00252   }
00253 
00254   resource->setAddressBook(core()->addressBook());
00255 
00256   KRES::ConfigDialog dlg( this, TQString( "contact" ), resource );
00257 
00258   if ( dlg.exec() ) {
00259     core()->addressBook()->addResource( resource );
00260     resource->asyncLoad();
00261 
00262     mLastResource = resource->identifier();
00263     updateView();
00264     currentChanged(mListView->currentItem() );
00265   } else {
00266     delete resource;
00267     resource = 0;
00268   }
00269 }
00270 
00271 void ResourceSelection::edit()
00272 {
00273   ResourceItem *item = selectedItem();
00274   if ( !item )
00275     return;
00276 
00277   // view items can change during "edit", e.g. sub resources being removed ->
00278   // sub resource item removed
00279   // thus keep their data rather than their pointer
00280   TDEABC::Resource *resource = item->resource();
00281 
00282   KRES::ConfigDialog dlg( this, TQString( "contact" ), resource );
00283 
00284   if ( dlg.exec() ) {
00285     mManager->change( resource );
00286     resource->asyncLoad();
00287 
00288     mLastResource = resource->identifier();
00289     updateView();
00290   }
00291 }
00292 
00293 void ResourceSelection::remove()
00294 {
00295   ResourceItem *item = selectedItem();
00296   if ( !item )
00297     return;
00298 
00299   int result = KMessageBox::warningContinueCancel( this,
00300         i18n( "<qt>Do you really want to remove the address book <b>%1</b>?</qt>" )
00301         .arg( item->resource()->resourceName() ), "",
00302         KGuiItem( i18n( "&Remove" ), "edit-delete" ) );
00303   if ( result == KMessageBox::Cancel )
00304     return;
00305 
00306   mLastResource = item->resource()->identifier();
00307 
00308   core()->addressBook()->removeResource( item->resource() );
00309   core()->addressBook()->emitAddressBookChanged();
00310 
00311   updateView();
00312   currentChanged(mListView->currentItem() );
00313 }
00314 
00315 void ResourceSelection::currentChanged( TQListViewItem *item )
00316 {
00317   ResourceItem *resItem = static_cast<ResourceItem*>( item );
00318   bool state = (resItem && !resItem->isSubResource() );
00319 
00320   mEditButton->setEnabled( state );
00321   mRemoveButton->setEnabled( state );
00322 
00323   if ( !resItem )
00324     return;
00325 
00326   TDEABC::Resource *resource = resItem->resource();
00327 
00328   if ( resItem->checked() != resItem->isOn() ) {
00329     resItem->setChecked( resItem->isOn() );
00330     if ( resItem->isSubResource() ) {
00331       KPIM::ResourceABC *res = dynamic_cast<KPIM::ResourceABC *>( resource );
00332       res->setSubresourceActive( resItem->resourceIdentifier(), resItem->isOn() );
00333       mManager->change( resource );
00334     } else {
00335       resource->setActive( resItem->isOn() );
00336       mManager->change( resource );
00337 
00338       if ( resItem->checked() ) {
00339         if ( !resource->addressBook() )
00340           resource->setAddressBook( core()->addressBook() );
00341 
00342         if ( !resource->isOpen() )
00343           resource->open();
00344 
00345         resource->asyncLoad();
00346       } else {
00347         resource->close();
00348       }
00349     }
00350 
00351     mLastResource = resource->identifier();
00352     core()->addressBook()->emitAddressBookChanged();
00353     //updateView();
00354   }
00355 }
00356 
00357 void ResourceSelection::updateView()
00358 {
00359   if ( !mManager )
00360     return;
00361 
00362   mListView->clear();
00363 
00364   KRES::Manager<TDEABC::Resource>::Iterator it;
00365   for ( it = mManager->begin(); it != mManager->end(); ++it ) {
00366 
00367     ResourceItem *item = new ResourceItem( mListView, *it );
00368     KPIM::ResourceABC* resource = dynamic_cast<KPIM::ResourceABC *>( *it );
00369     if ( resource ) {
00370       disconnect( resource, 0, this, 0 );
00371       connect( resource, TQT_SIGNAL( signalSubresourceAdded( KPIM::ResourceABC *,
00372                                                          const TQString &, const TQString & ) ),
00373                TQT_SLOT( slotSubresourceAdded( KPIM::ResourceABC *,
00374                                            const TQString &, const TQString & ) ) );
00375 
00376       connect( resource, TQT_SIGNAL( signalSubresourceRemoved( KPIM::ResourceABC *,
00377                                                            const TQString &, const TQString & ) ),
00378                TQT_SLOT( slotSubresourceRemoved( KPIM::ResourceABC *,
00379                                              const TQString &, const TQString & ) ) );
00380 
00381       connect( resource, TQT_SIGNAL( signalSubresourceChanged( KPIM::ResourceABC *,
00382                                                            const TQString &, const TQString & ) ),
00383                TQT_SLOT( slotSubresourceChanged( KPIM::ResourceABC *,
00384                                              const TQString &, const TQString & ) ) );
00385 
00386       //connect( resource, TQT_SIGNAL( resourceSaved( KPIM::ResourceABC * ) ),
00387       //         TQT_SLOT( closeResource( KPIM::ResourceABC * ) ) );
00388       item->createSubresourceItems();
00389     }
00390   }
00391 
00392   TQListViewItemIterator itemIt( mListView );
00393   while ( itemIt.current() ) {
00394     ResourceItem *item = static_cast<ResourceItem*>( itemIt.current() );
00395     if ( item->resource()->identifier() == mLastResource ) {
00396       mListView->setSelected( item, true );
00397       mListView->ensureItemVisible( item );
00398       break;
00399     }
00400     ++itemIt;
00401   }
00402 
00403   core()->addressBook()->emitAddressBookChanged();
00404 }
00405 
00406 
00407 // Add a new entry
00408 void ResourceSelection::slotSubresourceAdded( KPIM::ResourceABC *resource,
00409                                               const TQString& /*type*/,
00410                                               const TQString& subResource )
00411 {
00412   kdDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
00413   TQListViewItem *i = mListView->findItem( resource->resourceName(), 0 );
00414   if ( !i )
00415     // Not found
00416     return;
00417 
00418   ResourceItem *item = static_cast<ResourceItem *>( i );
00419   // Make sure all other sub items have already been created
00420   item->createSubresourceItems();
00421 
00422   // check if we already have an item for it
00423   if ( !findSubResourceItem( resource, subResource ) ) {
00424       (void)new ResourceItem( resource, item, subResource );
00425   }
00426 }
00427 
00428 // Remove an entry
00429 void ResourceSelection::slotSubresourceRemoved( KPIM::ResourceABC* resource,
00430                                                 const TQString& /*type*/,
00431                                                 const TQString& subResource )
00432 {
00433   ResourceItem *item = findSubResourceItem( resource, subResource );
00434   delete item;
00435   core()->addressBook()->emitAddressBookChanged();
00436   updateView();
00437 }
00438 
00439 // change an entry
00440 void ResourceSelection::slotSubresourceChanged( KPIM::ResourceABC* resource,
00441                                                 const TQString& type,
00442                                                 const TQString& subResource )
00443 {
00444   kdDebug(5720) << resource->resourceName() << subResource;
00445 
00446   ResourceItem *item = findSubResourceItem( resource, subResource );
00447   if ( item == 0 ) {
00448       kdWarning(5720) << "Changed before it was added?";
00449       slotSubresourceAdded( resource, type, subResource );
00450       return;
00451   }
00452 
00453   item->setText( 0, resource->subresourceLabel( subResource ) );
00454   item->setChecked( resource->subresourceActive( subResource ) ? true : false );
00455   // TODO
00456   //emitResourcesChanged();
00457   core()->addressBook()->emitAddressBookChanged();
00458   updateView();
00459 }
00460 
00461 ResourceItem* ResourceSelection::selectedItem() const
00462 {
00463   return static_cast<ResourceItem*>( mListView->selectedItem() );
00464 }
00465 
00466 ResourceItem* ResourceSelection::findSubResourceItem( KPIM::ResourceABC *resource,
00467                                                 const TQString &subResource )
00468 {
00469     TQListViewItemIterator parentIt( mListView );
00470     for ( ; *parentIt; ++parentIt ) {
00471         if ( static_cast<ResourceItem*>(*parentIt)->resource() != resource )
00472             continue;
00473 
00474         TQListViewItemIterator childIt( *parentIt );
00475         for ( ; *childIt; ++childIt ) {
00476             ResourceItem *item = static_cast<ResourceItem*>(*childIt);
00477             if ( item->resourceIdentifier() == subResource )
00478                 return item;
00479         }
00480     }
00481 
00482     return 0;
00483 }
00484 
00485 void ResourceSelection::initGUI()
00486 {
00487   TQBoxLayout *topLayout = new TQVBoxLayout( this );
00488   topLayout->setSpacing( KDialog::spacingHint() );
00489 
00490   TQBoxLayout *buttonLayout = new TQHBoxLayout();
00491   buttonLayout->setSpacing( KDialog::spacingHint() );
00492   topLayout->addLayout( buttonLayout );
00493 
00494   TQLabel *abLabel = new TQLabel( i18n( "Address Books" ), this );
00495   buttonLayout->addWidget( abLabel );
00496   buttonLayout->addStretch( 1 );
00497 
00498   mAddButton = new TQPushButton( this );
00499   mAddButton->setIconSet( SmallIconSet( "add" ) );
00500   TQToolTip::add( mAddButton, i18n( "Add addressbook" ) );
00501   buttonLayout->addWidget( mAddButton );
00502   mEditButton = new TQPushButton( this );
00503   mEditButton->setIconSet( SmallIconSet( "edit" ) );
00504   mEditButton->setEnabled( false );
00505   TQToolTip::add( mEditButton, i18n( "Edit addressbook settings" ) );
00506   buttonLayout->addWidget( mEditButton );
00507   mRemoveButton = new TQPushButton( this );
00508   mRemoveButton->setIconSet( SmallIconSet( "remove" ) );
00509   mRemoveButton->setEnabled( false );
00510   TQToolTip::add( mRemoveButton, i18n( "Remove addressbook" ) );
00511   buttonLayout->addWidget( mRemoveButton );
00512 
00513   mListView = new TDEListView( this );
00514   mListView->header()->hide();
00515   mListView->addColumn( i18n( "Address Books" ) );
00516   mListView->setFullWidth( true );
00517   topLayout->addWidget( mListView );
00518 }
00519 
00520 class ResourceSelectionFactory : public KAB::ExtensionFactory
00521 {
00522   public:
00523     KAB::ExtensionWidget *extension( KAB::Core *core, TQWidget *parent, const char *name )
00524     {
00525       return new ResourceSelection( core, parent, name );
00526     }
00527 
00528     TQString identifier() const
00529     {
00530       return "resourceselection";
00531     }
00532 };
00533 
00534 extern "C" {
00535   void *init_libkaddrbk_resourceselection()
00536   {
00537     return ( new ResourceSelectionFactory );
00538   }
00539 }
00540 
00541 #include "resourceselection.moc"