bool
ICalReport::generate()
{
#if KDE_IS_VERSION(3,4,89)
    KCal::CalendarLocal cal("UTC");
#else
    KCal::CalendarLocal cal;
#endif

    if( !open())
    {
        tjWarning(i18n("Can not open ICal File '%1' for writing!")
                 .arg(fileName));
        return false;
    }

    TaskList filteredList;
    if (!filterTaskList(filteredList, 0, getHideTask(), getRollUpTask()))
        return false;

    // Make sure that parents are in front of childs. We need this later to set
    // the relation.
    filteredList.setSorting(CoreAttributesList::TreeMode, 0);
    filteredList.setSorting(CoreAttributesList::StartUp, 1);
    sortTaskList(filteredList);

    ResourceList filteredResourceList;
    if (!filterResourceList(filteredResourceList, 0, hideResource,
                            rollUpResource))
        return false;
    sortResourceList(filteredResourceList);

    QPtrDict<KCal::Todo> toDoDict;
    QPtrDict<KCal::Event> eventDict;
    for (TaskListIterator tli(filteredList); *tli != 0; ++tli)
    {
        // Generate a TODO item for each task.
        KCal::Todo* todo = generateTODO(*tli, filteredResourceList);

        // In case we have the parent in the list set the relation pointer.
        if((*tli)->getParent() && toDoDict.find((*tli)->getParent()))
            todo->setRelatedTo(toDoDict[(*tli)->getParent()]);

        // Insert the just created TODO into the calendar.
        cal.addTodo(todo);

        // Insert the TODO into the dict. We might need it as a parent.
        toDoDict.insert(*tli, todo);

        if ((*tli)->isLeaf() && !(*tli)->isMilestone())
        {
            // Generate an event item for each task.
            KCal::Event* event = generateEvent(*tli, filteredResourceList);

            // In case we have the parent in the list set the relation pointer.
            if((*tli)->getParent() && eventDict.find((*tli)->getParent()))
                event->setRelatedTo(eventDict[(*tli)->getParent()]);

            // Insert the just created EVENT into the calendar.
            cal.addEvent(event);

            // Insert the EVENT into the dict. We might need it as a parent.
            eventDict.insert(*tli, event);
        }
    }

    // Dump the calendar in ICal format into a text file.
    KCal::ICalFormat format;
    s << format.toString(&cal) << endl;

    return close();
}
void SummaryEventTester::test_Multiday()
{
    QDate today = QDate::currentDate();
    QString multidayWithTimeInProgress = "Multiday, time specified, in progress";

    KCal::CalendarLocal *cal = new KCal::CalendarLocal( KDateTime().timeSpec() );

    KCal::Event *event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays( -1 ) ) );
    event->setDtEnd( KDateTime( today.addDays( 5 ) ) );
    event->setSummary( "Multiday, allday, in progress (day 2/6)" );
    QVERIFY( cal->addEvent( event ) );

    event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays( -1 ), QTime::fromString("12:00","hh:mm") ) );
    event->setDtEnd( KDateTime( today.addDays( 5 ), QTime::fromString("12:00","hh:mm") ) );
    event->setSummary( multidayWithTimeInProgress  );
    QVERIFY( cal->addEvent( event ) );
    for ( int i = 0; i < 5; i++ ) {
        SummaryEventInfo::List events4 = SummaryEventInfo::eventsForDate( today.addDays( i ), cal );
        QCOMPARE( 1, events4.size() );
        SummaryEventInfo *ev4 = events4.at(0);

        QCOMPARE( ev4->summaryText, QString(multidayWithTimeInProgress + " (%1/7)").arg(i+2));
        QCOMPARE( ev4->timeRange, QString("00:00 - 23:59") );
//    QCOMPARE( ev4->startDate, KGlobal::locale()->formatDate( QDate( today.addDays( i ) ), KLocale::FancyLongDate ) );
        QCOMPARE( ev4->makeBold, i == 0 );

        qDeleteAll( events4 );
    }

    // Test date a multiday event in the future has to correct DaysTo set
    QString multiDayWithTimeFuture = "Multiday, with time, in the future";
    event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays( 100 ), QTime::fromString("12:00","hh:mm") ) );
    event->setDtEnd( KDateTime( today.addDays( 106 ), QTime::fromString("12:00","hh:mm") ) );
    event->setSummary( multiDayWithTimeFuture );
    QVERIFY( cal->addEvent( event ) );
    for ( int i = 100; i <= 106; i++ ) {
        SummaryEventInfo::List events5 = SummaryEventInfo::eventsForDate( today.addDays( i ), cal );
        QCOMPARE( 1, events5.size() );
        SummaryEventInfo *ev5 = events5.at(0);
        /*qDebug() << ev5->summaryText;
        qDebug() << ev5->daysToGo;
        qDebug() << i;*/

        QCOMPARE( ev5->summaryText, QString(multiDayWithTimeFuture + " (%1/7)").arg(i-100+1));
        QCOMPARE( ev5->daysToGo, QString("in %1 days").arg(i) );

        qDeleteAll( events5 );
    }

    QString multiDayAllDayInFuture = "Multiday, allday, in future";
    int multiDayFuture = 30;
    event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays( multiDayFuture ) ) );
    event->setDtEnd( KDateTime( today.addDays( multiDayFuture + 5 ) ) );
    event->setSummary( multiDayAllDayInFuture );
    QVERIFY( cal->addEvent( event ) );

    event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays( 2 ), QTime::fromString("12:00","hh:mm") ) );
    event->setDtEnd( KDateTime( today.addDays( 5 ), QTime::fromString("12:00","hh:mm") ) );
    event->setSummary( "Multiday, time specified, in future" );
    QVERIFY( cal->addEvent( event ) );

    QString multiDayAllDayStartingToday = "Multiday, allday, starting today";
    event = new KCal::Event();
    event->setDtStart( KDateTime( today ) );
    event->setDtEnd( KDateTime( today.addDays( 5 ) ) );
    event->setSummary( multiDayAllDayStartingToday );
    QVERIFY( cal->addEvent( event ) );

    event = new KCal::Event();
    event->setDtStart( KDateTime( today.addDays(-10), QTime::fromString("12:00","hh:mm") ) );
    event->setDtEnd( KDateTime( today.addDays( -5 ), QTime::fromString("10:00","hh:mm") ) );
    event->setSummary( "Some event in the past" );
    QVERIFY( cal->addEvent( event ) );

    SummaryEventInfo::List eventsToday = SummaryEventInfo::eventsForDate( today, cal );
    QCOMPARE( 2, eventsToday.size() );
    foreach( const SummaryEventInfo *ev, eventsToday ) {
        if ( ev->summaryText == multidayWithTimeInProgress + " (2/7)" ) {
            QCOMPARE( ev->timeRange, QString("00:00 - 23:59") );
            QCOMPARE( ev->startDate, QString("Today") );
            QCOMPARE( ev->daysToGo, QString("now") );
            QCOMPARE( ev->makeBold, true );
        }
        else if ( ev->summaryText == multiDayAllDayStartingToday ) {
            QVERIFY( ev->timeRange.isEmpty() );
            QCOMPARE( ev->startDate, QString("Today") );
            QCOMPARE( ev->daysToGo, QString("all day") );
            QCOMPARE( ev->makeBold, true );
        }
        else
            Q_ASSERT( false ); // unexpected event!
    }

    SummaryEventInfo::List events2 = SummaryEventInfo::eventsForDate( today.addDays( multiDayFuture ), cal );
    QCOMPARE( 1, events2.size() );
    SummaryEventInfo *ev1 = events2.at( 0 );
    QCOMPARE( ev1->summaryText, multiDayAllDayInFuture );
    QVERIFY( ev1->timeRange.isEmpty() );
    QCOMPARE( ev1->startDate, KGlobal::locale()->formatDate( QDate( today.addDays( multiDayFuture ) ) ) );
    QCOMPARE( ev1->daysToGo, QString("in %1 days").arg(multiDayFuture) );
    QCOMPARE( ev1->makeBold, false );
    // Make sure multiday is only displayed once
    for ( int i = 1; i < 30; i++ ) {
        SummaryEventInfo::List events3 = SummaryEventInfo::eventsForDate( today.addDays( multiDayFuture + i ), cal );
        foreach(SummaryEventInfo *ev, events3 ) {
            QVERIFY( ev->summaryText.contains( multiDayAllDayInFuture ) );
        }
        qDeleteAll( events3 );
    }