00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "kogroupware.h"
00038 #include "freebusymanager.h"
00039 #include "calendarview.h"
00040 #include "mailscheduler.h"
00041 #include "koprefs.h"
00042 #include "koincidenceeditor.h"
00043 #include <libemailfunctions/email.h>
00044 #include <libkcal/attendee.h>
00045 #include <libkcal/journal.h>
00046 #include <libkcal/incidenceformatter.h>
00047 #include <kdebug.h>
00048 #include <kmessagebox.h>
00049 #include <kstandarddirs.h>
00050 #include <kdirwatch.h>
00051 #include <qfile.h>
00052 #include <qregexp.h>
00053 #include <qdir.h>
00054 #include <qtimer.h>
00055
00056 FreeBusyManager *KOGroupware::mFreeBusyManager = 0;
00057
00058 KOGroupware *KOGroupware::mInstance = 0;
00059
00060 KOGroupware *KOGroupware::create( CalendarView *view,
00061 KCal::CalendarResources *calendar )
00062 {
00063 if( !mInstance )
00064 mInstance = new KOGroupware( view, calendar );
00065 return mInstance;
00066 }
00067
00068 KOGroupware *KOGroupware::instance()
00069 {
00070
00071 Q_ASSERT( mInstance );
00072 return mInstance;
00073 }
00074
00075
00076 KOGroupware::KOGroupware( CalendarView* view, KCal::CalendarResources* cal )
00077 : QObject( 0, "kmgroupware_instance" ), mView( view ), mCalendar( cal )
00078 {
00079
00080 KDirWatch* watcher = KDirWatch::self();
00081 watcher->addDir( locateLocal( "data", "korganizer/income.accepted/" ) );
00082 watcher->addDir( locateLocal( "data", "korganizer/income.tentative/" ) );
00083 watcher->addDir( locateLocal( "data", "korganizer/income.counter/" ) );
00084 watcher->addDir( locateLocal( "data", "korganizer/income.cancel/" ) );
00085 watcher->addDir( locateLocal( "data", "korganizer/income.reply/" ) );
00086 watcher->addDir( locateLocal( "data", "korganizer/income.delegated/" ) );
00087 connect( watcher, SIGNAL( dirty( const QString& ) ),
00088 this, SLOT( incomingDirChanged( const QString& ) ) );
00089
00090 QTimer::singleShot( 0, this, SLOT(initialCheckForChanges()) );
00091 }
00092
00093 void KOGroupware::initialCheckForChanges()
00094 {
00095 incomingDirChanged( locateLocal( "data", "korganizer/income.accepted/" ) );
00096 incomingDirChanged( locateLocal( "data", "korganizer/income.tentative/" ) );
00097 incomingDirChanged( locateLocal( "data", "korganizer/income.counter/" ) );
00098 incomingDirChanged( locateLocal( "data", "korganizer/income.cancel/" ) );
00099 incomingDirChanged( locateLocal( "data", "korganizer/income.reply/" ) );
00100 incomingDirChanged( locateLocal( "data", "korganizer/income.delegated/" ) );
00101 }
00102
00103 void KOGroupware::slotViewNewIncidenceChanger( IncidenceChangerBase* changer )
00104 {
00105
00106 connect( changer, SIGNAL( incidenceAdded( Incidence* ) ),
00107 mFreeBusyManager, SLOT( slotPerhapsUploadFB() ) );
00108 connect( changer, SIGNAL( incidenceChanged( Incidence*, Incidence*, int ) ),
00109 mFreeBusyManager, SLOT( slotPerhapsUploadFB() ) );
00110 connect( changer, SIGNAL( incidenceChanged( Incidence*, Incidence* ) ),
00111 mFreeBusyManager, SLOT( slotPerhapsUploadFB() ) ) ;
00112 connect( changer, SIGNAL( incidenceDeleted( Incidence * ) ),
00113 mFreeBusyManager, SLOT( slotPerhapsUploadFB() ) );
00114 }
00115
00116 FreeBusyManager *KOGroupware::freeBusyManager()
00117 {
00118 if ( !mFreeBusyManager ) {
00119 mFreeBusyManager = new FreeBusyManager( this, "freebusymanager" );
00120 mFreeBusyManager->setCalendar( mCalendar );
00121 connect( mCalendar, SIGNAL( calendarChanged() ),
00122 mFreeBusyManager, SLOT( slotPerhapsUploadFB() ) );
00123 connect( mView, SIGNAL( newIncidenceChanger( IncidenceChangerBase* ) ),
00124 this, SLOT( slotViewNewIncidenceChanger( IncidenceChangerBase* ) ) );
00125 slotViewNewIncidenceChanger( mView->incidenceChanger() );
00126 }
00127
00128 return mFreeBusyManager;
00129 }
00130
00131 void KOGroupware::incomingDirChanged( const QString& path )
00132 {
00133 const QString incomingDirName = locateLocal( "data","korganizer/" )
00134 + "income.";
00135 if ( !path.startsWith( incomingDirName ) ) {
00136 kdDebug(5850) << "incomingDirChanged: Wrong dir " << path << endl;
00137 return;
00138 }
00139 QString action = path.mid( incomingDirName.length() );
00140 while ( action.length() > 0 && action[ action.length()-1 ] == '/' )
00141
00142 action.truncate( action.length()-1 );
00143
00144
00145 QDir dir( path );
00146 const QStringList files = dir.entryList( QDir::Files );
00147 if ( files.isEmpty() )
00148
00149 return;
00150
00151
00152 QFile f( path + "/" + files[0] );
00153 if (!f.open(IO_ReadOnly)) {
00154 kdError(5850) << "Can't open file '" << files[0] << "'" << endl;
00155 return;
00156 }
00157 QTextStream t(&f);
00158 t.setEncoding( QTextStream::UnicodeUTF8 );
00159 QString receiver = KPIM::getFirstEmailAddress( t.readLine() );
00160 QString iCal = t.read();
00161
00162 f.remove();
00163
00164 ScheduleMessage *message = mFormat.parseScheduleMessage( mCalendar, iCal );
00165 if ( !message ) {
00166 QString errorMessage;
00167 if (mFormat.exception())
00168 errorMessage = i18n( "Error message: %1" ).arg( mFormat.exception()->message() );
00169 kdDebug(5850) << "MailScheduler::retrieveTransactions() Error parsing "
00170 << errorMessage << endl;
00171 KMessageBox::detailedError( mView,
00172 i18n("Error while processing an invitation or update."),
00173 errorMessage );
00174 return;
00175 }
00176
00177 KCal::Scheduler::Method method =
00178 static_cast<KCal::Scheduler::Method>( message->method() );
00179 KCal::ScheduleMessage::Status status = message->status();
00180 KCal::Incidence* incidence =
00181 dynamic_cast<KCal::Incidence*>( message->event() );
00182 KCal::MailScheduler scheduler( mCalendar );
00183 if ( action.startsWith( "accepted" ) || action.startsWith( "tentative" )
00184 || action.startsWith( "delegated" ) || action.startsWith( "counter" ) ) {
00185
00186
00187 KCal::Attendee::List attendees = incidence->attendees();
00188 KCal::Attendee::List::ConstIterator it;
00189 for ( it = attendees.begin(); it != attendees.end(); ++it ) {
00190 if( (*it)->email() == receiver ) {
00191 if ( action.startsWith( "accepted" ) )
00192 (*it)->setStatus( KCal::Attendee::Accepted );
00193 else if ( action.startsWith( "tentative" ) || action.startsWith( "counter" ) )
00194 (*it)->setStatus( KCal::Attendee::Tentative );
00195 else if ( action.startsWith( "delegated" ) )
00196 (*it)->setStatus( KCal::Attendee::Delegated );
00197 break;
00198 }
00199 }
00200 scheduler.acceptTransaction( incidence, method, status );
00201 } else if ( action.startsWith( "cancel" ) )
00202
00203 scheduler.acceptTransaction( incidence, KCal::Scheduler::Cancel, status );
00204 else if ( action.startsWith( "reply" ) )
00205 scheduler.acceptTransaction( incidence, method, status );
00206 else
00207 kdError(5850) << "Unknown incoming action " << action << endl;
00208
00209 if ( action.startsWith( "counter" ) ) {
00210 mView->editIncidence( incidence );
00211 KOIncidenceEditor *tmp = mView->editorDialog( incidence );
00212 tmp->selectInvitationCounterProposal( true );
00213 }
00214 mView->updateView();
00215 }
00216
00217 class KOInvitationFormatterHelper : public InvitationFormatterHelper
00218 {
00219 public:
00220 virtual QString generateLinkURL( const QString &id ) { return "kmail:groupware_request_" + id; }
00221 };
00222
00223
00224
00225
00226
00227
00228
00229 bool KOGroupware::sendICalMessage( QWidget* parent,
00230 KCal::Scheduler::Method method,
00231 Incidence* incidence, bool isDeleting,
00232 bool statusChanged )
00233 {
00234
00235 if( incidence->attendees().isEmpty() )
00236 return true;
00237
00238 bool isOrganizer = KOPrefs::instance()->thatIsMe( incidence->organizer().email() );
00239 int rc = 0;
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 if ( isOrganizer ) {
00255
00256
00257
00258 if ( incidence->attendees().count() > 1
00259 || incidence->attendees().first()->email() != incidence->organizer().email() ) {
00260 QString type;
00261 if( incidence->type() == "Event") type = i18n("event");
00262 else if( incidence->type() == "Todo" ) type = i18n("task");
00263 else if( incidence->type() == "Journal" ) type = i18n("journal entry");
00264 else type = incidence->type();
00265 QString txt = i18n( "This %1 includes other people. "
00266 "Should email be sent out to the attendees?" )
00267 .arg( type );
00268 rc = KMessageBox::questionYesNoCancel( parent, txt,
00269 i18n("Group Scheduling Email"), i18n("Send Email"), i18n("Do Not Send") );
00270 } else {
00271 return true;
00272 }
00273 } else if( incidence->type() == "Todo" ) {
00274 if( method == Scheduler::Request )
00275
00276 method = Scheduler::Reply;
00277
00278
00279 QString txt = i18n( "Do you want to send a status update to the "
00280 "organizer of this task?");
00281 rc = KMessageBox::questionYesNo( parent, txt, QString::null, i18n("Send Update"), i18n("Do Not Send") );
00282 } else if( incidence->type() == "Event" ) {
00283 QString txt;
00284 if ( statusChanged && method == Scheduler::Request ) {
00285 txt = i18n( "Your status as an attendee of this event "
00286 "changed. Do you want to send a status update to the "
00287 "organizer of this event?" );
00288 method = Scheduler::Reply;
00289 rc = KMessageBox::questionYesNo( parent, txt, QString::null, i18n("Send Update"), i18n("Do Not Send") );
00290 } else {
00291 if( isDeleting )
00292 txt = i18n( "You are not the organizer of this event. "
00293 "Deleting it will bring your calendar out of sync "
00294 "with the organizers calendar. Do you really want "
00295 "to delete it?" );
00296 else
00297 txt = i18n( "You are not the organizer of this event. "
00298 "Editing it will bring your calendar out of sync "
00299 "with the organizers calendar. Do you really want "
00300 "to edit it?" );
00301 rc = KMessageBox::warningYesNo( parent, txt );
00302 return ( rc == KMessageBox::Yes );
00303 }
00304 } else {
00305 kdWarning(5850) << "Groupware messages for Journals are not implemented yet!" << endl;
00306 return true;
00307 }
00308
00309 if( rc == KMessageBox::Yes ) {
00310
00311
00312 if( incidence->summary().isEmpty() )
00313 incidence->setSummary( i18n("<No summary given>") );
00314
00315
00316 KCal::MailScheduler scheduler( mCalendar );
00317 scheduler.performTransaction( incidence, method );
00318
00319 return true;
00320 } else if( rc == KMessageBox::No )
00321 return true;
00322 else
00323 return false;
00324 }
00325
00326
00327 #include "kogroupware.moc"