diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch) | |
tree | 67208f7c145782a7e90b123b982ca78d88cc2c87 /korganizer/incidencechanger.cpp | |
download | tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'korganizer/incidencechanger.cpp')
-rw-r--r-- | korganizer/incidencechanger.cpp | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/korganizer/incidencechanger.cpp b/korganizer/incidencechanger.cpp new file mode 100644 index 000000000..d440f0842 --- /dev/null +++ b/korganizer/incidencechanger.cpp @@ -0,0 +1,354 @@ +/* + This file is part of KOrganizer. + + Copyright (c) 2004 Reinhold Kainhofer <[email protected]> + + 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 Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "incidencechanger.h" +#include "koprefs.h" +#include "kogroupware.h" +#include "mailscheduler.h" + +#include <libkcal/freebusy.h> +#include <libkcal/dndfactory.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <klocale.h> + + + +bool IncidenceChanger::beginChange( Incidence * incidence ) +{ + if ( !incidence ) return false; +kdDebug(5850)<<"IncidenceChanger::beginChange for incidence \""<<incidence->summary()<<"\""<<endl; + return mCalendar->beginChange( incidence ); +} + +bool IncidenceChanger::sendGroupwareMessage( Incidence *incidence, KCal::Scheduler::Method method, bool deleting ) +{ + if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) && incidence->attendeeCount()>0 + && !KOPrefs::instance()->mUseGroupwareCommunication ) { + emit schedule( method, incidence ); + return true; + } else if( KOPrefs::instance()->mUseGroupwareCommunication ) { + // FIXME: Find a widget to use as parent, instead of 0 + return KOGroupware::instance()->sendICalMessage( 0, method, incidence, deleting ); + } + 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 schedulling should be factored out to it's own class + // anyway + KCal::MailScheduler scheduler( mCalendar ); + scheduler.performTransaction( incidence, Scheduler::Cancel ); + } + } +} + +bool IncidenceChanger::endChange( Incidence *incidence ) +{ + // 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; + return mCalendar->endChange( incidence ); +} + +bool IncidenceChanger::deleteIncidence( Incidence *incidence ) +{ + if ( !incidence ) return true; +kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<<incidence->summary()<<"\""<<endl; + bool doDelete = sendGroupwareMessage( incidence, KCal::Scheduler::Cancel ); + if( doDelete ) { + // @TODO: let Calendar::deleteIncidence do the locking... + Incidence* tmp = incidence->clone(); + emit incidenceToBeDeleted( incidence ); + doDelete = mCalendar->deleteIncidence( incidence ); + if ( !KOPrefs::instance()->thatIsMe( tmp->organizer().email() ) ) { + const QStringList myEmails = KOPrefs::instance()->allEmails(); + bool notifyOrganizer = false; + for ( QStringList::ConstIterator it = myEmails.begin(); it != myEmails.end(); ++it ) { + QString 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 ( notifyOrganizer ) { + KCal::MailScheduler scheduler( mCalendar ); + scheduler.performTransaction( tmp, Scheduler::Reply ); + } + } + emit incidenceDeleted( incidence ); + } + return doDelete; +} + +bool IncidenceChanger::cutIncidence( Incidence *incidence ) +{ + if ( !incidence ) return true; +kdDebug(5850)<<"IncidenceChanger::deleteIncidence for incidence \""<<incidence->summary()<<"\""<<endl; + bool doDelete = sendGroupwareMessage( incidence, KCal::Scheduler::Cancel ); + if( doDelete ) { + // @TODO: the factory needs to do the locking! + DndFactory factory( mCalendar ); + emit incidenceToBeDeleted( incidence ); + factory.cutIncidence( incidence ); + emit incidenceDeleted( incidence ); + } + return doDelete; +} + +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<Event*>(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<Todo*>( 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<Journal*>( 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<FreeBusy*>( 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<Event*>( mIncidence2 ); + if ( event && ev2 ) { + *event = *ev2; + return true; + } else { + return false; + } + } + bool visit( Todo *todo ) + { + Todo *to2 = dynamic_cast<Todo*>( mIncidence2 ); + if ( todo && to2 ) { + *todo = *to2; + return true; + } else { + return false; + } + } + bool visit( Journal *journal ) + { + Journal *j2 = dynamic_cast<Journal*>(mIncidence2); + if ( journal && j2 ) { + *journal = *j2; + return true; + } else { + return false; + } + } + bool visit( FreeBusy *fb ) + { + FreeBusy *fb2 = dynamic_cast<FreeBusy*>( 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, + int action ) +{ +kdDebug(5850)<<"IncidenceChanger::changeIncidence for incidence \""<<newinc->summary()<<"\" ( old one was \""<<oldinc->summary()<<"\")"<<endl; + if( incidencesEqual( newinc, oldinc ) ) { + // Don't do anything + kdDebug(5850) << "Incidence not changed\n"; + } else { + kdDebug(5850) << "Incidence changed\n"; + bool statusChanged = myAttendeeStatusChanged( oldinc, newinc ); + int revision = newinc->revision(); + newinc->setRevision( revision + 1 ); + // FIXME: Use a generic method for this! Ideally, have an interface class + // for group cheduling. Each implementation could then just do what + // it wants with the event. If no groupware is used,use the null + // pattern... + bool revert = KOPrefs::instance()->mUseGroupwareCommunication; + if ( revert && + KOGroupware::instance()->sendICalMessage( 0, + KCal::Scheduler::Request, + newinc, false, statusChanged ) ) { + // Accept the event changes + if ( action<0 ) { + emit incidenceChanged( oldinc, newinc ); + } else { + emit incidenceChanged( oldinc, newinc, action ); + } + revert = false; + } + + if ( revert ) { + assignIncidence( newinc, oldinc ); + return false; + } + } + return true; +} + +bool IncidenceChanger::addIncidence( Incidence *incidence, QWidget *parent ) +{ +kdDebug(5850)<<"IncidenceChanger::addIncidence for incidence \""<<incidence->summary()<<"\""<<endl; + if ( KOPrefs::instance()->mUseGroupwareCommunication ) { + if ( !KOGroupware::instance()->sendICalMessage( parent, + KCal::Scheduler::Request, + incidence ) ) { + kdError() << "sendIcalMessage failed." << endl; + } + } + // 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 + CalendarResources *stdcal = dynamic_cast<CalendarResources*>(mCalendar); + QWidget *tmpparent = 0; + if ( stdcal ) { + tmpparent = stdcal->dialogParentWidget(); + stdcal->setDialogParentWidget( parent ); + } + bool success = mCalendar->addIncidence( incidence ); + if ( stdcal ) { + // Reset the parent widget, otherwise we'll end up with pointers to deleted + // widgets sooner or later + stdcal->setDialogParentWidget( tmpparent ); + } + if ( !success ) { + KMessageBox::sorry( parent, i18n("Unable to save %1 \"%2\".") + .arg( i18n( incidence->type() ) ) + .arg( incidence->summary() ) ); + return false; + } + emit incidenceAdded( incidence ); + return true; +} + +#include "incidencechanger.moc" +#include "incidencechangerbase.moc" |