Пример #1
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);
        }
    }
}