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
46class 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
57class 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
106void 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
124void 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
137ResourceSelection::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
160ResourceSelection::~ResourceSelection()
161{
162}
163
164void 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
192void ResourceSelection::reloadResource()
193{
194 ResourceItem *item = selectedItem();
195 if ( !item ) return;
196
197 TDEABC::Resource *r = item->resource();
198 r->load();
199}
200
201void 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
213void 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
222TQString ResourceSelection::title() const
223{
224 return i18n( "Address Books" );
225}
226
227TQString ResourceSelection::identifier() const
228{
229 return "resourceselection";
230}
231
232void 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
271void 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
293void 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
315void 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
357void 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
408void 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
429void 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
440void 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
461ResourceItem* ResourceSelection::selectedItem() const
462{
463 return static_cast<ResourceItem*>( mListView->selectedItem() );
464}
465
466ResourceItem* 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
485void 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
520class 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
534extern "C" {
535 void *init_libkaddrbk_resourceselection()
536 {
537 return ( new ResourceSelectionFactory );
538 }
539}
540
541#include "resourceselection.moc"