korganizer

koeditordetails.cpp
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of TQt, and distribute the resulting executable,
23  without including the source code for TQt in the source distribution.
24 */
25 
26 #include "koeditordetails.h"
27 
28 #include <tqbuttongroup.h>
29 #include <tqcheckbox.h>
30 #include <tqcombobox.h>
31 #include <tqdatetime.h>
32 #include <tqdragobject.h>
33 #include <tqfiledialog.h>
34 #include <tqgroupbox.h>
35 #include <tqlabel.h>
36 #include <tqlayout.h>
37 #include <tqlineedit.h>
38 #include <tqpushbutton.h>
39 #include <tqradiobutton.h>
40 #include <tqregexp.h>
41 #include <tqtooltip.h>
42 #include <tqvbox.h>
43 #include <tqvgroupbox.h>
44 #include <tqwhatsthis.h>
45 #include <tqwidgetstack.h>
46 #include <tqvaluevector.h>
47 
48 #include <kdebug.h>
49 #include <tdelocale.h>
50 #include <kiconloader.h>
51 #include <tdemessagebox.h>
52 #ifndef KORG_NOKABC
53 #include <tdeabc/addresseedialog.h>
54 #include <tdeabc/vcardconverter.h>
55 #include <libtdepim/addressesdialog.h>
56 #include <libtdepim/addresseelineedit.h>
57 #include <libtdepim/distributionlist.h>
58 #include <tdeabc/stdaddressbook.h>
59 #endif
60 #include <libtdepim/kvcarddrag.h>
61 #include <libemailfunctions/email.h>
62 
63 #include <libkcal/incidence.h>
64 
65 #include "koprefs.h"
66 #include "koglobals.h"
67 
68 #include "koeditorfreebusy.h"
69 
70 #include "kocore.h"
71 
72 template <>
73 CustomListViewItem<KCal::Attendee *>::~CustomListViewItem()
74 {
75  // do not delete mData here
76 // delete mData;
77 }
78 
79 template <>
80 void CustomListViewItem<KCal::Attendee *>::updateItem()
81 {
82  setText(0,mData->name());
83  setText(1,mData->email());
84  setText(2,mData->roleStr());
85  setText(3,mData->statusStr());
86  if (mData->RSVP() && !mData->email().isEmpty())
87  setPixmap(4,KOGlobals::self()->smallIcon("mailappt"));
88  else
89  setPixmap(4,KOGlobals::self()->smallIcon("nomailappt"));
90  setText(5, mData->delegate());
91  setText(6, mData->delegator());
92 }
93 
94 KOAttendeeListView::KOAttendeeListView ( TQWidget *parent, const char *name )
95  : TDEListView(parent, name)
96 {
97  setAcceptDrops( true );
98  setAllColumnsShowFocus( true );
99  setSorting( -1 );
100 }
101 
108 {
109 }
110 
111 void KOAttendeeListView::contentsDragEnterEvent( TQDragEnterEvent *e )
112 {
113  dragEnterEvent(e);
114 }
115 
116 void KOAttendeeListView::contentsDragMoveEvent( TQDragMoveEvent *e )
117 {
118 #ifndef KORG_NODND
119  if ( KVCardDrag::canDecode( e ) || TQTextDrag::canDecode( e ) ) {
120  e->accept();
121  } else {
122  e->ignore();
123  }
124 #endif
125 }
126 
127 void KOAttendeeListView::dragEnterEvent( TQDragEnterEvent *e )
128 {
129 #ifndef KORG_NODND
130  if ( KVCardDrag::canDecode( e ) || TQTextDrag::canDecode( e ) ) {
131  e->accept();
132  } else {
133  e->ignore();
134  }
135 #endif
136 }
137 
138 void KOAttendeeListView::addAttendee( const TQString &newAttendee )
139 {
140  kdDebug(5850) << " Email: " << newAttendee << endl;
141  TQString name;
142  TQString email;
143  KPIM::getNameAndMail( newAttendee, name, email );
144  emit dropped( new Attendee( name, email, true ) );
145 }
146 
147 void KOAttendeeListView::contentsDropEvent( TQDropEvent *e )
148 {
149  dropEvent(e);
150 }
151 
152 void KOAttendeeListView::dropEvent( TQDropEvent *e )
153 {
154 #ifndef KORG_NODND
155  TQString text;
156 
157 #ifndef KORG_NOKABC
158  TDEABC::Addressee::List list;
159  if ( KVCardDrag::decode( e, list ) ) {
160  TDEABC::Addressee::List::Iterator it;
161  for ( it = list.begin(); it != list.end(); ++it ) {
162  TQString em( (*it).fullEmail() );
163  if ( em.isEmpty() ) {
164  em = (*it).realName();
165  }
166  addAttendee( em );
167  }
168  } else
169 #endif // KORG_NOKABC
170  if (TQTextDrag::decode(e,text)) {
171  kdDebug(5850) << "Dropped : " << text << endl;
172  TQStringList emails = TQStringList::split(",",text);
173  for(TQStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
174  addAttendee(*it);
175  }
176  }
177 #endif //KORG_NODND
178 }
179 
180 
181 KOEditorDetails::KOEditorDetails( int spacing, TQWidget *parent,
182  const char *name )
183  : KOAttendeeEditor( parent, name), mDisableItemUpdate( false )
184 {
185  TQBoxLayout *topLayout = new TQVBoxLayout( this );
186  topLayout->setSpacing( spacing );
187 
188  initOrganizerWidgets( this, topLayout );
189 
190  mListView = new KOAttendeeListView( this, "mListView" );
191  TQWhatsThis::add( mListView,
192  i18n("Displays information about current attendees. "
193  "To edit an attendee, select it in this list "
194  "and modify the values in the area below. "
195  "Clicking on a column title will sort the list "
196  "according to that column. The RSVP column "
197  "indicates whether or not a response is requested "
198  "from the attendee.") );
199  mListView->addColumn( i18n("Name"), 200 );
200  mListView->addColumn( i18n("Email"), 200 );
201  mListView->addColumn( i18n("Role"), 80 );
202  mListView->addColumn( i18n("Status"), 100 );
203  mListView->addColumn( i18n("RSVP"), 55 );
204  mListView->addColumn( i18n("Delegated to"), 120 );
205  mListView->addColumn( i18n("Delegated from" ), 120 );
206  mListView->setResizeMode( TQListView::LastColumn );
207  if ( KOPrefs::instance()->mCompactDialogs ) {
208  mListView->setFixedHeight( 78 );
209  }
210 
211  connect( mListView, TQ_SIGNAL( selectionChanged( TQListViewItem * ) ),
212  TQ_SLOT( updateAttendeeInput() ) );
213 #ifndef KORG_NODND
214  connect( mListView, TQ_SIGNAL( dropped( Attendee * ) ),
215  TQ_SLOT( slotInsertAttendee( Attendee * ) ) );
216 #endif
217  topLayout->addWidget( mListView );
218 
219  initEditWidgets( this, topLayout );
220 
221  connect( mRemoveButton, TQ_SIGNAL(clicked()), TQ_SLOT(removeAttendee()) );
222 
223  updateAttendeeInput();
224 }
225 
226 KOEditorDetails::~KOEditorDetails()
227 {
228 }
229 
230 bool KOEditorDetails::hasAttendees()
231 {
232  return mListView->childCount() > 0;
233 }
234 
235 void KOEditorDetails::removeAttendee()
236 {
237  AttendeeListItem *aItem =
238  static_cast<AttendeeListItem *>( mListView->selectedItem() );
239  if ( !aItem ) return;
240 
241  AttendeeListItem *nextSelectedItem = static_cast<AttendeeListItem*>( aItem->nextSibling() );
242  if( mListView->childCount() == 1 )
243  nextSelectedItem = 0;
244  if( mListView->childCount() > 1 && aItem == mListView->lastItem() )
245  nextSelectedItem = static_cast<AttendeeListItem*>( mListView->firstChild() );
246 
247  Attendee *attendee = aItem->data();
248  Attendee *delA = new Attendee( attendee->name(), attendee->email(),
249  attendee->RSVP(), attendee->status(),
250  attendee->role(), attendee->uid() );
251  mdelAttendees.append( delA );
252  delete aItem;
253 
254  if( nextSelectedItem ) {
255  mListView->setSelected( nextSelectedItem, true );
256  }
257  updateAttendeeInput();
258  emit updateAttendeeSummary( mListView->childCount() );
259 }
260 
261 
262 void KOEditorDetails::insertAttendee( Attendee *a, bool goodEmailAddress )
263 {
264  Q_UNUSED( goodEmailAddress );
265 
266  // lastItem() is O(n), but for n very small that should be fine
267  AttendeeListItem *item = new AttendeeListItem(
268  a, mListView, static_cast<TDEListViewItem*>( mListView->lastItem() ) );
269  mListView->setSelected( item, true );
270  emit updateAttendeeSummary( mListView->childCount() );
271 }
272 
273 void KOEditorDetails::removeAttendee( Attendee *attendee )
274 {
275  TQListViewItem *item;
276  for ( item = mListView->firstChild(); item; item = item->nextSibling() ) {
277  AttendeeListItem *anItem = static_cast<AttendeeListItem *>( item );
278  Attendee *att = anItem->data();
279  if ( att == attendee ) {
280  delete anItem;
281  break;
282  }
283  }
284 }
285 
286 void KOEditorDetails::setDefaults()
287 {
288  mRsvpButton->setChecked( true );
289 }
290 
291 void KOEditorDetails::readEvent( Incidence *event )
292 {
293  mListView->clear();
294  KOAttendeeEditor::readEvent( event );
295 
296  mListView->setSelected( mListView->firstChild(), true );
297 
298  emit updateAttendeeSummary( mListView->childCount() );
299 }
300 
301 void KOEditorDetails::writeEvent(Incidence *event)
302 {
303  event->clearAttendees();
304  TQValueVector<TQListViewItem*> toBeDeleted;
305  TQListViewItem *item;
306  AttendeeListItem *a;
307  for (item = mListView->firstChild(); item;
308  item = item->nextSibling()) {
309  a = (AttendeeListItem *)item;
310  Attendee *attendee = a->data();
311  Q_ASSERT( attendee );
312  /* Check if the attendee is a distribution list and expand it */
313  if ( attendee->email().isEmpty() ) {
314  KPIM::DistributionList list =
315  KPIM::DistributionList::findByName( TDEABC::StdAddressBook::self(), attendee->name() );
316  if ( !list.isEmpty() ) {
317  toBeDeleted.push_back( item ); // remove it once we are done expanding
318  KPIM::DistributionList::Entry::List entries = list.entries( TDEABC::StdAddressBook::self() );
319  KPIM::DistributionList::Entry::List::Iterator it( entries.begin() );
320  while ( it != entries.end() ) {
321  KPIM::DistributionList::Entry &e = ( *it );
322  ++it;
323  // this calls insertAttendee, which appends
324  insertAttendeeFromAddressee( e.addressee, attendee );
325  // TODO: duplicate check, in case it was already added manually
326  }
327  }
328  } else {
329  bool skip = false;
330  if ( attendee->email().endsWith( "example.net" ) ) {
331  if ( KMessageBox::warningYesNo( this, i18n("%1 does not look like a valid email address. "
332  "Are you sure you want to invite this participant?").arg( attendee->email() ),
333  i18n("Invalid email address") ) != KMessageBox::Yes ) {
334  skip = true;
335  }
336  }
337  if ( !skip ) {
338  event->addAttendee( new Attendee( *attendee ) );
339  }
340  }
341  }
342 
343  KOAttendeeEditor::writeEvent( event );
344 
345  // cleanup
346  TQValueVector<TQListViewItem*>::iterator it;
347  for( it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it ) {
348  delete *it;
349  }
350 }
351 
352 bool KOEditorDetails::validateInput()
353 {
354  return true;
355 }
356 
357 KCal::Attendee * KOEditorDetails::currentAttendee() const
358 {
359  TQListViewItem *item = mListView->selectedItem();
360  AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item );
361  if ( !aItem )
362  return 0;
363  return aItem->data();
364 }
365 
366 void KOEditorDetails::updateCurrentItem()
367 {
368  AttendeeListItem *item = static_cast<AttendeeListItem*>( mListView->selectedItem() );
369  if ( item )
370  item->updateItem();
371 }
372 
373 void KOEditorDetails::slotInsertAttendee( Attendee *a )
374 {
375  insertAttendee( a );
376  mnewAttendees.append( a );
377 }
378 
379 void KOEditorDetails::setSelected( int index )
380 {
381  int count = 0;
382  for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) {
383  if ( count == index ) {
384  mListView->setSelected( *it, true );
385  return;
386  }
387  count++;
388  }
389 }
390 
391 int KOEditorDetails::selectedIndex()
392 {
393  int index = 0;
394  for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) {
395  if ( mListView->isSelected( *it ) ) {
396  break;
397  }
398  index++;
399  }
400  return index;
401 }
402 
403 void KOEditorDetails::changeStatusForMe(Attendee::PartStat status)
404 {
405  const TQStringList myEmails = KOPrefs::instance()->allEmails();
406  for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) {
407  AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() );
408  for ( TQStringList::ConstIterator it2( myEmails.begin() ), end( myEmails.end() ); it2 != end; ++it2 ) {
409  if ( item->data()->email() == *it2 ) {
410  item->data()->setStatus( status );
411  item->updateItem();
412  }
413  }
414  }
415 }
416 
417 TQListViewItem* KOEditorDetails::hasExampleAttendee() const
418 {
419  for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) {
420  AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() );
421  Attendee *attendee = item->data();
422  Q_ASSERT( attendee );
423  if ( isExampleAttendee( attendee ) )
424  return item;
425  }
426  return 0;
427 }
428 
429 #include "koeditordetails.moc"
TQString uid() const
Role role() const
bool RSVP() const
PartStat status() const
Common base class for attendee editor and free busy view.
KOAttendeeListView is a child class of TDEListView which supports dropping of attendees (e....
virtual ~KOAttendeeListView()
KOAttendeeListView is a child class of TDEListView which supports dropping of attendees (e....