summaryrefslogtreecommitdiffstats
path: root/korganizer/incidencechanger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'korganizer/incidencechanger.cpp')
-rw-r--r--korganizer/incidencechanger.cpp354
1 files changed, 354 insertions, 0 deletions
diff --git a/korganizer/incidencechanger.cpp b/korganizer/incidencechanger.cpp
new file mode 100644
index 00000000..d440f084
--- /dev/null
+++ b/korganizer/incidencechanger.cpp
@@ -0,0 +1,354 @@
+/*
+ This file is part of KOrganizer.
+
+ Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+
+ 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"