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>
44typedef KPIM::DistributionList DistributionList;
45#else
46#include <tdeabc/distributionlist.h>
47typedef 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
55class 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
69extern "C" {
70 void *init_libkaddrbk_distributionlist()
71 {
72 return ( new DistributionListFactory );
73 }
74}
75
81class 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
109class 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
149DistributionListWidget::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
229DistributionListWidget::~DistributionListWidget()
230{
231#ifndef TDEPIM_NEW_DISTRLISTS
232 delete mManager;
233#endif
234
235 mContactView->saveLayout( TDEGlobal::config(), "DistributionListViewColumns" );
236}
237
238void DistributionListWidget::save()
239{
240#ifndef TDEPIM_NEW_DISTRLISTS
241 mManager->save();
242#endif
243}
244
245void 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
255bool 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
264void 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
302void 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
343void 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
370void 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
400void 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
430void 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
466void 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
511void 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
527void 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
561void DistributionListWidget::contactsSelectionChanged()
562{
563 mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 );
564}
565
566TQString DistributionListWidget::title() const
567{
568 return i18n( "Distribution List Editor" );
569}
570
571TQString DistributionListWidget::identifier() const
572{
573 return "distribution_list_editor";
574}
575
576void DistributionListWidget::dropped( TQDropEvent *e, TQListViewItem* )
577{
578 dropEvent( e );
579}
580
581#ifdef TDEPIM_NEW_DISTRLISTS
582void DistributionListWidget::changed( const TDEABC::Addressee& dist )
583{
584 emit modified( TDEABC::Addressee::List() << dist );
585}
586#else
587void DistributionListWidget::changed()
588{
589 save();
590}
591#endif
592
593DistributionListView::DistributionListView( TQWidget *parent, const char* name )
594 : TDEListView( parent, name )
595{
596 setDragEnabled( true );
597 setAcceptDrops( true );
598 setAllColumnsShowFocus( true );
599}
600
601void DistributionListView::dragEnterEvent( TQDragEnterEvent* e )
602{
603 bool canDecode = TQTextDrag::canDecode( e );
604 e->accept( canDecode );
605}
606
607void DistributionListView::viewportDragMoveEvent( TQDragMoveEvent *e )
608{
609 bool canDecode = TQTextDrag::canDecode( e );
610 e->accept( canDecode );
611}
612
613void DistributionListView::viewportDropEvent( TQDropEvent *e )
614{
615 emit dropped( e, 0 );
616}
617
618void DistributionListView::dropEvent( TQDropEvent *e )
619{
620 emit dropped( e, 0 );
621}
622
623
624EmailSelector::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
650TQString EmailSelector::selected() const
651{
652 TQButton *button = mButtonGroup->selected();
653 if ( button )
654 return mEmailMap[ mButtonGroup->id( button ) ];
655
656 return TQString();
657}
658
659TQString 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"