kaddressbook

distributionlistwidget.cpp
1 /*
2  This file is part of KAddressBook.
3  Copyright (c) 2002 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  As a special exception, permission is given to link this program
19  with any edition of TQt, and distribute the resulting executable,
20  without including the source code for TQt in the source distribution.
21 */
22 
23 #include "distributionlistwidget.h"
24 
25 #include <tqbuttongroup.h>
26 #include <tqcombobox.h>
27 #include <tqlabel.h>
28 #include <tqlayout.h>
29 #include <tqlistview.h>
30 #include <tqpushbutton.h>
31 #include <tqradiobutton.h>
32 
33 #include <tdeaccelmanager.h>
34 #include <tdeconfig.h>
35 #include <kdebug.h>
36 #include <tdeglobal.h>
37 #include <kinputdialog.h>
38 #include <tdelocale.h>
39 #include <tdemessagebox.h>
40 
41 #include <tdeabc/addresseedialog.h>
42 #ifdef TDEPIM_NEW_DISTRLISTS
43 #include <libtdepim/distributionlist.h>
44 typedef KPIM::DistributionList DistributionList;
45 #else
46 #include <tdeabc/distributionlist.h>
47 typedef TDEABC::DistributionList DistributionList;
48 #endif
49 #include <tdeabc/stdaddressbook.h>
50 #include <tdeabc/vcardconverter.h>
51 #include <libtdepim/kvcarddrag.h>
52 
53 #include "core.h"
54 
55 class DistributionListFactory : public KAB::ExtensionFactory
56 {
57  public:
58  KAB::ExtensionWidget *extension( KAB::Core *core, TQWidget *parent, const char *name )
59  {
60  return new DistributionListWidget( core, parent, name );
61  }
62 
63  TQString identifier() const
64  {
65  return "distribution_list_editor";
66  }
67 };
68 
69 extern "C" {
70  void *init_libkaddrbk_distributionlist()
71  {
72  return ( new DistributionListFactory );
73  }
74 }
75 
81 class DeletePressedCatcher : public TQObject
82 {
83  public:
84  DeletePressedCatcher( DistributionListWidget *parent )
85  : TQObject( parent, "DeletePressedCatcher" ), mWidget( parent )
86  {
87  }
88 
89  protected:
90  bool eventFilter( TQObject*, TQEvent *event )
91  {
92  if ( event->type() == TQEvent::AccelOverride ) {
93  TQKeyEvent *keyEvent = (TQKeyEvent*)event;
94  if ( keyEvent->key() == TQt::Key_Delete ) {
95  keyEvent->accept();
96  mWidget->removeContact();
97  return true;
98  } else
99  return false;
100  } else {
101  return false;
102  }
103  }
104 
105  private:
106  DistributionListWidget *mWidget;
107 };
108 
109 class ContactItem : public TQListViewItem
110 {
111  public:
112  ContactItem( DistributionListView *parent, const TDEABC::Addressee &addressee,
113  const TQString &email = TQString() ) :
114  TQListViewItem( parent ),
115  mAddressee( addressee ),
116  mEmail( email )
117  {
118  setText( 0, addressee.realName() );
119  if ( email.isEmpty() ) {
120  setText( 1, addressee.preferredEmail() );
121  setText( 2, i18n( "Yes" ) );
122  } else {
123  setText( 1, email );
124  setText( 2, i18n( "No" ) );
125  }
126  }
127 
128  TDEABC::Addressee addressee() const
129  {
130  return mAddressee;
131  }
132 
133  TQString email() const
134  {
135  return mEmail;
136  }
137 
138  protected:
139  bool acceptDrop( const TQMimeSource* )
140  {
141  return true;
142  }
143 
144  private:
145  TDEABC::Addressee mAddressee;
146  TQString mEmail;
147 };
148 
149 DistributionListWidget::DistributionListWidget( KAB::Core *core, TQWidget *parent,
150  const char *name )
151  : KAB::ExtensionWidget( core, parent, name )
152 #ifndef TDEPIM_NEW_DISTRLISTS
153  , mManager( 0 )
154 #endif
155 {
156  TQGridLayout *topLayout = new TQGridLayout( this, 3, 4, KDialog::marginHint(),
157  KDialog::spacingHint() );
158 
159  mNameCombo = new TQComboBox( this );
160  topLayout->addWidget( mNameCombo, 0, 0 );
161  connect( mNameCombo, TQ_SIGNAL( activated( int ) ), TQ_SLOT( updateContactView() ) );
162 
163  mCreateListButton = new TQPushButton( i18n( "New List..." ), this );
164  topLayout->addWidget( mCreateListButton, 0, 1 );
165  connect( mCreateListButton, TQ_SIGNAL( clicked() ), TQ_SLOT( createList() ) );
166 
167  mEditListButton = new TQPushButton( i18n( "Rename List..." ), this );
168  topLayout->addWidget( mEditListButton, 0, 2 );
169  connect( mEditListButton, TQ_SIGNAL( clicked() ), TQ_SLOT( editList() ) );
170 
171  mRemoveListButton = new TQPushButton( i18n( "Remove List" ), this );
172  topLayout->addWidget( mRemoveListButton, 0, 3 );
173  connect( mRemoveListButton, TQ_SIGNAL( clicked() ), TQ_SLOT( removeList() ) );
174 
175  mContactView = new DistributionListView( this );
176  mContactView->addColumn( i18n( "Name" ) );
177  mContactView->addColumn( i18n( "Email" ) );
178  mContactView->addColumn( i18n( "Use Preferred" ) );
179  mContactView->setEnabled( false );
180  mContactView->setAllColumnsShowFocus( true );
181  mContactView->setFullWidth( true );
182  topLayout->addMultiCellWidget( mContactView, 1, 1, 0, 3 );
183  connect( mContactView, TQ_SIGNAL( selectionChanged() ),
184  TQ_SLOT( selectionContactViewChanged() ) );
185  connect( mContactView, TQ_SIGNAL( dropped( TQDropEvent*, TQListViewItem* ) ),
186  TQ_SLOT( dropped( TQDropEvent*, TQListViewItem* ) ) );
187 
188  mAddContactButton = new TQPushButton( i18n( "Add Contact" ), this );
189  mAddContactButton->setEnabled( false );
190  topLayout->addWidget( mAddContactButton, 2, 0 );
191  connect( mAddContactButton, TQ_SIGNAL( clicked() ), TQ_SLOT( addContact() ) );
192 
193  mEntryCountLabel = new TQLabel( this );
194  topLayout->addWidget( mEntryCountLabel, 2, 1 );
195 
196  mChangeEmailButton = new TQPushButton( i18n( "Change Email..." ), this );
197  topLayout->addWidget( mChangeEmailButton, 2, 2 );
198  connect( mChangeEmailButton, TQ_SIGNAL( clicked() ), TQ_SLOT( changeEmail() ) );
199 
200  mRemoveContactButton = new TQPushButton( i18n( "Remove Contact" ), this );
201  topLayout->addWidget( mRemoveContactButton, 2, 3 );
202  connect( mRemoveContactButton, TQ_SIGNAL( clicked() ), TQ_SLOT( removeContact() ) );
203 
204 #ifdef TDEPIM_NEW_DISTRLISTS
205  // When contacts are changed, update both distr list combo and contents of displayed distr list
206  connect( core, TQ_SIGNAL( contactsUpdated() ),
207  this, TQ_SLOT( updateNameCombo() ) );
208 #else
209  mManager = new TDEABC::DistributionListManager( core->addressBook() );
210 
211  connect( TDEABC::DistributionListWatcher::self(), TQ_SIGNAL( changed() ),
212  this, TQ_SLOT( updateNameCombo() ) );
213 #endif
214 
215  connect( core->addressBook(), TQ_SIGNAL( addressBookChanged( AddressBook* ) ),
216  this, TQ_SLOT( updateNameCombo() ) );
217 
218  updateNameCombo();
219 
220  TQObject *catcher = new DeletePressedCatcher( this );
221  installEventFilter( catcher );
222  mContactView->installEventFilter( catcher );
223 
224  mContactView->restoreLayout( TDEGlobal::config(), "DistributionListViewColumns" );
225 
226  TDEAcceleratorManager::manage( this );
227 }
228 
229 DistributionListWidget::~DistributionListWidget()
230 {
231 #ifndef TDEPIM_NEW_DISTRLISTS
232  delete mManager;
233 #endif
234 
235  mContactView->saveLayout( TDEGlobal::config(), "DistributionListViewColumns" );
236 }
237 
238 void DistributionListWidget::save()
239 {
240 #ifndef TDEPIM_NEW_DISTRLISTS
241  mManager->save();
242 #endif
243 }
244 
245 void DistributionListWidget::selectionContactViewChanged()
246 {
247  ContactItem *contactItem =
248  static_cast<ContactItem *>( mContactView->selectedItem() );
249  bool state = contactItem;
250 
251  mChangeEmailButton->setEnabled( state );
252  mRemoveContactButton->setEnabled( state );
253 }
254 
255 bool DistributionListWidget::alreadyExists( const TQString& distrListName ) const
256 {
257 #ifdef TDEPIM_NEW_DISTRLISTS
258  return core()->distributionListNames().contains( distrListName );
259 #else
260  return mManager->listNames().contains( distrListName );
261 #endif
262 }
263 
264 void DistributionListWidget::createList()
265 {
266  TQString newName = KInputDialog::getText( i18n( "New Distribution List" ),
267  i18n( "Please enter name:" ),
268  TQString(), 0, this );
269 
270  if ( newName.isEmpty() ) return;
271 
272  if ( alreadyExists( newName ) ) {
273  KMessageBox::sorry( this, i18n( "The name already exists" ) );
274  return;
275  }
276 #ifdef TDEPIM_NEW_DISTRLISTS
277  TDEABC::Resource* resource = core()->requestResource( this );
278  if ( !resource )
279  return;
280 
281  KPIM::DistributionList dist;
282  dist.setResource( resource );
283  dist.setName( newName );
284  // Creates undo-redo command, calls setModified, also triggers contactsUpdated,
285  // which triggers updateNameCombo, so the new name appears
286  changed( dist );
287  core()->addressBook()->insertAddressee( dist );
288 
289 #else
290  new TDEABC::DistributionList( mManager, newName );
291  changed();
292 
293  updateNameCombo();
294 #endif
295 
296  // Select the new one in the list
297  mNameCombo->setCurrentText( newName );
298  // Display the contents of the list we just selected (well, it's empty)
299  updateContactView();
300 }
301 
302 void DistributionListWidget::editList()
303 {
304  const TQString oldName = mNameCombo->currentText();
305 
306  const TQString newName = KInputDialog::getText( i18n( "Rename Distribution List" ),
307  i18n( "Please enter name:" ),
308  oldName, 0, this );
309 
310  if ( newName.isEmpty() ) return;
311 
312  if ( alreadyExists( newName ) ) {
313  KMessageBox::sorry( this, i18n( "The name already exists." ) );
314  return;
315  }
316 #ifdef TDEPIM_NEW_DISTRLISTS
317  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
318  core()->addressBook(), mNameCombo->currentText() );
319  if ( dist.isEmpty() ) // not found [should be impossible]
320  return;
321 
322  dist.setFormattedName( newName );
323  core()->addressBook()->insertAddressee( dist );
324 
325  changed( dist );
326 #else
327  TDEABC::DistributionList *list = mManager->list( oldName );
328  list->setName( newName );
329  mManager->save();
330  updateNameCombo();
331 #endif
332 
333  // Select the new name in the list (updateNameCombo couldn't know we wanted that one)
334  mNameCombo->setCurrentText( newName );
335  // Display the contents of the list we just selected
336  updateContactView();
337 
338 #ifndef TDEPIM_NEW_DISTRLISTS
339  changed();
340 #endif
341 }
342 
343 void DistributionListWidget::removeList()
344 {
345  int result = KMessageBox::warningContinueCancel( this,
346  i18n( "<qt>Delete distribution list <b>%1</b>?</qt>" ) .arg( mNameCombo->currentText() ),
347  TQString(), KGuiItem( i18n("Delete"), "edit-delete") );
348 
349  if ( result != KMessageBox::Continue )
350  return;
351 
352 #ifdef TDEPIM_NEW_DISTRLISTS
353  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
354  core()->addressBook(), mNameCombo->currentText() );
355  if ( dist.isEmpty() ) // not found [should be impossible]
356  return;
357 
358  emit deleted( dist.uid() );
359  core()->addressBook()->removeAddressee( dist );
360 #else
361  mManager->remove( mManager->list( mNameCombo->currentText() ) );
362  mNameCombo->removeItem( mNameCombo->currentItem() );
363 
364  updateContactView();
365 
366  changed();
367 #endif
368 }
369 
370 void DistributionListWidget::addContact()
371 {
372 #ifdef TDEPIM_NEW_DISTRLISTS
373  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
374  core()->addressBook(), mNameCombo->currentText() );
375  if ( dist.isEmpty() ) { // not found
376  kdDebug(5720) << k_funcinfo << mNameCombo->currentText() << " not found" << endl;
377  return;
378  }
379 #else
380  TDEABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
381  if ( !list )
382  return;
383  TDEABC::DistributionList& dist = *list;
384 #endif
385 
386  const TDEABC::Addressee::List addrList = selectedContacts();
387  TDEABC::Addressee::List::ConstIterator it;
388  for ( it = addrList.begin(); it != addrList.end(); ++it )
389  dist.insertEntry( *it );
390 
391 #ifdef TDEPIM_NEW_DISTRLISTS
392  core()->addressBook()->insertAddressee( dist );
393  changed( dist );
394 #else
395  updateContactView();
396  changed();
397 #endif
398 }
399 
400 void DistributionListWidget::removeContact()
401 {
402 #ifdef TDEPIM_NEW_DISTRLISTS
403  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
404  core()->addressBook(), mNameCombo->currentText() );
405  if ( dist.isEmpty() ) // not found
406  return;
407 #else
408  TDEABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
409  if ( !list )
410  return;
411  TDEABC::DistributionList& dist = *list;
412 #endif
413 
414  ContactItem *contactItem =
415  static_cast<ContactItem *>( mContactView->selectedItem() );
416  if ( !contactItem )
417  return;
418 
419  dist.removeEntry( contactItem->addressee(), contactItem->email() );
420  delete contactItem;
421 
422 #ifdef TDEPIM_NEW_DISTRLISTS
423  core()->addressBook()->insertAddressee( dist );
424  changed( dist );
425 #else
426  changed();
427 #endif
428 }
429 
430 void DistributionListWidget::changeEmail()
431 {
432 #ifdef TDEPIM_NEW_DISTRLISTS
433  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
434  core()->addressBook(), mNameCombo->currentText() );
435  if ( dist.isEmpty() ) // not found
436  return;
437 #else
438  TDEABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
439  if ( !list )
440  return;
441  TDEABC::DistributionList& dist = *list;
442 #endif
443 
444  ContactItem *contactItem =
445  static_cast<ContactItem *>( mContactView->selectedItem() );
446  if ( !contactItem )
447  return;
448 
449  bool canceled = false;
450  const TQString email = EmailSelector::getEmail( contactItem->addressee().emails(),
451  contactItem->email(), this, canceled);
452  if( canceled)
453  return;
454  dist.removeEntry( contactItem->addressee(), contactItem->email() );
455  dist.insertEntry( contactItem->addressee(), email );
456 
457 #ifdef TDEPIM_NEW_DISTRLISTS
458  core()->addressBook()->insertAddressee( dist );
459  changed( dist );
460 #else
461  updateContactView();
462  changed();
463 #endif
464 }
465 
466 void DistributionListWidget::updateContactView()
467 {
468  mContactView->clear();
469 
470  bool isListSelected = false;
471 #ifdef TDEPIM_NEW_DISTRLISTS
472  KPIM::DistributionList dist;
473  if ( mNameCombo->count() != 0 )
474  dist = KPIM::DistributionList::findByName(
475  core()->addressBook(), mNameCombo->currentText() );
476  isListSelected = !dist.isEmpty();
477 #else
478  TDEABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
479  isListSelected = list != 0;
480 #endif
481  if ( !isListSelected ) {
482  mEditListButton->setEnabled( false );
483  mRemoveListButton->setEnabled( false );
484  mChangeEmailButton->setEnabled( false );
485  mRemoveContactButton->setEnabled( false );
486  mContactView->setEnabled( false );
487  return;
488  }
489  mEditListButton->setEnabled( true );
490  mRemoveListButton->setEnabled( true );
491  mContactView->setEnabled( true );
492 
493  uint entryCount = 0;
494 #ifdef TDEPIM_NEW_DISTRLISTS
495  const KPIM::DistributionList::Entry::List entries = dist.entries( core()->addressBook() );
496  KPIM::DistributionList::Entry::List::ConstIterator it;
497 #else
498  const TDEABC::DistributionList::Entry::List entries = list->entries();
499  TDEABC::DistributionList::Entry::List::ConstIterator it;
500 #endif
501  for ( it = entries.begin(); it != entries.end(); ++it, ++entryCount )
502  new ContactItem( mContactView, (*it).addressee, (*it).email );
503 
504  bool state = mContactView->selectedItem() != 0;
505  mChangeEmailButton->setEnabled( state );
506  mRemoveContactButton->setEnabled( state );
507 
508  mEntryCountLabel->setText( i18n( "Count: %n contact", "Count: %n contacts", entryCount ) );
509 }
510 
511 void DistributionListWidget::updateNameCombo()
512 {
513  int pos = mNameCombo->currentItem();
514  mNameCombo->clear();
515 #ifdef TDEPIM_NEW_DISTRLISTS
516  const TQStringList names = core()->distributionListNames();
517 #else
518  mManager->load();
519  const TQStringList names = mManager->listNames();
520 #endif
521  mNameCombo->insertStringList( names );
522  mNameCombo->setCurrentItem( TQMIN( pos, (int)names.count() - 1 ) );
523 
524  updateContactView();
525 }
526 
527 void DistributionListWidget::dropEvent( TQDropEvent *e )
528 {
529  if ( mNameCombo->count() == 0 )
530  return;
531 
532 #ifdef TDEPIM_NEW_DISTRLISTS
533  KPIM::DistributionList dist = KPIM::DistributionList::findByName(
534  core()->addressBook(), mNameCombo->currentText() );
535  if ( dist.isEmpty() )
536  return;
537 #else
538  TDEABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
539  if ( !list )
540  return;
541  TDEABC::DistributionList& dist = *list;
542 #endif
543 
544  TQString vcards;
545  if ( KVCardDrag::decode( e, vcards ) ) {
546  TDEABC::VCardConverter converter;
547  const TDEABC::Addressee::List lst = converter.parseVCards( vcards );
548  for ( TDEABC::Addressee::List::ConstIterator it = lst.begin(); it != lst.end(); ++it )
549  dist.insertEntry( *it );
550 
551 #ifdef TDEPIM_NEW_DISTRLISTS
552  core()->addressBook()->insertAddressee( dist );
553  changed( dist );
554 #else
555  changed();
556  updateContactView();
557 #endif
558  }
559 }
560 
561 void DistributionListWidget::contactsSelectionChanged()
562 {
563  mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 );
564 }
565 
566 TQString DistributionListWidget::title() const
567 {
568  return i18n( "Distribution List Editor" );
569 }
570 
571 TQString DistributionListWidget::identifier() const
572 {
573  return "distribution_list_editor";
574 }
575 
576 void DistributionListWidget::dropped( TQDropEvent *e, TQListViewItem* )
577 {
578  dropEvent( e );
579 }
580 
581 #ifdef TDEPIM_NEW_DISTRLISTS
582 void DistributionListWidget::changed( const TDEABC::Addressee& dist )
583 {
584  emit modified( TDEABC::Addressee::List() << dist );
585 }
586 #else
587 void DistributionListWidget::changed()
588 {
589  save();
590 }
591 #endif
592 
593 DistributionListView::DistributionListView( TQWidget *parent, const char* name )
594  : TDEListView( parent, name )
595 {
596  setDragEnabled( true );
597  setAcceptDrops( true );
598  setAllColumnsShowFocus( true );
599 }
600 
601 void DistributionListView::dragEnterEvent( TQDragEnterEvent* e )
602 {
603  bool canDecode = TQTextDrag::canDecode( e );
604  e->accept( canDecode );
605 }
606 
607 void DistributionListView::viewportDragMoveEvent( TQDragMoveEvent *e )
608 {
609  bool canDecode = TQTextDrag::canDecode( e );
610  e->accept( canDecode );
611 }
612 
613 void DistributionListView::viewportDropEvent( TQDropEvent *e )
614 {
615  emit dropped( e, 0 );
616 }
617 
618 void DistributionListView::dropEvent( TQDropEvent *e )
619 {
620  emit dropped( e, 0 );
621 }
622 
623 
624 EmailSelector::EmailSelector( const TQStringList &emails,
625  const TQString &current, TQWidget *parent )
626  : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok|Cancel, Ok,
627  parent )
628 {
629  TQFrame *topFrame = plainPage();
630  TQBoxLayout *topLayout = new TQVBoxLayout( topFrame );
631 
632  mButtonGroup = new TQButtonGroup( 1, Horizontal, i18n("Email Addresses"),
633  topFrame );
634  mButtonGroup->setRadioButtonExclusive( true );
635  topLayout->addWidget( mButtonGroup );
636 
637  TQRadioButton *button = new TQRadioButton( i18n("Preferred address"), mButtonGroup );
638  button->setDown( true );
639  mEmailMap.insert( mButtonGroup->id( button ), "" );
640 
641  TQStringList::ConstIterator it;
642  for ( it = emails.begin(); it != emails.end(); ++it ) {
643  button = new TQRadioButton( *it, mButtonGroup );
644  mEmailMap.insert( mButtonGroup->id( button ), *it );
645  if ( (*it) == current )
646  button->setDown( true );
647  }
648 }
649 
650 TQString EmailSelector::selected() const
651 {
652  TQButton *button = mButtonGroup->selected();
653  if ( button )
654  return mEmailMap[ mButtonGroup->id( button ) ];
655 
656  return TQString();
657 }
658 
659 TQString EmailSelector::getEmail( const TQStringList &emails,
660  const TQString &current, TQWidget *parent, bool &canceled )
661 {
662  EmailSelector dlg( emails, current, parent );
663  if(dlg.exec())
664  {
665  canceled = false;
666  return dlg.selected();
667  }
668  canceled = true;
669  return TQString();
670 }
671 
672 
673 #include "distributionlistwidget.moc"