kaddressbook

resourceselection.cpp
1 /*
2  This file is part of KAddressBook.
3  Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19  As a special exception, permission is given to link this program
20  with any edition of TQt, and distribute the resulting executable,
21  without including the source code for TQt in the source distribution.
22 */
23 
24 #include <tqlayout.h>
25 #include <tqpopupmenu.h>
26 #include <tqpushbutton.h>
27 #include <tqtimer.h>
28 #include <tqlabel.h>
29 #include <tqheader.h>
30 #include <tqtooltip.h>
31 
32 #include <tdeabc/resource.h>
33 #include <kdialog.h>
34 #include <tdeglobal.h>
35 #include <kiconloader.h>
36 #include <kinputdialog.h>
37 #include <tdelocale.h>
38 #include <tdemessagebox.h>
39 #include <tderesources/configdialog.h>
40 
41 #include "core.h"
42 
43 #include "resourceselection.h"
44 #include <libtdepim/resourceabc.h>
45 
46 class AddressBookWrapper : public TDEABC::AddressBook
47 {
48  public:
49  AddressBookWrapper( TDEABC::AddressBook* );
50 
51  KRES::Manager<TDEABC::Resource>* getResourceManager()
52  {
53  return resourceManager();
54  }
55 };
56 
57 class ResourceItem : public TQCheckListItem
58 {
59  public:
60  ResourceItem( TDEListView *parent, TDEABC::Resource *resource )
61  : TQCheckListItem( parent, resource->resourceName(), CheckBox ),
62  mResource( resource ), mChecked( false ),
63  mIsSubresource( false ), mSubItemsCreated( false ),
64  mResourceIdentifier()
65  {
66  setOn( resource->isActive() );
67  setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "contents", TDEIcon::Small ) );
68  mChecked = isOn();
69  }
70 
71  ResourceItem( KPIM::ResourceABC *resourceABC, ResourceItem* parent,
72  const TQString& resourceIdent )
73  : TQCheckListItem( parent, resourceABC->subresourceLabel( resourceIdent ), CheckBox ),
74  mResource( resourceABC ), mChecked( false ),
75  mIsSubresource( true ), mSubItemsCreated( false ),
76  mResourceIdentifier( resourceIdent )
77  {
78  KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
79  setOn( res->subresourceActive( mResourceIdentifier ) );
80  setPixmap( 0, TDEGlobal::iconLoader()->loadIcon( "contents", TDEIcon::Small ) );
81  mChecked = isOn();
82  }
83 
84  void createSubresourceItems();
85 
86  void setChecked( bool state ) {
87  mChecked = state;
88  setOn(state);
89  }
90  bool checked() const { return mChecked; }
91  TDEABC::Resource *resource() const { return mResource; }
92  TQString resourceIdentifier() const { return mResourceIdentifier; }
93  bool isSubResource() const { return mIsSubresource; }
94 
95  virtual void stateChange( bool active );
96 
97  private:
98  TDEABC::Resource * const mResource;
99  bool mChecked;
100  const bool mIsSubresource;
101  bool mSubItemsCreated;
102  const TQString mResourceIdentifier;
103 };
104 
105 // Comes from korganizer/resourceview.cpp
106 void ResourceItem::createSubresourceItems()
107 {
108  KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
109  TQStringList subresources;
110  if ( res )
111  subresources = res->subresources();
112  if ( !subresources.isEmpty() ) {
113  setOpen( true );
114  setExpandable( true );
115  // This resource has subresources
116  TQStringList::ConstIterator it;
117  for ( it = subresources.begin(); it != subresources.end(); ++it ) {
118  (void)new ResourceItem( res, this, *it );
119  }
120  }
121  mSubItemsCreated = true;
122 }
123 
124 void ResourceItem::stateChange( bool active )
125 {
126  //kdDebug(5720) << k_funcinfo << this << " " << text( 0 ) << " active=" << active << endl;
127  if ( active && !mIsSubresource ) {
128  if ( !mSubItemsCreated )
129  createSubresourceItems();
130  }
131 
132  setOpen( active && childCount() > 0 );
133 }
134 
136 
137 ResourceSelection::ResourceSelection( KAB::Core *core, TQWidget *parent, const char *name )
138  : KAB::ExtensionWidget( core, parent, name ), mManager( 0 )
139 {
140  initGUI();
141 
142  AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
143  mManager = wrapper->getResourceManager();
144 
145  connect( mAddButton, TQ_SIGNAL( clicked() ), TQ_SLOT( add() ) );
146  connect( mEditButton, TQ_SIGNAL( clicked() ), TQ_SLOT( edit() ) );
147  connect( mRemoveButton, TQ_SIGNAL( clicked() ), TQ_SLOT( remove() ) );
148 
149  connect( mListView, TQ_SIGNAL( clicked( TQListViewItem* ) ),
150  TQ_SLOT( currentChanged( TQListViewItem* ) ) );
151 
152  connect( mListView, TQ_SIGNAL( contextMenuRequested ( TQListViewItem *,
153  const TQPoint &, int ) ),
154  TQ_SLOT( contextMenuRequested( TQListViewItem *, const TQPoint &,
155  int ) ) );
156 
157  TQTimer::singleShot( 0, this, TQ_SLOT( updateView() ) );
158 }
159 
160 ResourceSelection::~ResourceSelection()
161 {
162 }
163 
164 void ResourceSelection::contextMenuRequested ( TQListViewItem *i,
165  const TQPoint &pos, int )
166 {
167  ResourceItem *item = static_cast<ResourceItem *>( i );
168 
169  TQPopupMenu *menu = new TQPopupMenu( this );
170  connect( menu, TQ_SIGNAL( aboutToHide() ), menu, TQ_SLOT( deleteLater() ) );
171  if ( item ) {
172  int reloadId = menu->insertItem( i18n("Re&load"), this,
173  TQ_SLOT( reloadResource() ) );
174  menu->setItemEnabled( reloadId, item->resource()->isActive() );
175  int saveId = menu->insertItem( i18n("&Save"), this,
176  TQ_SLOT( saveResource() ) );
177  menu->setItemEnabled( saveId, item->resource()->isActive() );
178  menu->insertSeparator();
179 
180 // menu->insertItem( i18n("Show &Info"), this, TQ_SLOT( showInfo() ) );
181 
182  menu->insertItem( i18n("&Edit..."), this, TQ_SLOT( edit() ) );
183  menu->insertItem( i18n("&Remove"), this, TQ_SLOT( remove() ) );
184 
185  menu->insertSeparator();
186  }
187  menu->insertItem( i18n("&Add..."), this, TQ_SLOT( add() ) );
188 
189  menu->popup( pos );
190 }
191 
192 void ResourceSelection::reloadResource()
193 {
194  ResourceItem *item = selectedItem();
195  if ( !item ) return;
196 
197  TDEABC::Resource *r = item->resource();
198  r->load();
199 }
200 
201 void ResourceSelection::saveResource()
202 {
203  ResourceItem *item = selectedItem();
204  if ( !item ) return;
205 
206  TDEABC::Resource *r = item->resource();
207  TDEABC::Ticket *ticket = core()->addressBook()->requestSaveTicket( r );
208  if ( ticket ) {
209  r->save( ticket );
210  }
211 }
212 
213 void ResourceSelection::showInfo()
214 {
215  ResourceItem *item = selectedItem();
216  if ( !item ) return;
217 
218 // TQString txt = "<qt>" + item->resource()->infoText() + "</qt>";
219 // KMessageBox::information( this, txt );
220 }
221 
222 TQString ResourceSelection::title() const
223 {
224  return i18n( "Address Books" );
225 }
226 
227 TQString ResourceSelection::identifier() const
228 {
229  return "resourceselection";
230 }
231 
232 void ResourceSelection::add()
233 {
234  TQStringList types = mManager->resourceTypeNames();
235  TQStringList descs = mManager->resourceTypeDescriptions();
236 
237  bool ok = false;
238  TQString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
239  i18n( "Please select type of the new address book:" ),
240  descs, 0, false, &ok, this );
241  if ( !ok )
242  return;
243 
244  TQString type = types[ descs.findIndex( desc ) ];
245 
246  // Create new resource
247  TDEABC::Resource *resource = mManager->createResource( type );
248  if ( !resource ) {
249  KMessageBox::error( this, i18n("<qt>Unable to create an address book of type <b>%1</b>.</qt>")
250  .arg( type ) );
251  return;
252  }
253 
254  resource->setAddressBook(core()->addressBook());
255 
256  KRES::ConfigDialog dlg( this, TQString( "contact" ), resource );
257 
258  if ( dlg.exec() ) {
259  core()->addressBook()->addResource( resource );
260  resource->asyncLoad();
261 
262  mLastResource = resource->identifier();
263  updateView();
264  currentChanged(mListView->currentItem() );
265  } else {
266  delete resource;
267  resource = 0;
268  }
269 }
270 
271 void ResourceSelection::edit()
272 {
273  ResourceItem *item = selectedItem();
274  if ( !item )
275  return;
276 
277  // view items can change during "edit", e.g. sub resources being removed ->
278  // sub resource item removed
279  // thus keep their data rather than their pointer
280  TDEABC::Resource *resource = item->resource();
281 
282  KRES::ConfigDialog dlg( this, TQString( "contact" ), resource );
283 
284  if ( dlg.exec() ) {
285  mManager->change( resource );
286  resource->asyncLoad();
287 
288  mLastResource = resource->identifier();
289  updateView();
290  }
291 }
292 
293 void ResourceSelection::remove()
294 {
295  ResourceItem *item = selectedItem();
296  if ( !item )
297  return;
298 
299  int result = KMessageBox::warningContinueCancel( this,
300  i18n( "<qt>Do you really want to remove the address book <b>%1</b>?</qt>" )
301  .arg( item->resource()->resourceName() ), "",
302  KGuiItem( i18n( "&Remove" ), "edit-delete" ) );
303  if ( result == KMessageBox::Cancel )
304  return;
305 
306  mLastResource = item->resource()->identifier();
307 
308  core()->addressBook()->removeResource( item->resource() );
309  core()->addressBook()->emitAddressBookChanged();
310 
311  updateView();
312  currentChanged(mListView->currentItem() );
313 }
314 
315 void ResourceSelection::currentChanged( TQListViewItem *item )
316 {
317  ResourceItem *resItem = static_cast<ResourceItem*>( item );
318  bool state = (resItem && !resItem->isSubResource() );
319 
320  mEditButton->setEnabled( state );
321  mRemoveButton->setEnabled( state );
322 
323  if ( !resItem )
324  return;
325 
326  TDEABC::Resource *resource = resItem->resource();
327 
328  if ( resItem->checked() != resItem->isOn() ) {
329  resItem->setChecked( resItem->isOn() );
330  if ( resItem->isSubResource() ) {
331  KPIM::ResourceABC *res = dynamic_cast<KPIM::ResourceABC *>( resource );
332  res->setSubresourceActive( resItem->resourceIdentifier(), resItem->isOn() );
333  mManager->change( resource );
334  } else {
335  resource->setActive( resItem->isOn() );
336  mManager->change( resource );
337 
338  if ( resItem->checked() ) {
339  if ( !resource->addressBook() )
340  resource->setAddressBook( core()->addressBook() );
341 
342  if ( !resource->isOpen() )
343  resource->open();
344 
345  resource->asyncLoad();
346  } else {
347  resource->close();
348  }
349  }
350 
351  mLastResource = resource->identifier();
352  core()->addressBook()->emitAddressBookChanged();
353  //updateView();
354  }
355 }
356 
357 void ResourceSelection::updateView()
358 {
359  if ( !mManager )
360  return;
361 
362  mListView->clear();
363 
364  KRES::Manager<TDEABC::Resource>::Iterator it;
365  for ( it = mManager->begin(); it != mManager->end(); ++it ) {
366 
367  ResourceItem *item = new ResourceItem( mListView, *it );
368  KPIM::ResourceABC* resource = dynamic_cast<KPIM::ResourceABC *>( *it );
369  if ( resource ) {
370  disconnect( resource, 0, this, 0 );
371  connect( resource, TQ_SIGNAL( signalSubresourceAdded( KPIM::ResourceABC *,
372  const TQString &, const TQString & ) ),
373  TQ_SLOT( slotSubresourceAdded( KPIM::ResourceABC *,
374  const TQString &, const TQString & ) ) );
375 
376  connect( resource, TQ_SIGNAL( signalSubresourceRemoved( KPIM::ResourceABC *,
377  const TQString &, const TQString & ) ),
378  TQ_SLOT( slotSubresourceRemoved( KPIM::ResourceABC *,
379  const TQString &, const TQString & ) ) );
380 
381  connect( resource, TQ_SIGNAL( signalSubresourceChanged( KPIM::ResourceABC *,
382  const TQString &, const TQString & ) ),
383  TQ_SLOT( slotSubresourceChanged( KPIM::ResourceABC *,
384  const TQString &, const TQString & ) ) );
385 
386  //connect( resource, TQ_SIGNAL( resourceSaved( KPIM::ResourceABC * ) ),
387  // TQ_SLOT( closeResource( KPIM::ResourceABC * ) ) );
388  item->createSubresourceItems();
389  }
390  }
391 
392  TQListViewItemIterator itemIt( mListView );
393  while ( itemIt.current() ) {
394  ResourceItem *item = static_cast<ResourceItem*>( itemIt.current() );
395  if ( item->resource()->identifier() == mLastResource ) {
396  mListView->setSelected( item, true );
397  mListView->ensureItemVisible( item );
398  break;
399  }
400  ++itemIt;
401  }
402 
403  core()->addressBook()->emitAddressBookChanged();
404 }
405 
406 
407 // Add a new entry
408 void ResourceSelection::slotSubresourceAdded( KPIM::ResourceABC *resource,
409  const TQString& /*type*/,
410  const TQString& subResource )
411 {
412  kdDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
413  TQListViewItem *i = mListView->findItem( resource->resourceName(), 0 );
414  if ( !i )
415  // Not found
416  return;
417 
418  ResourceItem *item = static_cast<ResourceItem *>( i );
419  // Make sure all other sub items have already been created
420  item->createSubresourceItems();
421 
422  // check if we already have an item for it
423  if ( !findSubResourceItem( resource, subResource ) ) {
424  (void)new ResourceItem( resource, item, subResource );
425  }
426 }
427 
428 // Remove an entry
429 void ResourceSelection::slotSubresourceRemoved( KPIM::ResourceABC* resource,
430  const TQString& /*type*/,
431  const TQString& subResource )
432 {
433  ResourceItem *item = findSubResourceItem( resource, subResource );
434  delete item;
435  core()->addressBook()->emitAddressBookChanged();
436  updateView();
437 }
438 
439 // change an entry
440 void ResourceSelection::slotSubresourceChanged( KPIM::ResourceABC* resource,
441  const TQString& type,
442  const TQString& subResource )
443 {
444  kdDebug(5720) << resource->resourceName() << subResource;
445 
446  ResourceItem *item = findSubResourceItem( resource, subResource );
447  if ( item == 0 ) {
448  kdWarning(5720) << "Changed before it was added?";
449  slotSubresourceAdded( resource, type, subResource );
450  return;
451  }
452 
453  item->setText( 0, resource->subresourceLabel( subResource ) );
454  item->setChecked( resource->subresourceActive( subResource ) ? true : false );
455  // TODO
456  //emitResourcesChanged();
457  core()->addressBook()->emitAddressBookChanged();
458  updateView();
459 }
460 
461 ResourceItem* ResourceSelection::selectedItem() const
462 {
463  return static_cast<ResourceItem*>( mListView->selectedItem() );
464 }
465 
466 ResourceItem* ResourceSelection::findSubResourceItem( KPIM::ResourceABC *resource,
467  const TQString &subResource )
468 {
469  TQListViewItemIterator parentIt( mListView );
470  for ( ; *parentIt; ++parentIt ) {
471  if ( static_cast<ResourceItem*>(*parentIt)->resource() != resource )
472  continue;
473 
474  TQListViewItemIterator childIt( *parentIt );
475  for ( ; *childIt; ++childIt ) {
476  ResourceItem *item = static_cast<ResourceItem*>(*childIt);
477  if ( item->resourceIdentifier() == subResource )
478  return item;
479  }
480  }
481 
482  return 0;
483 }
484 
485 void ResourceSelection::initGUI()
486 {
487  TQBoxLayout *topLayout = new TQVBoxLayout( this );
488  topLayout->setSpacing( KDialog::spacingHint() );
489 
490  TQBoxLayout *buttonLayout = new TQHBoxLayout();
491  buttonLayout->setSpacing( KDialog::spacingHint() );
492  topLayout->addLayout( buttonLayout );
493 
494  TQLabel *abLabel = new TQLabel( i18n( "Address Books" ), this );
495  buttonLayout->addWidget( abLabel );
496  buttonLayout->addStretch( 1 );
497 
498  mAddButton = new TQPushButton( this );
499  mAddButton->setIconSet( SmallIconSet( "add" ) );
500  TQToolTip::add( mAddButton, i18n( "Add addressbook" ) );
501  buttonLayout->addWidget( mAddButton );
502  mEditButton = new TQPushButton( this );
503  mEditButton->setIconSet( SmallIconSet( "edit" ) );
504  mEditButton->setEnabled( false );
505  TQToolTip::add( mEditButton, i18n( "Edit addressbook settings" ) );
506  buttonLayout->addWidget( mEditButton );
507  mRemoveButton = new TQPushButton( this );
508  mRemoveButton->setIconSet( SmallIconSet( "remove" ) );
509  mRemoveButton->setEnabled( false );
510  TQToolTip::add( mRemoveButton, i18n( "Remove addressbook" ) );
511  buttonLayout->addWidget( mRemoveButton );
512 
513  mListView = new TDEListView( this );
514  mListView->header()->hide();
515  mListView->addColumn( i18n( "Address Books" ) );
516  mListView->setFullWidth( true );
517  topLayout->addWidget( mListView );
518 }
519 
520 class ResourceSelectionFactory : public KAB::ExtensionFactory
521 {
522  public:
523  KAB::ExtensionWidget *extension( KAB::Core *core, TQWidget *parent, const char *name )
524  {
525  return new ResourceSelection( core, parent, name );
526  }
527 
528  TQString identifier() const
529  {
530  return "resourceselection";
531  }
532 };
533 
534 extern "C" {
535  void *init_libkaddrbk_resourceselection()
536  {
537  return ( new ResourceSelectionFactory );
538  }
539 }
540 
541 #include "resourceselection.moc"