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 <kabc/resource.h> 00033 #include <kdialog.h> 00034 #include <kglobal.h> 00035 #include <kiconloader.h> 00036 #include <kinputdialog.h> 00037 #include <klocale.h> 00038 #include <kmessagebox.h> 00039 #include <kresources/configdialog.h> 00040 00041 #include "core.h" 00042 00043 #include "resourceselection.h" 00044 #include <libkdepim/resourceabc.h> 00045 00046 class AddressBookWrapper : public KABC::AddressBook 00047 { 00048 public: 00049 AddressBookWrapper( KABC::AddressBook* ); 00050 00051 KRES::Manager<KABC::Resource>* getResourceManager() 00052 { 00053 return resourceManager(); 00054 } 00055 }; 00056 00057 class ResourceItem : public TQCheckListItem 00058 { 00059 public: 00060 ResourceItem( KListView *parent, KABC::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, KGlobal::iconLoader()->loadIcon( "contents", KIcon::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, KGlobal::iconLoader()->loadIcon( "contents", KIcon::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 KABC::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 KABC::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 KABC::Resource *r = item->resource(); 00198 r->load(); 00199 } 00200 00201 void ResourceSelection::saveResource() 00202 { 00203 ResourceItem *item = selectedItem(); 00204 if ( !item ) return; 00205 00206 KABC::Resource *r = item->resource(); 00207 KABC::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 KABC::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 KABC::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" ), "editdelete" ) ); 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 KABC::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<KABC::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 KListView( 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"