void KonsoleKalendarDelete::printSpecs(const Event::Ptr &event) { cout << i18n(" UID: %1", m_variables->getUID()).data() << endl; cout << i18n(" What: %1", event->summary()).data() << endl; KDateTime::Spec timeSpec = m_variables->getCalendar()->timeSpec(); cout << i18n(" Begin: %1", event->dtStart().toTimeSpec(timeSpec).dateTime().toString(Qt::TextDate)).data() << endl; cout << i18n(" End: %1", event->dtEnd().toTimeSpec(timeSpec).dateTime().toString(Qt::TextDate)).data() << endl; cout << i18n(" Desc: %1", event->description()).data() << endl; cout << i18n(" Location: %1", event->location()).data() << endl; }
bool KonsoleKalendar::showInstance() { bool status = true; QFile f; QString title; Event::Ptr event; const KDateTime::Spec timeSpec = m_variables->getCalendar()->timeSpec(); Akonadi::CalendarBase::Ptr calendar = m_variables->getCalendar(); if (m_variables->isDryRun()) { cout << i18n("View Events <Dry Run>:").toLocal8Bit().data() << endl; printSpecs(); } else { qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" << "open export file"; if (m_variables->isExportFile()) { f.setFileName(m_variables->getExportFile()); if (!f.open(QIODevice::WriteOnly)) { status = false; qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" << "unable to open export file" << m_variables->getExportFile(); } } else { f.open(stdout, QIODevice::WriteOnly); } if (status) { qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" << "opened successful"; if (m_variables->isVerbose()) { cout << i18n("View Event <Verbose>:").toLocal8Bit().data() << endl; printSpecs(); } QTextStream ts(&f); if (m_variables->getExportType() != ExportTypeHTML && m_variables->getExportType() != ExportTypeMonthHTML) { if (m_variables->getAll()) { qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" << "view all events sorted list"; Event::List sortedList = calendar->events(EventSortStartDate); qCDebug(KONSOLEKALENDAR_LOG) << "Found" << sortedList.count() << "events"; if (!sortedList.isEmpty()) { // The code that was here before the akonadi port was really slow with 200 events // this is much faster: foreach (const KCalCore::Event::Ptr &event, sortedList) { status &= printEvent(&ts, event, event->dtStart().date()); } } } else if (m_variables->isUID()) {
void CalendarBaseTest::createInitialIncidences() { mExpectedSlotResult = true; for (int i=0; i<5; ++i) { Event::Ptr event = Event::Ptr(new Event()); event->setUid(QStringLiteral("event") + QString::number(i)); event->setSummary(QStringLiteral("summary") + QString::number(i)); event->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(event->uid()); QVERIFY(mCalendar->addEvent(event)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneEventUid = mUids.last(); for (int i=0; i<5; ++i) { Todo::Ptr todo = Todo::Ptr(new Todo()); todo->setUid(QStringLiteral("todo") + QString::number(i)); todo->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); todo->setSummary(QStringLiteral("summary") + QString::number(i)); mUids.append(todo->uid()); QVERIFY(mCalendar->addTodo(todo)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneTodoUid = mUids.last(); for (int i=0; i<5; ++i) { Journal::Ptr journal = Journal::Ptr(new Journal()); journal->setUid(QStringLiteral("journal") + QString::number(i)); journal->setSummary(QStringLiteral("summary") + QString::number(i)); journal->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(journal->uid()); QVERIFY(mCalendar->addJournal(journal)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneJournalUid = mUids.last(); for (int i=0; i<5; ++i) { Incidence::Ptr incidence = Incidence::Ptr(new Event()); incidence->setUid(QStringLiteral("incidence") + QString::number(i)); incidence->setSummary(QStringLiteral("summary") + QString::number(i)); incidence->setDtStart(KDateTime::currentDateTime(KDateTime::UTC)); mUids.append(incidence->uid()); QVERIFY(mCalendar->addIncidence(incidence)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } mOneIncidenceUid = mUids.last(); }
bool EventDispatcher::emitEvent(Event::Ptr event) { if(event.isNull()) { MTQ_WARNING << "Could not dispatch NULL event."; return false; } TypeId currentTypeId = event->typeId(); while(currentTypeId.key()) { getOrCreateEmitter(currentTypeId)->emitEvent(event); currentTypeId = currentTypeId.parent(); } return true; }
bool KonsoleKalendarDelete::deleteEvent() { bool status = false; qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendardelete.cpp::deleteEvent()"; /* * Retrieve event on the basis of the unique string ID */ Event::Ptr event = m_variables->getCalendar()->event(m_variables->getUID()); if (event) { if (m_variables->isDryRun()) { cout << i18n("Delete Event <Dry Run>:").data() << endl; printSpecs(event); } else { qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendardelete.cpp:deleteEvent() :" << m_variables->getUID().data(); if (m_variables->isVerbose()) { cout << i18n("Delete Event <Verbose>:").data() << endl; printSpecs(event); } QEventLoop loop; Akonadi::CalendarBase::Ptr calendar = m_variables->getCalendar(); QObject::connect(calendar.data(), &Akonadi::CalendarBase::deleteFinished, &loop, &QEventLoop::quit); calendar->deleteEvent(event); loop.exec(); qCDebug(KONSOLEKALENDAR_LOG) << "Finished deleting"; status = calendar->incidence(event->uid()) == 0; if (status) { cout << i18n("Success: \"%1\" deleted", event->summary()).data() << endl; } else { cout << i18n("Error deleting: \"%1\"", event->summary()).data() << endl; } } } qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendardelete.cpp::deleteEvent() | Done"; return status; }
void DndFactoryTest::testPasteAllDayEvent() { MemoryCalendar::Ptr calendar( new MemoryCalendar( QString() ) ); DndFactory factory( calendar ); Event::Ptr allDayEvent( new Event() ); allDayEvent->setSummary( QLatin1String( "Summary 1" ) ); allDayEvent->setDtStart( KDateTime( QDate( 2010, 8, 8 ) ) ); allDayEvent->setDtEnd( KDateTime( QDate( 2010, 8, 9 ) ) ); const QString originalUid = allDayEvent->uid(); const bool originalIsAllDay = allDayEvent->allDay(); Incidence::List incidencesToPaste; incidencesToPaste.append( allDayEvent ); QVERIFY( factory.copyIncidences( incidencesToPaste ) ); Incidence::List pastedIncidences = factory.pasteIncidences(); QVERIFY( pastedIncidences.size() == 1 ); Incidence::Ptr incidence = pastedIncidences.first(); QVERIFY( incidence->type() == Incidence::TypeEvent ); // check if a new uid was generated. QVERIFY( incidence->uid() != originalUid ); // we passed an invalid KDateTime to pasteIncidences() so dates don't change. QVERIFY( incidence->allDay() == originalIsAllDay ); Event::Ptr pastedEvent = incidence.staticCast<Event>(); QVERIFY( pastedEvent->dtStart() == allDayEvent->dtStart() ); QVERIFY( pastedEvent->dtEnd() == allDayEvent->dtEnd() ); QVERIFY( pastedEvent->summary() == allDayEvent->summary() ); }
void DndFactoryTest::testPasteAllDayEvent2() { MemoryCalendar::Ptr calendar( new MemoryCalendar( QString() ) ); DndFactory factory( calendar ); Event::Ptr allDayEvent( new Event() ); allDayEvent->setSummary( QLatin1String( "Summary 2" ) ); allDayEvent->setDtStart( KDateTime( QDate( 2010, 8, 8 ) ) ); allDayEvent->setDtEnd( KDateTime( QDate( 2010, 8, 9 ) ) ); const QString originalUid = allDayEvent->uid(); Incidence::List incidencesToPaste; incidencesToPaste.append( allDayEvent ); QVERIFY( factory.copyIncidences( incidencesToPaste ) ); const KDateTime newDateTime( QDate( 2011, 1, 1 ) ); const uint originalLength = allDayEvent->dtStart().secsTo( allDayEvent->dtEnd() ); // paste at the new time Incidence::List pastedIncidences = factory.pasteIncidences( newDateTime ); // we only copied one incidence QVERIFY( pastedIncidences.size() == 1 ); Incidence::Ptr incidence = pastedIncidences.first(); QVERIFY( incidence->type() == Incidence::TypeEvent ); // check if a new uid was generated. QVERIFY( incidence->uid() != originalUid ); // the new dateTime didn't have time component QVERIFY( incidence->allDay() ); Event::Ptr pastedEvent = incidence.staticCast<Event>(); const uint newLength = pastedEvent->dtStart().secsTo( pastedEvent->dtEnd() ); kDebug() << "originalLength was " << originalLength << "; and newLength is " << newLength << "; old dtStart was " << allDayEvent->dtStart() << " and old dtEnd was " << allDayEvent->dtEnd() << endl << "; new dtStart is " << pastedEvent->dtStart() << " and new dtEnd is " << pastedEvent->dtEnd(); QVERIFY( originalLength == newLength ); QVERIFY( pastedEvent->dtStart() == newDateTime ); QVERIFY( pastedEvent->summary() == allDayEvent->summary() ); }
CallId Scheduler::acceptReply( const IncidenceBase::Ptr &incidence, ScheduleMessage::Status status, iTIPMethod method ) { Q_UNUSED( status ); if ( incidence->type() == IncidenceBase::TypeFreeBusy ) { return acceptFreeBusy( incidence, method ); } const CallId callId = ++d->mLatestCallId; ResultCode resultCode = ResultCodeIncidenceOrAttendeeNotFound; QString errorMessage; Event::Ptr ev = d->mCalendar->event( incidence->uid() ); Todo::Ptr to = d->mCalendar->todo( incidence->uid() ); // try harder to find the correct incidence if ( !ev && !to ) { const Incidence::List list = d->mCalendar->incidences(); for ( Incidence::List::ConstIterator it=list.constBegin(), end=list.constEnd(); it != end; ++it ) { if ( (*it)->schedulingID() == incidence->uid() ) { ev = ( *it ).dynamicCast<Event>(); to = ( *it ).dynamicCast<Todo>(); break; } } } if ( ev || to ) { //get matching attendee in calendar kDebug() << "match found!"; Attendee::List attendeesIn = incidence->attendees(); Attendee::List attendeesEv; Attendee::List attendeesNew; if ( ev ) { attendeesEv = ev->attendees(); } if ( to ) { attendeesEv = to->attendees(); } Attendee::List::ConstIterator inIt; Attendee::List::ConstIterator evIt; for ( inIt = attendeesIn.constBegin(); inIt != attendeesIn.constEnd(); ++inIt ) { Attendee::Ptr attIn = *inIt; bool found = false; for ( evIt = attendeesEv.constBegin(); evIt != attendeesEv.constEnd(); ++evIt ) { Attendee::Ptr attEv = *evIt; if ( attIn->email().toLower() == attEv->email().toLower() ) { //update attendee-info kDebug() << "update attendee"; attEv->setStatus( attIn->status() ); attEv->setDelegate( attIn->delegate() ); attEv->setDelegator( attIn->delegator() ); resultCode = ResultCodeSuccess; found = true; } } if ( !found && attIn->status() != Attendee::Declined ) { attendeesNew.append( attIn ); } } bool attendeeAdded = false; for ( Attendee::List::ConstIterator it = attendeesNew.constBegin(); it != attendeesNew.constEnd(); ++it ) { Attendee::Ptr attNew = *it; QString msg = i18nc( "@info", "%1 wants to attend %2 but was not invited.", attNew->fullName(), ( ev ? ev->summary() : to->summary() ) ); if ( !attNew->delegator().isEmpty() ) { msg = i18nc( "@info", "%1 wants to attend %2 on behalf of %3.", attNew->fullName(), ( ev ? ev->summary() : to->summary() ), attNew->delegator() ); } if ( KMessageBox::questionYesNo( 0, msg, i18nc( "@title", "Uninvited attendee" ), KGuiItem( i18nc( "@option", "Accept Attendance" ) ), KGuiItem( i18nc( "@option", "Reject Attendance" ) ) ) != KMessageBox::Yes ) { Incidence::Ptr cancel = incidence.dynamicCast<Incidence>(); if ( cancel ) { cancel->addComment( i18nc( "@info", "The organizer rejected your attendance at this meeting." ) ); } performTransaction( incidence, iTIPCancel, attNew->fullName() ); // ### can't delete cancel here because it is aliased to incidence which // is accessed in the next loop iteration (CID 4232) // delete cancel; continue; } Attendee::Ptr a( new Attendee( attNew->name(), attNew->email(), attNew->RSVP(), attNew->status(), attNew->role(), attNew->uid() ) ); a->setDelegate( attNew->delegate() ); a->setDelegator( attNew->delegator() ); if ( ev ) { ev->addAttendee( a ); } else if ( to ) { to->addAttendee( a ); } resultCode = ResultCodeSuccess; attendeeAdded = true; } // send update about new participants if ( attendeeAdded ) { bool sendMail = false; if ( ev || to ) { if ( KMessageBox::questionYesNo( 0, i18nc( "@info", "An attendee was added to the incidence. " "Do you want to email the attendees an update message?" ), i18nc( "@title", "Attendee Added" ), KGuiItem( i18nc( "@option", "Send Messages" ) ), KGuiItem( i18nc( "@option", "Do Not Send" ) ) ) == KMessageBox::Yes ) { sendMail = true; } } if ( ev ) { ev->setRevision( ev->revision() + 1 ); if ( sendMail ) { performTransaction( ev, iTIPRequest ); } } if ( to ) { to->setRevision( to->revision() + 1 ); if ( sendMail ) { performTransaction( to, iTIPRequest ); } } } if ( resultCode == ResultCodeSuccess ) { // We set at least one of the attendees, so the incidence changed // Note: This should not result in a sequence number bump if ( ev ) { ev->updated(); } else if ( to ) { to->updated(); } } if ( to ) { // for VTODO a REPLY can be used to update the completion status of // a to-do. see RFC2446 3.4.3 Todo::Ptr update = incidence.dynamicCast<Todo>(); Q_ASSERT( update ); if ( update && ( to->percentComplete() != update->percentComplete() ) ) { to->setPercentComplete( update->percentComplete() ); to->updated(); } } } else { kError() << "No incidence for scheduling."; } if ( resultCode == ResultCodeSuccess ) { deleteTransaction( incidence->uid() ); } emitOperationFinished( callId, resultCode, errorMessage ); return callId; }
Incidence::Ptr pasteIncidence( const Incidence::Ptr &incidence, KDateTime newDateTime, const QFlags<PasteFlag> &pasteOptions ) { Incidence::Ptr inc( incidence ); if ( inc ) { inc = Incidence::Ptr( inc->clone() ); inc->recreate(); } if ( inc && newDateTime.isValid() ) { if ( inc->type() == Incidence::TypeEvent ) { Event::Ptr event = inc.staticCast<Event>(); if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = event->dtStart(); newDateTime.setDate( date ); } // in seconds const int durationInSeconds = event->dtStart().secsTo( event->dtEnd() ); const int durationInDays = event->dtStart().daysTo( event->dtEnd() ); event->setDtStart( newDateTime ); if ( newDateTime.isDateOnly() ) { event->setDtEnd( newDateTime.addDays( durationInDays ) ); } else { event->setDtEnd( newDateTime.addSecs( durationInSeconds ) ); } } else if ( inc->type() == Incidence::TypeTodo ) { Todo::Ptr aTodo = inc.staticCast<Todo>(); const bool pasteAtDtStart = ( pasteOptions & FlagTodosPasteAtDtStart ); if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = pasteAtDtStart ? aTodo->dtStart() : aTodo->dtDue(); newDateTime.setDate( date ); } if ( pasteAtDtStart ) { aTodo->setDtStart( newDateTime ); } else { aTodo->setDtDue( newDateTime ); } } else if ( inc->type() == Incidence::TypeJournal ) { if ( pasteOptions & FlagPasteAtOriginalTime ) { // Set date and preserve time and timezone stuff const QDate date = newDateTime.date(); newDateTime = inc->dtStart(); newDateTime.setDate( date ); } inc->setDtStart( newDateTime ); } else { kDebug() << "Trying to paste unknown incidence of type" << int( inc->type() ); } } return inc; }
//@cond PRIVATE void FreeBusy::Private::init( const Event::List &eventList, const KDateTime &start, const KDateTime &end ) { int extraDays, i, x, duration; duration = start.daysTo( end ); QDate day; KDateTime tmpStart; KDateTime tmpEnd; // Loops through every event in the calendar Event::List::ConstIterator it; for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) { Event::Ptr event = *it; // If this event is transparent it shouldn't be in the freebusy list. if ( event->transparency() == Event::Transparent ) { continue; } // The code below can not handle all-day events. Fixing this resulted // in a lot of duplicated code. Instead, make a copy of the event and // set the period to the full day(s). This trick works for recurring, // multiday, and single day all-day events. Event::Ptr allDayEvent; if ( event->allDay() ) { // addDay event. Do the hack kDebug() << "All-day event"; allDayEvent = Event::Ptr( new Event( *event ) ); // Set the start and end times to be on midnight KDateTime st = allDayEvent->dtStart(); st.setTime( QTime( 0, 0 ) ); KDateTime nd = allDayEvent->dtEnd(); nd.setTime( QTime( 23, 59, 59, 999 ) ); allDayEvent->setAllDay( false ); allDayEvent->setDtStart( st ); allDayEvent->setDtEnd( nd ); kDebug() << "Use:" << st.toString() << "to" << nd.toString(); // Finally, use this event for the setting below event = allDayEvent; } // This whole for loop is for recurring events, it loops through // each of the days of the freebusy request for ( i = 0; i <= duration; ++i ) { day = start.addDays( i ).date(); tmpStart.setDate( day ); tmpEnd.setDate( day ); if ( event->recurs() ) { if ( event->isMultiDay() ) { // FIXME: This doesn't work for sub-daily recurrences or recurrences with // a different time than the original event. extraDays = event->dtStart().daysTo( event->dtEnd() ); for ( x = 0; x <= extraDays; ++x ) { if ( event->recursOn( day.addDays( -x ), start.timeSpec() ) ) { tmpStart.setDate( day.addDays( -x ) ); tmpStart.setTime( event->dtStart().time() ); tmpEnd = event->duration().end( tmpStart ); addLocalPeriod( q, tmpStart, tmpEnd ); break; } } } else { if ( event->recursOn( day, start.timeSpec() ) ) { tmpStart.setTime( event->dtStart().time() ); tmpEnd.setTime( event->dtEnd().time() ); addLocalPeriod ( q, tmpStart, tmpEnd ); } } } } // Non-recurring events addLocalPeriod( q, event->dtStart(), event->dtEnd() ); } q->sortList(); }
void ICalFormatTest::testCharsets() { ICalFormat format; const QDate currentDate = QDate::currentDate(); Event::Ptr event = Event::Ptr( new Event() ); event->setUid( "12345" ); event->setDtStart( KDateTime( currentDate ) ); event->setDtEnd( KDateTime( currentDate.addDays( 1 ) ) ); // ΓΌ const QChar latin1_umlaut[] = { 0xFC, '\0' }; event->setSummary( QString( latin1_umlaut ) ); // Test if toString( Incidence ) didn't mess charsets const QString serialized = format.toString( event.staticCast<Incidence>() ); const QChar utf_umlaut[] = { 0xC3, 0XBC, '\0' }; QVERIFY( serialized.toUtf8().contains( QString( utf_umlaut ).toLatin1().constData() ) ); QVERIFY( !serialized.toUtf8().contains( QString( latin1_umlaut ).toLatin1().constData() ) ); QVERIFY( serialized.toLatin1().contains( QString( latin1_umlaut ).toLatin1().constData() ) ); QVERIFY( !serialized.toLatin1().contains( QString( utf_umlaut ).toLatin1().constData() ) ); // test fromString( QString ) const QString serializedCalendar = "BEGIN:VCALENDAR\nPRODID:-//K Desktop Environment//NONSGML libkcal 3.2//EN\nVERSION:2.0\n" + serialized + "\nEND:VCALENDAR"; Incidence::Ptr event2 = format.fromString( serializedCalendar ); QVERIFY( event->summary() == event2->summary() ); QVERIFY( event2->summary().toUtf8() == QByteArray( QString( utf_umlaut ).toLatin1().constData() ) ); // test save() MemoryCalendar::Ptr calendar( new MemoryCalendar( "UTC" ) ); calendar->addIncidence( event ); QVERIFY( format.save( calendar, "hommer.ics" ) ); // Make sure hommer.ics is in UTF-8 QFile file( "hommer.ics" ); QVERIFY( file.open( QIODevice::ReadOnly | QIODevice::Text ) ); const QByteArray bytesFromFile = file.readAll(); QVERIFY( bytesFromFile.contains( QString( utf_umlaut ).toLatin1().constData() ) ); QVERIFY( !bytesFromFile.contains( QString( latin1_umlaut ).toLatin1().constData() ) ); file.close(); // Test load: MemoryCalendar::Ptr calendar2( new MemoryCalendar( "UTC" ) ); QVERIFY( format.load( calendar2, "hommer.ics" ) ); QVERIFY( calendar2->incidences().count() == 1 ); // kDebug() << format.toString( event.staticCast<Incidence>() ); // kDebug() << format.toString( calendar2->incidences().first() ); Event::Ptr loadedEvent = calendar2->incidences().first().staticCast<Event>(); QVERIFY( loadedEvent->summary().toUtf8() == QByteArray( QString( utf_umlaut ).toLatin1().constData() ) ); QVERIFY( *loadedEvent == *event ); // Test fromRawString() MemoryCalendar::Ptr calendar3( new MemoryCalendar( "UTC" ) ); format.fromRawString( calendar3, bytesFromFile ); QVERIFY( calendar3->incidences().count() == 1 ); QVERIFY( *calendar3->incidences().first() == *event ); unlink( "hommer.ics" ); }
void HtmlExport::createEvent(QTextStream *ts, const Event::Ptr &event, QDate date, bool withDescription) { qCDebug(KCALUTILS_LOG) << event->summary(); *ts << " <tr>" << endl; if (!event->allDay()) { if (event->isMultiDay(d->mCalendar->timeSpec()) && (event->dtStart().date() != date)) { *ts << " <td> </td>" << endl; } else { *ts << " <td valign=\"top\">" << Stringify::formatTime(event->dtStart(), true, d->mCalendar->timeSpec()) << "</td>" << endl; } if (event->isMultiDay(d->mCalendar->timeSpec()) && (event->dtEnd().date() != date)) { *ts << " <td> </td>" << endl; } else { *ts << " <td valign=\"top\">" << Stringify::formatTime(event->dtEnd(), true, d->mCalendar->timeSpec()) << "</td>" << endl; } } else { *ts << " <td> </td><td> </td>" << endl; } *ts << " <td class=\"sum\">" << endl; *ts << " <b>" << cleanChars(event->summary()) << "</b>" << endl; if (withDescription && !event->description().isEmpty()) { *ts << " <p>" << breakString(cleanChars(event->description())) << "</p>" << endl; } *ts << " </td>" << endl; if (d->mSettings->eventLocation()) { *ts << " <td>" << endl; formatLocation(ts, event); *ts << " </td>" << endl; } if (d->mSettings->eventCategories()) { *ts << " <td>" << endl; formatCategories(ts, event); *ts << " </td>" << endl; } if (d->mSettings->eventAttendees()) { *ts << " <td>" << endl; formatAttendees(ts, event); *ts << " </td>" << endl; } *ts << " </tr>" << endl; }