KCal::Event* IncidenceConverter::convertFromAppointment( ngwt__Appointment* appointment ) { kDebug() <<"IncidenceConverter::convertFromAppointment()"; if ( !appointment ) return 0; KCal::Event *event = new KCal::Event(); if ( !convertFromCalendarItem( appointment, event ) ) { delete event; return 0; } if ( appointment->allDayEvent && (*appointment->allDayEvent) ) { event->setAllDay( true ); if ( appointment->startDay != 0 ) event->setDtStart( stringToKDateTime( appointment->startDay ).addDays( 1 ) ); if ( appointment->endDay != 0 ) //TODO: Use KDateTime::fromString()? event->setDtEnd( stringToKDateTime( appointment->endDay) ); kDebug() <<" all day event."; } else { event->setAllDay( false ); if ( appointment->startDate != 0 ) { event->setDtStart( charToKDateTime( appointment->startDate, mTimeSpec ) ); } if ( appointment->endDate != 0 ) { event->setDtEnd( charToKDateTime( appointment->endDate, mTimeSpec ) ); } } kDebug() <<"start date:" << event->dtStart(); kDebug() <<"end date:" << event->dtEnd(); if ( appointment->alarm ) { KCal::Alarm *alarm = event->newAlarm(); alarm->setStartOffset( appointment->alarm->__item * -1 ); alarm->setEnabled( appointment->alarm->enabled ); } if ( appointment->place ) event->setLocation( stringToQString( appointment->place ) ); if ( appointment->acceptLevel ) { if ( *appointment->acceptLevel == Tentative ) event->setTransparency( KCal::Event::Transparent ); else event->setTransparency( KCal::Event::Opaque ); } return event; }
int KMobileGnokii::readCalendarEntry( int index, KCal::Event &event ) { if (index < 0 || index >= GN_CALNOTE_MAX_NUMBER) return KIO::ERR_DOES_NOT_EXIST; gn_data_clear(&data); gn_calnote entry; memset(&entry, 0, sizeof(entry)); entry.location = index+1; data.calnote = &entry; data.calnote_list = &calnote_list; gn_error error = gn_sm_functions(GN_OP_GetCalendarNote, &data, &state); GNOKII_CHECK_ERROR(error); if (error != GN_ERR_NONE) return gn_error2kio_error(error); print_calnote( entry ); QDateTime dt_start = timestamp_2_QDateTime(entry.time); QDateTime dt_end = dt_start.addSecs( 60*60 ); // XXX: assume one hour event.setDtStart( dt_start ); event.setDtEnd( dt_end ); event.setSummary( QString::fromUtf8(entry.text) ); // type: switch (entry.type) { case GN_CALNOTE_MEETING: event.setCategories(i18n("MEETING")); break; case GN_CALNOTE_CALL: event.setCategories(i18n("PHONE CALL")); event.setDescription(QString::fromUtf8(entry.phone_number)); break; case GN_CALNOTE_BIRTHDAY: event.setCategories(i18n("BIRTHDAY")); break; case GN_CALNOTE_REMINDER: event.setCategories(i18n("REMINDER")); break; default: kdWarning() << "unknown calendar GN_CALNOTE_XXXX type #" << entry.type << endl; } // alarm: if (entry.alarm.enabled) { QDateTime at = timestamp_2_QDateTime(entry.alarm.timestamp); if (at.isValid() && dt_start.isValid()) { int seconds = abs(at.secsTo(dt_start)); seconds %= 60*60*24; /* max. 1 day in advance... */ KCal::Alarm *eventalarm = event.newAlarm(); eventalarm->setStartOffset(KCal::Duration(seconds)); } } // recurrence: switch (entry.recurrence) { case GN_CALNOTE_NEVER: break; case GN_CALNOTE_DAILY: event.recurrence()->setDaily(1,-1); break; case GN_CALNOTE_WEEKLY: case GN_CALNOTE_2WEEKLY: event.recurrence()->setDaily( 7 + (entry.recurrence==GN_CALNOTE_2WEEKLY ? 7:0) , -1); break; case GN_CALNOTE_MONTHLY: event.recurrence()->setMonthly(KCal::Recurrence::rMonthlyPos, 1, -1); break; case GN_CALNOTE_YEARLY: event.recurrence()->setYearly(KCal::Recurrence::rYearlyPos, 1, -1); break; default: // hourly event.recurrence()->setHourly(entry.recurrence, -1); break; } return 0; }
/****************************************************************************** * Check if any alarms are pending for a specified calendar, and display the * pending alarms. */ void AlarmDaemon::checkAlarms(ADCalendar *cal) { kdDebug(5901) << "AlarmDaemons::checkAlarms(" << cal->urlString() << ")" << endl; if(!cal->loaded() || !cal->enabled()) return; QDateTime now = QDateTime::currentDateTime(); kdDebug(5901) << " To: " << now.toString() << endl; QValueList<KCal::Alarm *> alarms = cal->alarmsTo(now); if(!alarms.count()) return; QValueList<KCal::Event *> eventsDone; for(QValueList<KCal::Alarm *>::ConstIterator it = alarms.begin(); it != alarms.end(); ++it) { KCal::Event *event = dynamic_cast<KCal::Event *>((*it)->parent()); if(!event || eventsDone.find(event) != eventsDone.end()) continue; // either not an event, or the event has already been processed eventsDone += event; const QString &eventID = event->uid(); kdDebug(5901) << "AlarmDaemon::checkAlarms(): event " << eventID << endl; // Check which of the alarms for this event are due. // The times in 'alarmtimes' corresponding to due alarms are set. // The times for non-due alarms are set invalid in 'alarmtimes'. bool recurs = event->doesRecur(); const QStringList cats = event->categories(); bool floats = (cats.find(QString::fromLatin1("DATE")) != cats.end()); QDateTime nextDateTime = event->dtStart(); if(recurs) { QString prop = event->customProperty("KALARM", "NEXTRECUR"); if(prop.length() >= 8) { // The next due recurrence time is specified QDate d(prop.left(4).toInt(), prop.mid(4, 2).toInt(), prop.mid(6, 2).toInt()); if(d.isValid()) { if(floats && prop.length() == 8) nextDateTime = d; else if(!floats && prop.length() == 15 && prop[8] == QChar('T')) { QTime t(prop.mid(9, 2).toInt(), prop.mid(11, 2).toInt(), prop.mid(13, 2).toInt()); if(t.isValid()) nextDateTime = QDateTime(d, t); } } } } if(floats) nextDateTime.setTime(mStartOfDay); QValueList<QDateTime> alarmtimes; KCal::Alarm::List alarms = event->alarms(); for(KCal::Alarm::List::ConstIterator al = alarms.begin(); al != alarms.end(); ++al) { KCal::Alarm *alarm = *al; QDateTime dt; if(alarm->enabled()) { QDateTime dt1; if(!alarm->hasTime()) { // Find the latest recurrence for the alarm. // Need to do this for alarms with offsets in order to detect // reminders due for recurrences. int offset = alarm->hasStartOffset() ? alarm->startOffset().asSeconds() : alarm->endOffset().asSeconds() + event->dtStart().secsTo(event->dtEnd()); if(offset) { dt1 = nextDateTime.addSecs(floats ? (offset / SECS_PER_DAY) * SECS_PER_DAY : offset); if(dt1 > now) dt1 = QDateTime(); } } // Get latest due repetition, or the recurrence time if none dt = nextDateTime; if(nextDateTime <= now && alarm->repeatCount() > 0) { int snoozeSecs = alarm->snoozeTime() * 60; int offset = alarm->repeatCount() * snoozeSecs; QDateTime lastRepetition = nextDateTime.addSecs(floats ? (offset / SECS_PER_DAY) * SECS_PER_DAY : offset); if(lastRepetition <= now) dt = lastRepetition; else { int repetition = nextDateTime.secsTo(now) / snoozeSecs; int offset = repetition * snoozeSecs; dt = nextDateTime.addSecs(floats ? (offset / SECS_PER_DAY) * SECS_PER_DAY : offset); } } if(!dt.isValid() || dt > now || dt1.isValid() && dt1 > dt) // already tested dt1 <= now dt = dt1; } alarmtimes.append(dt); } if(!cal->eventHandled(event, alarmtimes)) { if(notifyEvent(cal, eventID)) cal->setEventPending(event, alarmtimes); } } }
void ExchangeDownload::slotPropFindResult(KIO::Job *job) { kdDebug() << "slotPropFindResult" << endl; int error = job->error(); if(error) { job->showErrorDialog(0); finishUp(ExchangeClient::CommunicationError, job); return; } QDomDocument response = static_cast<KIO::DavJob *>(job)->response(); kdDebug() << "Response: " << endl; kdDebug() << response.toString() << endl; QDomElement prop = response.documentElement().namedItem("response") .namedItem("propstat").namedItem("prop").toElement(); KCal::Event *event = new KCal::Event(); QDomElement uidElement = prop.namedItem("uid").toElement(); if(uidElement.isNull()) { kdError() << "Error: no uid in Exchange server reply" << endl; finishUp(ExchangeClient::IllegalAppointmentError, "WebDAV server response:\n" + response.toString()); return; } event->setUid(uidElement.text()); // kdDebug() << "Got UID: " << uidElement.text() << endl; QString timezoneid = prop.namedItem("timezoneid").toElement().text(); // kdDebug() << "DEBUG: timezoneid = " << timezoneid << endl; QString timezone = prop.namedItem("timezone").toElement().text(); // kdDebug() << "DEBUG: timezone = " << timezone << endl; // mFormat is used for parsing recurrence rules. QString localTimeZoneId; if(mCalendar) { mFormat->setTimeZone(mCalendar->timeZoneId(), !mCalendar->isLocalTime()); localTimeZoneId = mCalendar->timeZoneId(); } else { localTimeZoneId = "UTC"; // If no mCalendar, stay in UTC } QString lastModified = prop.namedItem("lastmodified").toElement().text(); if(!lastModified.isEmpty()) { QDateTime dt = utcAsZone(QDateTime::fromString(lastModified, Qt::ISODate), localTimeZoneId); event->setLastModified(dt); kdDebug() << "Got lastModified:" << lastModified << ", " << dt.toString() << endl; } QString organizer = prop.namedItem("organizer").toElement().text(); // TODO: Does outlook have a common name? Or does the organizer already contain both? event->setOrganizer(organizer); // kdDebug() << "Got organizer: " << organizer << endl; // Trying to find attendees, not working yet QString contact = prop.namedItem("contact").toElement().text(); // event->setOrganizer( organizer ); // kdDebug() << "DEBUG: Got contact: " << contact << endl; // This looks promising for finding attendees // FIXME: get this to work QString to = prop.namedItem("to").toElement().text(); // kdDebug() << "DEBUG: Got to: " << to << endl; QStringList attn = QStringList::split(",", to); // This doesn't work: there can be commas between "" QStringList::iterator it; for(it = attn.begin(); it != attn.end(); ++it) { // kdDebug() << " attendee: " << (*it) << endl; QString name = ""; // KCal::Attendee* a = new KCal::Attendee( name, email ); // event->addAttendee( a ); } QString readonly = prop.namedItem("isreadonly").toElement().text(); event->setReadOnly(readonly == "1"); kdDebug() << "Got readonly: " << readonly << ":" << (readonly != "0") << endl; QString created = prop.namedItem("created").toElement().text(); if(!created.isEmpty()) { QDateTime dt = utcAsZone(QDateTime::fromString(created, Qt::ISODate), localTimeZoneId); event->setCreated(dt); kdDebug() << "got created: " << dt.toString() << endl; } QString dtstart = prop.namedItem("dtstart").toElement().text(); if(!dtstart.isEmpty()) { QDateTime dt = utcAsZone(QDateTime::fromString(dtstart, Qt::ISODate), localTimeZoneId); event->setDtStart(dt); kdDebug() << "got dtstart: " << dtstart << " becomes in timezone " << dt.toString() << endl; } QString alldayevent = prop.namedItem("alldayevent").toElement().text(); bool floats = alldayevent.toInt() != 0; event->setFloats(floats); kdDebug() << "Got alldayevent: \"" << alldayevent << "\":" << floats << endl; QString dtend = prop.namedItem("dtend").toElement().text(); if(!dtend.isEmpty()) { QDateTime dt = utcAsZone(QDateTime::fromString(dtend, Qt::ISODate), localTimeZoneId); // Outlook thinks differently about floating event timing than libkcal if(floats) dt = dt.addDays(-1); event->setDtEnd(dt); kdDebug() << "got dtend: " << dtend << " becomes in timezone " << dt.toString() << endl; } QString transparent = prop.namedItem("transparent").toElement().text(); event->setTransparency(transparent.toInt() > 0 ? KCal::Event::Transparent : KCal::Event::Opaque); // kdDebug() << "Got transparent: " << transparent << endl; QString description = prop.namedItem("textdescription").toElement().text(); event->setDescription(description); kdDebug() << "Got description: " << description << endl; QString subject = prop.namedItem("subject").toElement().text(); event->setSummary(subject); kdDebug() << "Got summary: " << subject << endl; QString location = prop.namedItem("location").toElement().text(); event->setLocation(location); // kdDebug() << "Got location: " << location << endl; QString rrule = prop.namedItem("rrule").toElement().text(); kdDebug() << "Got rrule: " << rrule << endl; if(!rrule.isEmpty()) { // Timezone should be handled automatically // because we used mFormat->setTimeZone() earlier KCal::RecurrenceRule *rr = event->recurrence()->defaultRRule(true); if(!rr || !mFormat->fromString(rr, rrule)) { kdError() << "ERROR parsing rrule " << rrule << endl; } } QDomElement keywords = prop.namedItem("Keywords").toElement(); QStringList categories; QDomNodeList list = keywords.elementsByTagNameNS("xml:", "v"); for(uint i = 0; i < list.count(); i++) { QDomElement item = list.item(i).toElement(); categories.append(item.text()); } event->setCategories(categories); // kdDebug() << "Got categories: " << categories.join( ", " ) << endl; QDomElement exdate = prop.namedItem("exdate").toElement(); KCal::DateList exdates; list = exdate.elementsByTagNameNS("xml:", "v"); for(uint i = 0; i < list.count(); i++) { QDomElement item = list.item(i).toElement(); QDate date = utcAsZone(QDateTime::fromString(item.text(), Qt::ISODate), localTimeZoneId).date(); exdates.append(date); // kdDebug() << "Got exdate: " << date.toString() << endl; } event->recurrence()->setExDates(exdates); // Exchange sentitivity values: // 0 None // 1 Personal // 2 Private // 3 Company Confidential QString sensitivity = prop.namedItem("sensitivity").toElement().text(); if(! sensitivity.isNull()) switch(sensitivity.toInt()) { case 0: event->setSecrecy(KCal::Incidence::SecrecyPublic); break; case 1: event->setSecrecy(KCal::Incidence::SecrecyPrivate); break; case 2: event->setSecrecy(KCal::Incidence::SecrecyPrivate); break; case 3: event->setSecrecy(KCal::Incidence::SecrecyConfidential); break; default: kdWarning() << "Unknown sensitivity: " << sensitivity << endl; } // kdDebug() << "Got sensitivity: " << sensitivity << endl; QString reminder = prop.namedItem("reminderoffset").toElement().text(); // kdDebug() << "Reminder offset: " << reminder << endl; if(!reminder.isEmpty()) { // Duration before event in seconds KCal::Duration offset(- reminder.toInt()); KCal::Alarm *alarm = event->newAlarm(); alarm->setStartOffset(offset); alarm->setDisplayAlarm(""); alarm->setEnabled(true); // TODO: multiple alarms; alarm->setType( KCal::Alarm::xxxx ); } /** Create a new alarm which is associated with this incidence */ //Alarm* newAlarm(); /** Add an alarm which is associated with this incidence */ //void addAlarm(Alarm*); /** point at some other event to which the event relates */ //void setRelatedTo(Incidence *relatedTo); /** Add an event which is related to this event */ //void addRelation(Incidence *); /** set the list of attachments/associated files for this event */ //void setAttachments(const QStringList &attachments); /** set resources used, such as Office, Car, etc. */ //void setResources(const QStringList &resources); /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */ //void setPriority(int priority); /** Add Attendee to this incidence. IncidenceBase takes ownership of the Attendee object. */ //void addAttendee(Attendee *a, bool doupdate=true ); // THE FOLLOWING EVENT PROPERTIES ARE NOT READ // Revision ID in webdav is a String, not an int /** set the number of revisions this event has seen */ //void setRevision(int rev); // Problem: When you sync Outlook to a Palm, the conduit splits up // multi-day events into single-day events WITH ALL THE SAME UID // Grrrrrrr. if(mCalendar) { KCal::Event *oldEvent = mCalendar->event(event->uid()); if(oldEvent) { kdWarning() << "Already got his event, replace it..." << endl; mCalendar->deleteEvent(oldEvent); } kdDebug() << "ADD EVENT" << endl; mCalendar->addEvent(event); } else { kdDebug() << "EMIT gotEvent" << endl; emit gotEvent(event, static_cast<KIO::DavJob *>(job)->url()); // mEvents->append( event ); } decreaseDownloads(); }
void Incidence::saveTo(KCal::Incidence *incidence) { KolabBase::saveTo(incidence); if(mFloatingStatus == AllDay) { // This is a floating event. Don't timezone move this one incidence->setDtStart(startDate()); incidence->setFloats(true); } else { incidence->setDtStart(utcToLocal(startDate())); incidence->setFloats(false); } incidence->setSummary(summary()); incidence->setLocation(location()); if(mHasAlarm) { KCal::Alarm *alarm = incidence->newAlarm(); alarm->setStartOffset(qRound(mAlarm * 60.0)); alarm->setEnabled(true); } if(organizer().displayName.isEmpty()) incidence->setOrganizer(organizer().smtpAddress); else incidence->setOrganizer(organizer().displayName + "<" + organizer().smtpAddress + ">"); incidence->clearAttendees(); QValueList<Attendee>::ConstIterator it; for(it = mAttendees.begin(); it != mAttendees.end(); ++it) { KCal::Attendee::PartStat status = attendeeStringToStatus((*it).status); KCal::Attendee::Role role = attendeeStringToRole((*it).role); KCal::Attendee *attendee = new KCal::Attendee((*it).displayName, (*it).smtpAddress, (*it).requestResponse, status, role); attendee->setDelegate((*it).delegate); attendee->setDelegator((*it).delegator); incidence->addAttendee(attendee); } incidence->clearAttachments(); KCal::Attachment::List::ConstIterator it2; for(it2 = mAttachments.begin(); it2 != mAttachments.end(); ++it2) { KCal::Attachment *a = (*it2); // TODO should we copy? incidence->addAttachment(a); } if(!mRecurrence.cycle.isEmpty()) { KCal::Recurrence *recur = incidence->recurrence(); // yeah, this creates it // done below recur->setFrequency( mRecurrence.interval ); if(mRecurrence.cycle == "minutely") { recur->setMinutely(mRecurrence.interval); } else if(mRecurrence.cycle == "hourly") { recur->setHourly(mRecurrence.interval); } else if(mRecurrence.cycle == "daily") { recur->setDaily(mRecurrence.interval); } else if(mRecurrence.cycle == "weekly") { QBitArray rDays = daysListToBitArray(mRecurrence.days); recur->setWeekly(mRecurrence.interval, rDays); } else if(mRecurrence.cycle == "monthly") { recur->setMonthly(mRecurrence.interval); if(mRecurrence.type == "weekday") { recur->addMonthlyPos(mRecurrence.dayNumber.toInt(), daysListToBitArray(mRecurrence.days)); } else if(mRecurrence.type == "daynumber") { recur->addMonthlyDate(mRecurrence.dayNumber.toInt()); } else kdWarning() << "Unhandled monthly recurrence type " << mRecurrence.type << endl; } else if(mRecurrence.cycle == "yearly") { recur->setYearly(mRecurrence.interval); if(mRecurrence.type == "monthday") { recur->addYearlyDate(mRecurrence.dayNumber.toInt()); for(int i = 0; i < 12; ++i) if(s_monthName[ i ] == mRecurrence.month) recur->addYearlyMonth(i + 1); } else if(mRecurrence.type == "yearday") { recur->addYearlyDay(mRecurrence.dayNumber.toInt()); } else if(mRecurrence.type == "weekday") { for(int i = 0; i < 12; ++i) if(s_monthName[ i ] == mRecurrence.month) recur->addYearlyMonth(i + 1); recur->addYearlyPos(mRecurrence.dayNumber.toInt(), daysListToBitArray(mRecurrence.days)); } else kdWarning() << "Unhandled yearly recurrence type " << mRecurrence.type << endl; } else kdWarning() << "Unhandled recurrence cycle " << mRecurrence.cycle << endl; if(mRecurrence.rangeType == "number") { recur->setDuration(mRecurrence.range.toInt()); } else if(mRecurrence.rangeType == "date") { recur->setEndDate(stringToDate(mRecurrence.range)); } // "none" is default since tje set*ly methods set infinite recurrence incidence->recurrence()->setExDates(mRecurrence.exclusions); } /* If we've stored a uid to be used internally instead of the real one * (to deal with duplicates of events in different folders) before, then * restore it, so it does not change. Keep the original uid around for * scheduling purposes. */ if(!internalUID().isEmpty()) { incidence->setUid(internalUID()); incidence->setSchedulingID(uid()); } for(QValueList<Custom>::ConstIterator it = mCustomList.begin(); it != mCustomList.end(); ++it) { incidence->setNonKDECustomProperty((*it).key, (*it).value); } }
void AlarmListViewItem::construct() { if ( mAlarm ) { // Alarm type: QString type; switch ( mAlarm->type() ) { case KCal::Alarm::Display: type = i18n("Reminder Dialog"); break; case KCal::Alarm::Procedure: type = i18n("Program"); break; case KCal::Alarm::Email: type = i18n("Email"); break; case KCal::Alarm::Audio: type = i18n("Audio"); break; default: type = i18n("Unknown"); break; } setText( ColAlarmType, type ); // Alarm offset: QString offsetstr; int offset = 0; if ( mAlarm->hasStartOffset() ) { offset = mAlarm->startOffset().asSeconds(); if ( offset < 0 ) { offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the start"); offset = -offset; } else { offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the start"); } } else if ( mAlarm->hasEndOffset() ) { offset = mAlarm->endOffset().asSeconds(); if ( offset < 0 ) { offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 before the end"); offset = -offset; } else { offsetstr = i18n("N days/hours/minutes before/after the start/end", "%1 after the end"); } } offset = offset / 60; // make minutes int useoffset = offset; if ( offset % (24*60) == 0 && offset>0 ) { // divides evenly into days? useoffset = offset / (24*60); offsetstr = offsetstr.arg( i18n("1 day", "%n days", useoffset ) ); } else if (offset % 60 == 0 && offset>0 ) { // divides evenly into hours? useoffset = offset / 60; offsetstr = offsetstr.arg( i18n("1 hour", "%n hours", useoffset ) ); } else { useoffset = offset; offsetstr = offsetstr.arg( i18n("1 minute", "%n minutes", useoffset ) ); } setText( ColAlarmOffset, offsetstr ); // Alarm repeat if ( mAlarm->repeatCount()>0 ) { setText( ColAlarmRepeat, i18n("Yes") ); } else { setText( ColAlarmRepeat, i18n("No") ); } } }