25 #include <tqtooltip.h>
28 #include <tqcombobox.h>
29 #include <tqpushbutton.h>
30 #include <tqvaluevector.h>
31 #include <tqwhatsthis.h>
34 #include <tdelocale.h>
35 #include <kiconloader.h>
36 #include <tdemessagebox.h>
39 #include <tdeabc/addresseedialog.h>
40 #include <tdeabc/vcardconverter.h>
41 #include <libtdepim/addressesdialog.h>
42 #include <libtdepim/addresseelineedit.h>
43 #include <libtdepim/distributionlist.h>
44 #include <tdeabc/stdaddressbook.h>
47 #include <libkcal/event.h>
48 #include <libkcal/freebusy.h>
50 #include <libemailfunctions/email.h>
52 #include <kdgantt/KDGanttView.h>
53 #include <kdgantt/KDGanttViewTaskItem.h>
54 #include <kdgantt/KDGanttViewSubwidgets.h>
57 #include "koglobals.h"
58 #include "kogroupware.h"
59 #include "freebusymanager.h"
60 #include "freebusyurldialog.h"
62 #include "koeditorfreebusy.h"
69 class FreeBusyItem :
public KDGanttViewTaskItem
72 FreeBusyItem(
Attendee *attendee, KDGanttView *parent ) :
73 KDGanttViewTaskItem( parent, parent->lastItem() ), mAttendee( attendee ), mTimerID( 0 ),
74 mIsDownloading( false )
78 setFreeBusyPeriods( 0 );
79 setDisplaySubitemsAsGroup(
true );
81 listView ()->setRootIsDecorated(
false );
87 Attendee *attendee()
const {
return mAttendee; }
91 void setFreeBusyPeriods(
FreeBusy *fb );
93 TQString key(
int column,
bool )
const
95 TQMap<int,TQString>::ConstIterator it = mKeyMap.find( column );
96 if ( it == mKeyMap.end() )
return listViewText( column );
100 void setSortKey(
int column,
const TQString &key )
102 mKeyMap.insert( column, key );
105 TQString email()
const {
return mAttendee->email(); }
106 void setUpdateTimerID(
int id ) { mTimerID = id; }
107 int updateTimerID()
const {
return mTimerID; }
109 void startDownload(
bool forceDownload ) {
110 mIsDownloading =
true;
111 FreeBusyManager *m = KOGroupware::instance()->freeBusyManager();
112 if ( !m->retrieveFreeBusy( attendee()->email(), forceDownload ) )
113 mIsDownloading =
false;
115 void setIsDownloading(
bool d ) { mIsDownloading = d; }
116 bool isDownloading()
const {
return mIsDownloading; }
122 TQMap<int,TQString> mKeyMap;
131 void FreeBusyItem::updateItem()
133 TQString text = mAttendee->name() +
" <" + mAttendee->email() +
'>';
134 setListViewText( 0, text );
135 switch ( mAttendee->status() ) {
136 case Attendee::Accepted:
137 setPixmap( 0, KOGlobals::self()->smallIcon(
"ok" ) );
139 case Attendee::Declined:
140 setPixmap( 0, KOGlobals::self()->smallIcon(
"no" ) );
142 case Attendee::NeedsAction:
143 case Attendee::InProcess:
144 setPixmap( 0, KOGlobals::self()->smallIcon(
"help" ) );
146 case Attendee::Tentative:
147 setPixmap( 0, KOGlobals::self()->smallIcon(
"apply" ) );
149 case Attendee::Delegated:
150 setPixmap( 0, KOGlobals::self()->smallIcon(
"mail-forward" ) );
153 setPixmap( 0, TQPixmap() );
159 void FreeBusyItem::setFreeBusyPeriods(
FreeBusy* fb )
163 for( KDGanttViewItem* it = firstChild(); it; it = firstChild() )
167 TQValueList<KCal::Period> busyPeriods = fb->busyPeriods();
168 for( TQValueList<KCal::Period>::Iterator it = busyPeriods.begin();
169 it != busyPeriods.end(); ++it ) {
172 KDGanttViewTaskItem *newSubItem =
new KDGanttViewTaskItem(
this );
173 newSubItem->setStartTime( per.start() );
174 newSubItem->setEndTime( per.end() );
175 newSubItem->setColors( TQt::red, TQt::red, TQt::red );
177 TQString toolTip =
"<qt>";
178 toolTip +=
"<b>" + i18n(
"Freebusy Period" ) +
"</b>";
179 toolTip +=
"<br>----------------------<br>";
180 if ( !per.summary().isEmpty() ) {
181 toolTip +=
"<i>" + i18n(
"Summary:" ) +
"</i>" +
" ";
182 toolTip += per.summary();
185 if ( !per.location().isEmpty() ) {
186 toolTip +=
"<i>" + i18n(
"Location:" ) +
"</i>" +
" ";
187 toolTip += per.location();
190 toolTip +=
"<i>" + i18n(
"Start:" ) +
"</i>" +
" ";
191 toolTip += TDEGlobal::locale()->formatDateTime( per.start() );
193 toolTip +=
"<i>" + i18n(
"End:" ) +
"</i>" +
" ";
194 toolTip += TDEGlobal::locale()->formatDateTime( per.end() );
197 newSubItem->setTooltipText( toolTip );
200 setShowNoInformation(
false );
216 setShowNoInformation(
true );
220 mIsDownloading =
false;
225 KOEditorFreeBusy::KOEditorFreeBusy(
int spacing, TQWidget *parent,
229 TQVBoxLayout *topLayout =
new TQVBoxLayout(
this );
230 topLayout->setSpacing( spacing );
232 initOrganizerWidgets(
this, topLayout );
236 mIsOrganizer =
false;
237 mStatusSummaryLabel =
new TQLabel(
this );
238 mStatusSummaryLabel->setPalette( TQToolTip::palette() );
239 mStatusSummaryLabel->setFrameStyle( TQFrame::Plain | TQFrame::Box );
240 mStatusSummaryLabel->setLineWidth( 1 );
241 mStatusSummaryLabel->hide();
242 topLayout->addWidget( mStatusSummaryLabel );
245 TQBoxLayout *controlLayout =
new TQHBoxLayout( topLayout );
247 TQString whatsThis = i18n(
"Sets the zoom level on the Gantt chart. "
248 "'Hour' shows a range of several hours, "
249 "'Day' shows a range of a few days, "
250 "'Week' shows a range of a few months, "
251 "and 'Month' shows a range of a few years, "
252 "while 'Automatic' selects the range most "
253 "appropriate for the current event or to-do.");
254 TQLabel *label =
new TQLabel( i18n(
"Scale: " ),
this );
255 TQWhatsThis::add( label, whatsThis );
256 controlLayout->addWidget( label );
258 scaleCombo =
new TQComboBox(
this );
259 TQWhatsThis::add( scaleCombo, whatsThis );
260 scaleCombo->insertItem( i18n(
"Hour" ) );
261 scaleCombo->insertItem( i18n(
"Day" ) );
262 scaleCombo->insertItem( i18n(
"Week" ) );
263 scaleCombo->insertItem( i18n(
"Month" ) );
264 scaleCombo->insertItem( i18n(
"Automatic" ) );
265 scaleCombo->setCurrentItem( 0 );
266 connect( scaleCombo, TQ_SIGNAL( activated(
int ) ),
267 TQ_SLOT( slotScaleChanged(
int ) ) );
268 controlLayout->addWidget( scaleCombo );
270 TQPushButton *button =
new TQPushButton( i18n(
"Center on Start" ),
this );
271 TQWhatsThis::add( button,
272 i18n(
"Centers the Gantt chart on the start time "
273 "and day of this event.") );
274 connect( button, TQ_SIGNAL( clicked() ), TQ_SLOT( slotCenterOnStart() ) );
275 controlLayout->addWidget( button );
277 controlLayout->addStretch( 1 );
279 button =
new TQPushButton( i18n(
"Pick Date" ),
this );
280 TQWhatsThis::add( button,
281 i18n(
"Moves the event to a date and time when all the "
282 "attendees are free.") );
283 connect( button, TQ_SIGNAL( clicked() ), TQ_SLOT( slotPickDate() ) );
284 controlLayout->addWidget( button );
286 controlLayout->addStretch( 1 );
288 button =
new TQPushButton( i18n(
"Reload"),
this );
289 TQWhatsThis::add( button,
290 i18n(
"Reloads Free/Busy data for all attendees from "
291 "the corresponding servers.") );
292 controlLayout->addWidget( button );
293 connect( button, TQ_SIGNAL( clicked() ), TQ_SLOT( manualReload() ) );
295 mGanttView =
new KDGanttView(
this,
"mGanttView" );
296 TQWhatsThis::add( mGanttView,
297 i18n(
"Shows the free/busy status of all attendees. "
298 "Double-clicking on an attendees entry in the "
299 "list will allow you to enter the location of their "
300 "Free/Busy Information.") );
301 topLayout->addWidget( mGanttView );
303 mGanttView->removeColumn( 0 );
304 mGanttView->addColumn( i18n(
"Attendee") );
305 if ( KOPrefs::instance()->mCompactDialogs ) {
306 mGanttView->setFixedHeight( 78 );
308 mGanttView->setHeaderVisible(
true );
309 mGanttView->setScale( KDGanttView::Hour );
310 mGanttView->setShowHeaderPopupMenu(
false,
false,
false,
false,
false,
false );
313 TQDateTime horizonStart = TQDateTime( TQDateTime::currentDateTime()
314 .addDays( -15 ).date() );
315 TQDateTime horizonEnd = TQDateTime::currentDateTime().addDays( 15 );
316 mGanttView->setHorizonStart( horizonStart );
317 mGanttView->setHorizonEnd( horizonEnd );
318 mGanttView->setCalendarMode(
true );
320 mGanttView->setShowLegendButton(
false );
322 mGanttView->centerTimelineAfterShow( TQDateTime::currentDateTime() );
323 if ( TDEGlobal::locale()->use12Clock() )
324 mGanttView->setHourFormat( KDGanttView::Hour_12 );
326 mGanttView->setHourFormat( KDGanttView::Hour_24_FourDigit );
329 mEventRectangle =
new KDIntervalColorRectangle( mGanttView );
330 mEventRectangle->setColor( TQt::magenta );
331 mGanttView->addIntervalBackgroundColor( mEventRectangle );
333 connect( mGanttView, TQ_SIGNAL ( timeIntervalSelected(
const TQDateTime &,
334 const TQDateTime & ) ),
335 mGanttView, TQ_SLOT( zoomToSelection(
const TQDateTime &,
336 const TQDateTime & ) ) );
337 connect( mGanttView, TQ_SIGNAL( lvItemDoubleClicked( KDGanttViewItem * ) ),
338 TQ_SLOT( editFreeBusyUrl( KDGanttViewItem * ) ) );
339 connect( mGanttView, TQ_SIGNAL( intervalColorRectangleMoved(
const TQDateTime&,
const TQDateTime& ) ),
340 this, TQ_SLOT( slotIntervalColorRectangleMoved(
const TQDateTime&,
const TQDateTime& ) ) );
342 connect( mGanttView, TQ_SIGNAL(lvSelectionChanged(KDGanttViewItem*)),
343 this, TQ_SLOT(updateAttendeeInput()) );
344 connect( mGanttView, TQ_SIGNAL(lvItemLeftClicked(KDGanttViewItem*)),
345 this, TQ_SLOT(showAttendeeStatusMenu()) );
346 connect( mGanttView, TQ_SIGNAL(lvItemRightClicked(KDGanttViewItem*)),
347 this, TQ_SLOT(showAttendeeStatusMenu()) );
348 connect( mGanttView, TQ_SIGNAL(lvMouseButtonClicked(
int, KDGanttViewItem*,
const TQPoint&,
int)),
349 this, TQ_SLOT(listViewClicked(
int, KDGanttViewItem*)) );
351 FreeBusyManager *m = KOGroupware::instance()->freeBusyManager();
352 connect( m, TQ_SIGNAL( freeBusyRetrieved(
KCal::FreeBusy *,
const TQString & ) ),
353 TQ_SLOT( slotInsertFreeBusy(
KCal::FreeBusy *,
const TQString & ) ) );
355 connect( &mReloadTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( autoReload() ) );
357 initEditWidgets(
this, topLayout );
358 connect( mRemoveButton, TQ_SIGNAL(clicked()),
359 TQ_SLOT(removeAttendee()) );
361 slotOrganizerChanged( mOrganizerCombo->currentText() );
362 connect( mOrganizerCombo, TQ_SIGNAL( activated(
const TQString&) ),
363 this, TQ_SLOT( slotOrganizerChanged(
const TQString&) ) );
366 mGanttView->timeHeaderWidget()->installEventFilter(
this );
369 KOEditorFreeBusy::~KOEditorFreeBusy()
373 void KOEditorFreeBusy::removeAttendee(
Attendee *attendee )
375 FreeBusyItem *anItem =
376 static_cast<FreeBusyItem *
>( mGanttView->firstChild() );
378 if( anItem->attendee() == attendee ) {
379 if ( anItem->updateTimerID() != 0 )
380 killTimer( anItem->updateTimerID() );
382 updateStatusSummary();
385 anItem =
static_cast<FreeBusyItem *
>( anItem->nextSibling() );
389 void KOEditorFreeBusy::insertAttendee(
Attendee *attendee,
bool readFBList )
391 FreeBusyItem* item =
new FreeBusyItem( attendee, mGanttView );
393 updateFreeBusyData( item );
396 mGanttView->setSelected( item,
true );
398 updateStatusSummary();
399 emit updateAttendeeSummary( mGanttView->childCount() );
402 void KOEditorFreeBusy::clearAttendees()
408 void KOEditorFreeBusy::setUpdateEnabled(
bool enabled )
410 mGanttView->setUpdateEnabled( enabled );
413 bool KOEditorFreeBusy::updateEnabled()
const
415 return mGanttView->getUpdateEnabled();
419 void KOEditorFreeBusy::readEvent(
Event *event )
421 bool block = updateEnabled();
422 setUpdateEnabled(
false );
426 mIsOrganizer = KOPrefs::instance()->thatIsMe( event->organizer().email() );
427 updateStatusSummary();
429 KOAttendeeEditor::readEvent( event );
431 setUpdateEnabled( block );
432 emit updateAttendeeSummary( mGanttView->childCount() );
435 void KOEditorFreeBusy::slotIntervalColorRectangleMoved(
const TQDateTime& start,
const TQDateTime& end )
437 kdDebug() << k_funcinfo <<
"slotIntervalColorRectangleMoved " << start <<
"," << end << endl;
440 emit dateTimesChanged( start, end );
443 void KOEditorFreeBusy::setDateTimes(
const TQDateTime &start,
const TQDateTime &end )
445 slotUpdateGanttView( start, end );
448 void KOEditorFreeBusy::slotScaleChanged(
int newScale )
451 KDGanttView::Scale scale =
static_cast<KDGanttView::Scale
>( newScale+1 );
452 mGanttView->setScale( scale );
456 void KOEditorFreeBusy::slotCenterOnStart()
458 mGanttView->centerTimeline( mDtStart );
461 void KOEditorFreeBusy::slotZoomToTime()
463 mGanttView->zoomToFit();
466 void KOEditorFreeBusy::updateFreeBusyData( FreeBusyItem* item )
468 if ( item->isDownloading() )
472 if ( item->updateTimerID() != 0 )
474 killTimer( item->updateTimerID() );
478 item->setUpdateTimerID( startTimer( 5000 ) );
481 void KOEditorFreeBusy::timerEvent( TQTimerEvent* event )
483 killTimer( event->timerId() );
484 FreeBusyItem *item =
static_cast<FreeBusyItem *
>( mGanttView->firstChild() );
486 if( item->updateTimerID() ==
event->timerId() ) {
487 item->setUpdateTimerID( 0 );
488 item->startDownload( mForceDownload );
491 item =
static_cast<FreeBusyItem *
>( item->nextSibling() );
498 const TQString &email )
500 kdDebug(5850) <<
"KOEditorFreeBusy::slotInsertFreeBusy() " << email << endl;
504 bool block = mGanttView->getUpdateEnabled();
505 mGanttView->setUpdateEnabled(
false );
506 for( KDGanttViewItem *it = mGanttView->firstChild(); it;
507 it = it->nextSibling() ) {
508 FreeBusyItem *item =
static_cast<FreeBusyItem *
>( it );
509 if( item->email() == email )
510 item->setFreeBusyPeriods( fb );
512 mGanttView->setUpdateEnabled( block );
520 void KOEditorFreeBusy::slotUpdateGanttView(
const TQDateTime &dtFrom,
const TQDateTime &dtTo )
524 bool block = mGanttView->getUpdateEnabled( );
525 mGanttView->setUpdateEnabled(
false );
526 TQDateTime horizonStart = TQDateTime( dtFrom.addDays( -15 ).date() );
527 mGanttView->setHorizonStart( horizonStart );
528 mGanttView->setHorizonEnd( dtTo.addDays( 15 ) );
529 mEventRectangle->setDateTimes( dtFrom, dtTo );
530 mGanttView->setUpdateEnabled( block );
531 mGanttView->centerTimelineAfterShow( dtFrom );
538 void KOEditorFreeBusy::slotPickDate()
540 TQDateTime start = mDtStart;
541 TQDateTime end = mDtEnd;
542 bool success = findFreeSlot( start, end );
545 if ( start == mDtStart && end == mDtEnd ) {
546 KMessageBox::information(
this,
547 i18n(
"The meeting already has suitable start/end times." ), TQString(),
548 "MeetingTimeOKFreeBusy" );
550 if ( KMessageBox::questionYesNo(
552 i18n(
"<qt>The next available time slot for the meeting is:<br>"
553 "Start: %1<br>End: %2<br>"
554 "Would you like to move the meeting to this time slot?</qt>" ).
555 arg( start.toString(), end.toString() ),
557 KStdGuiItem::yes(), KStdGuiItem::no(),
558 "MeetingMovedFreeBusy" ) == KMessageBox::Yes ) {
559 emit dateTimesChanged( start, end );
560 slotUpdateGanttView( start, end );
564 KMessageBox::sorry(
this, i18n(
"No suitable date found." ) );
572 bool KOEditorFreeBusy::findFreeSlot( TQDateTime &dtFrom, TQDateTime &dtTo )
574 if( tryDate( dtFrom, dtTo ) )
578 TQDateTime tryFrom = dtFrom;
579 TQDateTime tryTo = dtTo;
583 if( tryFrom < TQDateTime::currentDateTime() ) {
585 int secs = tryFrom.secsTo( tryTo );
586 tryFrom = TQDateTime::currentDateTime();
587 tryTo = tryFrom.addSecs( secs );
592 found = tryDate( tryFrom, tryTo );
594 if( !found && dtFrom.daysTo( tryFrom ) > 365 )
613 bool KOEditorFreeBusy::tryDate( TQDateTime& tryFrom, TQDateTime& tryTo )
615 FreeBusyItem* currentItem =
static_cast<FreeBusyItem*
>( mGanttView->firstChild() );
616 while( currentItem ) {
617 if( !tryDate( currentItem, tryFrom, tryTo ) ) {
622 currentItem =
static_cast<FreeBusyItem*
>( currentItem->nextSibling() );
635 bool KOEditorFreeBusy::tryDate( FreeBusyItem *attendee,
636 TQDateTime &tryFrom, TQDateTime &tryTo )
645 TQValueList<KCal::Period> busyPeriods = fb->busyPeriods();
646 for( TQValueList<KCal::Period>::Iterator it = busyPeriods.begin();
647 it != busyPeriods.end(); ++it ) {
648 if( (*it).end() <= tryFrom ||
649 (*it).start() >= tryTo )
654 int secsDuration = tryFrom.secsTo( tryTo );
655 tryFrom = (*it).end();
656 tryTo = tryFrom.addSecs( secsDuration );
658 tryDate( attendee, tryFrom, tryTo );
667 void KOEditorFreeBusy::updateStatusSummary()
669 FreeBusyItem *aItem =
670 static_cast<FreeBusyItem *
>( mGanttView->firstChild() );
677 switch( aItem->attendee()->status() ) {
678 case Attendee::Accepted:
681 case Attendee::Tentative:
684 case Attendee::Declined:
687 case Attendee::NeedsAction:
688 case Attendee::Delegated:
689 case Attendee::Completed:
690 case Attendee::InProcess:
695 aItem =
static_cast<FreeBusyItem *
>( aItem->nextSibling() );
697 if( total > 1 && mIsOrganizer ) {
698 mStatusSummaryLabel->show();
699 mStatusSummaryLabel->setText(
700 i18n(
"Of the %1 participants, %2 have accepted, %3"
701 " have tentatively accepted, and %4 have declined.")
702 .arg( total ).arg( accepted ).arg( tentative ).arg( declined ) );
704 mStatusSummaryLabel->hide();
706 mStatusSummaryLabel->adjustSize();
709 void KOEditorFreeBusy::triggerReload()
711 mReloadTimer.start( 1000,
true );
714 void KOEditorFreeBusy::cancelReload()
719 void KOEditorFreeBusy::manualReload()
721 mForceDownload =
true;
725 void KOEditorFreeBusy::autoReload()
727 mForceDownload =
false;
731 void KOEditorFreeBusy::reload()
733 kdDebug(5850) <<
"KOEditorFreeBusy::reload()" << endl;
735 FreeBusyItem *item =
static_cast<FreeBusyItem *
>( mGanttView->firstChild() );
737 if ( mForceDownload )
738 item->startDownload( mForceDownload );
740 updateFreeBusyData( item );
742 item =
static_cast<FreeBusyItem *
>( item->nextSibling() );
746 void KOEditorFreeBusy::editFreeBusyUrl( KDGanttViewItem *i )
748 FreeBusyItem *item =
static_cast<FreeBusyItem *
>( i );
751 Attendee *attendee = item->attendee();
753 FreeBusyUrlDialog dialog( attendee,
this );
757 void KOEditorFreeBusy::writeEvent(
KCal::Event * event)
759 event->clearAttendees();
760 TQValueVector<FreeBusyItem*> toBeDeleted;
761 for ( FreeBusyItem *item =
static_cast<FreeBusyItem *
>( mGanttView->firstChild() ); item;
762 item =
static_cast<FreeBusyItem*
>( item->nextSibling() ) )
764 Attendee *attendee = item->attendee();
765 Q_ASSERT( attendee );
767 if ( attendee->email().isEmpty() ) {
768 KPIM::DistributionList list =
769 KPIM::DistributionList::findByName( TDEABC::StdAddressBook::self(), attendee->name() );
770 if ( !list.isEmpty() ) {
771 toBeDeleted.push_back( item );
772 KPIM::DistributionList::Entry::List entries = list.entries( TDEABC::StdAddressBook::self() );
773 KPIM::DistributionList::Entry::List::Iterator it( entries.begin() );
774 while ( it != entries.end() ) {
775 KPIM::DistributionList::Entry &e = ( *it );
778 insertAttendeeFromAddressee( e.addressee, attendee );
784 if ( attendee->email().endsWith(
"example.net" ) ) {
785 if ( KMessageBox::warningYesNo(
this, i18n(
"%1 does not look like a valid email address. "
786 "Are you sure you want to invite this participant?").arg( attendee->email() ),
787 i18n(
"Invalid email address") ) != KMessageBox::Yes ) {
792 event->addAttendee(
new Attendee( *attendee ) );
797 KOAttendeeEditor::writeEvent( event );
800 TQValueVector<FreeBusyItem*>::iterator it;
801 for( it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it ) {
808 KDGanttViewItem *item = mGanttView->selectedItem();
809 FreeBusyItem *aItem =
static_cast<FreeBusyItem*
>( item );
812 return aItem->attendee();
815 void KOEditorFreeBusy::updateCurrentItem()
817 FreeBusyItem* item =
static_cast<FreeBusyItem*
>( mGanttView->selectedItem() );
820 updateFreeBusyData( item );
821 updateStatusSummary();
825 void KOEditorFreeBusy::removeAttendee()
827 FreeBusyItem *item =
static_cast<FreeBusyItem*
>( mGanttView->selectedItem() );
831 FreeBusyItem *nextSelectedItem =
static_cast<FreeBusyItem*
>( item->nextSibling() );
832 if( mGanttView->childCount() == 1 )
833 nextSelectedItem = 0;
834 if( mGanttView->childCount() > 1 && item == mGanttView->lastItem() )
835 nextSelectedItem =
static_cast<FreeBusyItem*
>( mGanttView->firstChild() );
837 Attendee *delA =
new Attendee( item->attendee()->name(), item->attendee()->email(),
838 item->attendee()->RSVP(), item->attendee()->status(),
839 item->attendee()->role(), item->attendee()->uid() );
840 mdelAttendees.append( delA );
843 updateStatusSummary();
844 if( nextSelectedItem )
845 mGanttView->setSelected( nextSelectedItem,
true );
846 updateAttendeeInput();
847 emit updateAttendeeSummary( mGanttView->childCount() );
850 void KOEditorFreeBusy::clearSelection()
const
852 KDGanttViewItem *item = mGanttView->selectedItem();
854 mGanttView->setSelected( item,
false );
856 mGanttView->repaint();
862 void KOEditorFreeBusy::setSelected(
int index )
865 for( KDGanttViewItem *it = mGanttView->firstChild(); it; it = it->nextSibling() ) {
866 FreeBusyItem *item =
static_cast<FreeBusyItem*
>( it );
867 if ( count == index ) {
868 mGanttView->setSelected( item,
true );
875 int KOEditorFreeBusy::selectedIndex()
878 for ( KDGanttViewItem *it = mGanttView->firstChild(); it; it = it->nextSibling() ) {
879 FreeBusyItem *item =
static_cast<FreeBusyItem*
>( it );
880 if ( item->isSelected() ) {
888 void KOEditorFreeBusy::changeStatusForMe(KCal::Attendee::PartStat status)
890 const TQStringList myEmails = KOPrefs::instance()->allEmails();
891 for ( FreeBusyItem *item =
static_cast<FreeBusyItem *
>( mGanttView->firstChild() ); item;
892 item =
static_cast<FreeBusyItem*
>( item->nextSibling() ) )
894 for ( TQStringList::ConstIterator it2( myEmails.begin() ), end( myEmails.end() ); it2 != end; ++it2 ) {
895 if ( item->attendee()->email() == *it2 ) {
896 item->attendee()->setStatus( status );
903 void KOEditorFreeBusy::showAttendeeStatusMenu()
905 if ( mGanttView->mapFromGlobal( TQCursor::pos() ).x() > 22 )
908 popup.insertItem( SmallIcon(
"help" ), Attendee::statusName( Attendee::NeedsAction ), Attendee::NeedsAction );
909 popup.insertItem( KOGlobals::self()->smallIcon(
"ok" ), Attendee::statusName( Attendee::Accepted ), Attendee::Accepted );
910 popup.insertItem( KOGlobals::self()->smallIcon(
"no" ), Attendee::statusName( Attendee::Declined ), Attendee::Declined );
911 popup.insertItem( KOGlobals::self()->smallIcon(
"apply" ), Attendee::statusName( Attendee::Tentative ), Attendee::Tentative );
912 popup.insertItem( KOGlobals::self()->smallIcon(
"mail-forward" ), Attendee::statusName( Attendee::Delegated ), Attendee::Delegated );
913 popup.insertItem( Attendee::statusName( Attendee::Completed ), Attendee::Completed );
914 popup.insertItem( KOGlobals::self()->smallIcon(
"help" ), Attendee::statusName( Attendee::InProcess ), Attendee::InProcess );
915 popup.setItemChecked( currentAttendee()->status(),
true );
916 int status = popup.exec( TQCursor::pos() );
918 currentAttendee()->setStatus( (Attendee::PartStat)status );
920 updateAttendeeInput();
924 void KOEditorFreeBusy::listViewClicked(
int button, KDGanttViewItem * item)
926 if ( button == TQt::LeftButton && item == 0 )
930 void KOEditorFreeBusy::slotOrganizerChanged(
const TQString & newOrganizer)
932 if (newOrganizer==mCurrentOrganizer)
return;
936 bool success = KPIM::getNameAndMail( newOrganizer, name, email );
938 if (!success)
return;
941 Attendee *currentOrganizerAttendee = 0;
944 FreeBusyItem *anItem =
945 static_cast<FreeBusyItem *
>( mGanttView->firstChild() );
947 Attendee *attendee = anItem->attendee();
948 if( attendee->fullName() == mCurrentOrganizer )
949 currentOrganizerAttendee = attendee;
951 if( attendee->fullName() == newOrganizer )
952 newOrganizerAttendee = attendee;
954 anItem =
static_cast<FreeBusyItem *
>( anItem->nextSibling() );
957 int answer = KMessageBox::No;
959 if (currentOrganizerAttendee) {
960 answer = KMessageBox::questionYesNo(
this, i18n(
"You are changing the organiser of "
961 "this event, who is also attending, "
962 "do you want to change that attendee "
965 answer = KMessageBox::Yes;
968 if (answer==KMessageBox::Yes) {
969 if (currentOrganizerAttendee) {
970 removeAttendee( currentOrganizerAttendee );
973 if (!newOrganizerAttendee) {
975 insertAttendee( a,
false );
976 mnewAttendees.append( a );
981 mCurrentOrganizer = newOrganizer;
984 bool KOEditorFreeBusy::eventFilter( TQObject *watched, TQEvent *event )
986 if ( watched == mGanttView->timeHeaderWidget() &&
987 event->type() >= TQEvent::MouseButtonPress && event->type() <= TQEvent::MouseMove ) {
990 return KOAttendeeEditor::eventFilter( watched, event );
994 TQListViewItem* KOEditorFreeBusy::hasExampleAttendee()
const
996 for ( FreeBusyItem *item =
static_cast<FreeBusyItem *
>( mGanttView->firstChild() ); item;
997 item =
static_cast<FreeBusyItem*
>( item->nextSibling() ) ) {
998 Attendee *attendee = item->attendee();
999 Q_ASSERT( attendee );
1000 if ( isExampleAttendee( attendee ) )
1006 #include "koeditorfreebusy.moc"
virtual TQDateTime dtEnd() const
virtual TQDateTime dtStart() const
Common base class for attendee editor and free busy view.