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