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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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);
        }
    }
}
Exemplo n.º 4
0
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();
}
Exemplo n.º 5
0
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);
    }

}
Exemplo n.º 6
0
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") );
        }
    }
}