/* This file is part of KOrganizer. Copyright (c) 2004 Reinhold Kainhofer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include "incidencechanger.h" #include "koglobals.h" #include "koprefs.h" #include "kogroupware.h" #include "mailscheduler.h" #include #include #include #include #include bool IncidenceChanger::beginChange( Incidence *incidence, ResourceCalendar *res, const TQString &subRes ) { if ( !incidence ) { return false; } kdDebug(5850) << "IncidenceChanger::beginChange for incidence \"" << incidence->summary() << "\"" << endl; CalendarResources *calRes = dynamic_cast( mCalendar ); if ( !calRes ) { return false; } return calRes->beginChange( incidence, res, subRes ); } bool IncidenceChanger::sendGroupwareMessage( Incidence *incidence, KCal::Scheduler::Method method, KOGlobals::HowChanged action, TQWidget *parent ) { if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) && incidence->attendeeCount()>0 && !KOPrefs::instance()->mUseGroupwareCommunication ) { emit schedule( method, incidence ); return true; } else if( KOPrefs::instance()->mUseGroupwareCommunication ) { return KOGroupware::instance()->sendICalMessage( parent, method, incidence, action, false ); } return true; } void IncidenceChanger::cancelAttendees( Incidence *incidence ) { if ( KOPrefs::instance()->mUseGroupwareCommunication ) { if ( KMessageBox::questionYesNo( 0, i18n("Some attendees were removed " "from the incidence. Shall cancel messages be sent to these attendees?"), i18n( "Attendees Removed" ), i18n("Send Messages"), i18n("Do Not Send") ) == KMessageBox::Yes ) { // don't use KOGroupware::sendICalMessage here, because that asks just // a very general question "Other people are involved, send message to // them?", which isn't helpful at all in this situation. Afterwards, it // would only call the MailScheduler::performTransaction, so do this // manually. // FIXME: Groupware scheduling should be factored out to it's own class // anyway KCal::MailScheduler scheduler( mCalendar ); scheduler.performTransaction( incidence, Scheduler::Cancel ); } } } bool IncidenceChanger::endChange( Incidence *incidence, ResourceCalendar *res, const TQString &subRes ) { // FIXME: if that's a groupware incidence, and I'm not the organizer, // send out a mail to the organizer with a counterproposal instead // of actually changing the incidence. Then no locking is needed. // FIXME: if that's a groupware incidence, and the incidence was // never locked, we can't unlock it with endChange(). if ( !incidence ) { return false; } kdDebug(5850) << "IncidenceChanger::endChange for incidence \"" << incidence->summary() << "\"" << endl; CalendarResources *calRes = dynamic_cast( mCalendar ); if ( !calRes ) { return false; } return calRes->endChange( incidence, res, subRes ); } bool IncidenceChanger::deleteIncidence( Incidence *incidence, TQWidget *parent ) { if ( !incidence ) return true; kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<summary()<<"\""<clone(); emit incidenceToBeDeleted( incidence ); doDelete = mCalendar->deleteIncidence( incidence ); if ( !KOPrefs::instance()->thatIsMe( tmp->organizer().email() ) ) { const TQStringList myEmails = KOPrefs::instance()->allEmails(); bool notifyOrganizer = false; for ( TQStringList::ConstIterator it = myEmails.begin(); it != myEmails.end(); ++it ) { TQString email = *it; Attendee *me = tmp->attendeeByMail(email); if ( me ) { if ( me->status() == KCal::Attendee::Accepted || me->status() == KCal::Attendee::Delegated ) notifyOrganizer = true; Attendee *newMe = new Attendee( *me ); newMe->setStatus( KCal::Attendee::Declined ); tmp->clearAttendees(); tmp->addAttendee( newMe ); break; } } if ( !KOGroupware::instance()->doNotNotify() && notifyOrganizer ) { KCal::MailScheduler scheduler( mCalendar ); scheduler.performTransaction( tmp, Scheduler::Reply ); } //reset the doNotNotify flag KOGroupware::instance()->setDoNotNotify( false ); } emit incidenceDeleted( incidence ); } return doDelete; } bool IncidenceChanger::cutIncidences( const Incidence::List &incidences, TQWidget *parent ) { Incidence::List::ConstIterator it; bool doDelete = true; Incidence::List incsToCut; for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) { if ( *it ) { doDelete = sendGroupwareMessage( *it, KCal::Scheduler::Cancel, KOGlobals::INCIDENCEDELETED, parent ); if ( doDelete ) { emit incidenceToBeDeleted( *it ); incsToCut.append( *it ); } } } DndFactory factory( mCalendar ); if ( factory.cutIncidences( incsToCut ) ) { for ( it = incsToCut.constBegin(); it != incsToCut.constEnd(); ++it ) { emit incidenceDeleted( *it ); } return !incsToCut.isEmpty(); } else { return false; } } bool IncidenceChanger::cutIncidence( Incidence *incidence, TQWidget *parent ) { Incidence::List incidences; incidences.append( incidence ); return cutIncidences( incidences, parent ); } class IncidenceChanger::ComparisonVisitor : public IncidenceBase::Visitor { public: ComparisonVisitor() {} bool act( IncidenceBase *incidence, IncidenceBase *inc2 ) { mIncidence2 = inc2; if ( incidence ) return incidence->accept( *this ); else return (inc2 == 0); } protected: bool visit( Event *event ) { Event *ev2 = dynamic_cast(mIncidence2); if ( event && ev2 ) { return *event == *ev2; } else { // either both 0, or return false; return ( ev2 == event ); } } bool visit( Todo *todo ) { Todo *to2 = dynamic_cast( mIncidence2 ); if ( todo && to2 ) { return *todo == *to2; } else { // either both 0, or return false; return ( todo == to2 ); } } bool visit( Journal *journal ) { Journal *j2 = dynamic_cast( mIncidence2 ); if ( journal && j2 ) { return *journal == *j2; } else { // either both 0, or return false; return ( journal == j2 ); } } bool visit( FreeBusy *fb ) { FreeBusy *fb2 = dynamic_cast( mIncidence2 ); if ( fb && fb2 ) { return *fb == *fb2; } else { // either both 0, or return false; return ( fb2 == fb ); } } protected: IncidenceBase *mIncidence2; }; class IncidenceChanger::AssignmentVisitor : public IncidenceBase::Visitor { public: AssignmentVisitor() {} bool act( IncidenceBase *incidence, IncidenceBase *inc2 ) { mIncidence2 = inc2; if ( incidence ) return incidence->accept( *this ); else return false; } protected: bool visit( Event *event ) { Event *ev2 = dynamic_cast( mIncidence2 ); if ( event && ev2 ) { *event = *ev2; return true; } else { return false; } } bool visit( Todo *todo ) { Todo *to2 = dynamic_cast( mIncidence2 ); if ( todo && to2 ) { *todo = *to2; return true; } else { return false; } } bool visit( Journal *journal ) { Journal *j2 = dynamic_cast(mIncidence2); if ( journal && j2 ) { *journal = *j2; return true; } else { return false; } } bool visit( FreeBusy *fb ) { FreeBusy *fb2 = dynamic_cast( mIncidence2 ); if ( fb && fb2 ) { *fb = *fb2; return true; } else { return false; } } protected: IncidenceBase *mIncidence2; }; bool IncidenceChanger::incidencesEqual( Incidence *inc1, Incidence *inc2 ) { ComparisonVisitor v; return ( v.act( inc1, inc2 ) ); } bool IncidenceChanger::assignIncidence( Incidence *inc1, Incidence *inc2 ) { AssignmentVisitor v; return v.act( inc1, inc2 ); } bool IncidenceChanger::myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc ) { Attendee *oldMe = oldInc->attendeeByMails( KOPrefs::instance()->allEmails() ); Attendee *newMe = newInc->attendeeByMails( KOPrefs::instance()->allEmails() ); if ( oldMe && newMe && ( oldMe->status() != newMe->status() ) ) return true; return false; } bool IncidenceChanger::changeIncidence( Incidence *oldinc, Incidence *newinc, KOGlobals::WhatChanged action, TQWidget *parent ) { return changeIncidence( oldinc, newinc, action, parent, 0 ); } bool IncidenceChanger::changeIncidence( Incidence *oldinc, Incidence *newinc, KOGlobals::WhatChanged action, TQWidget *parent, int dontAskForGroupware ) { kdDebug(5850)<<"IncidenceChanger::changeIncidence for incidence \""<summary()<<"\" ( old one was \""<summary()<<"\")"<revision(); newinc->setRevision( revision + 1 ); // FIXME: Use a generic method for this! Ideally, have an interface class // for group scheduling. Each implementation could then just do what // it wants with the event. If no groupware is used,use the null // pattern... bool success = true; if ( KOPrefs::instance()->mUseGroupwareCommunication ) { success = KOGroupware::instance()->sendICalMessage( parent, KCal::Scheduler::Request, newinc, KOGlobals::INCIDENCEEDITED, attendeeStatusChanged, dontAskForGroupware ); } if ( success ) { // Accept the event changes emit incidenceChanged( oldinc, newinc, action ); } else { // revert changes assignIncidence( newinc, oldinc ); return false; } } return true; } bool IncidenceChanger::addIncidence( Incidence *incidence, ResourceCalendar *res, const TQString &subRes, TQWidget *parent ) { return addIncidence( incidence, res, subRes, parent, 0 ); } bool IncidenceChanger::addIncidence( Incidence *incidence, ResourceCalendar *res, const TQString &subRes, TQWidget *parent, int dontAskForGroupware ) { CalendarResources *stdcal = dynamic_cast( mCalendar ); if( stdcal && !stdcal->hasCalendarResources() ) { KMessageBox::sorry( parent, i18n( "No calendars found, unable to save %1 \"%2\"." ). arg( i18n( incidence->type() ) ). arg( incidence->summary() ) ); kdDebug(5850) << "IncidenceChanger: No calendars found" << endl; return false; } // FIXME: This is a nasty hack, since we need to set a parent for the // resource selection dialog. However, we don't have any UI methods // in the calendar, only in the CalendarResources::DestinationPolicy // So we need to type-cast it and extract it from the CalendarResources TQWidget *tmpparent = 0; if ( stdcal ) { tmpparent = stdcal->dialogParentWidget(); stdcal->setDialogParentWidget( parent ); } // If a ResourceCalendar isn't provided, then try to compute one // along with any subResource from the incidence. ResourceCalendar *pRes = res; TQString pSubRes = subRes; TQString pResName; if ( !pRes ) { if ( stdcal ) { pRes = stdcal->resource( incidence ); if ( pRes ) { pResName = pRes->resourceName(); if ( pRes->canHaveSubresources() ) { pSubRes = pRes->subresourceIdentifier( incidence ); pResName = pRes->labelForSubresource( pSubRes ); } } } } bool success = false; if ( stdcal && pRes && !pRes->readOnly() && pRes->subresourceWritable( pSubRes ) ) { success = stdcal->addIncidence( incidence, pRes, pSubRes ); } else { success = mCalendar->addIncidence( incidence ); } if ( !success ) { // We can have a failure if the user pressed [cancel] in the resource // selectdialog, so check the exception. ErrorFormat *e = stdcal ? stdcal->exception() : 0; if ( !e || ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel && e->errorCode() != KCal::ErrorFormat::NoWritableFound ) ) ) { TQString errMessage; if ( pResName.isEmpty() ) { errMessage = i18n( "Unable to save %1 \"%2\"." ). arg( i18n( incidence->type() ) ). arg( incidence->summary() ); } else { errMessage = i18n( "Unable to save %1 \"%2\" to calendar %3." ). arg( i18n( incidence->type() ) ). arg( incidence->summary() ). arg( pResName ); } KMessageBox::sorry( parent, errMessage ); } kdDebug(5850) << "IncidenceChanger: Can't add incidence" << endl; return false; } if ( KOPrefs::instance()->mUseGroupwareCommunication ) { if ( !KOGroupware::instance()->sendICalMessage( parent, KCal::Scheduler::Request, incidence, KOGlobals::INCIDENCEADDED, false, dontAskForGroupware ) ) { KMessageBox::sorry( parent, i18n( "Attempt to send the scheduling message failed. " "Please check your Group Scheduling settings. " "Contact your system administrator for more help.") ); } } emit incidenceAdded( incidence ); return true; } #include "incidencechanger.moc" #include "incidencechangerbase.moc"