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
72template <>
73CustomListViewItem<KCal::Attendee *>::~CustomListViewItem()
74{
75 // do not delete mData here
76// delete mData;
77}
78
79template <>
80void 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
94KOAttendeeListView::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
111void KOAttendeeListView::contentsDragEnterEvent( TQDragEnterEvent *e )
112{
113 dragEnterEvent(e);
114}
115
116void 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
127void 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
138void 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
147void KOAttendeeListView::contentsDropEvent( TQDropEvent *e )
148{
149 dropEvent(e);
150}
151
152void 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
181KOEditorDetails::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
226KOEditorDetails::~KOEditorDetails()
227{
228}
229
230bool KOEditorDetails::hasAttendees()
231{
232 return mListView->childCount() > 0;
233}
234
235void 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
262void 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
273void 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
286void KOEditorDetails::setDefaults()
287{
288 mRsvpButton->setChecked( true );
289}
290
291void 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
301void 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
352bool KOEditorDetails::validateInput()
353{
354 return true;
355}
356
357KCal::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
366void KOEditorDetails::updateCurrentItem()
367{
368 AttendeeListItem *item = static_cast<AttendeeListItem*>( mListView->selectedItem() );
369 if ( item )
370 item->updateItem();
371}
372
373void KOEditorDetails::slotInsertAttendee( Attendee *a )
374{
375 insertAttendee( a );
376 mnewAttendees.append( a );
377}
378
379void 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
391int 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
403void 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
417TQListViewItem* 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....