//! @return "opened x minutes ago" string or similar static QString openedString(const QDateTime& _opened) { const KDateTime cur(KDateTime::currentUtcDateTime()); const KDateTime opened = KDateTime(_opened); if (!opened.isValid() || opened >= cur) return QString(); const int days = opened.daysTo(cur); if (days <= 1 && opened.secsTo(cur) < 24*60*60) { const int minutes = opened.secsTo(cur) / 60; const int hours = minutes / 60; if (hours < 1) { if (minutes == 0) return i18n("Opened less than minute ago"); else return i18np("Opened 1 minute ago", "Opened %1 minutes ago", minutes); } else { return i18np("Opened 1 hour ago", "Opened %1 hours ago", hours); } } else { if (days < 30) return i18np("Opened yesterday", "Opened %1 days ago", days); if (days < 365) return i18np("Opened over a month ago", "Opened %1 months ago", days / 30); return i18np("Opened one year ago", "Opened %1 years ago", days / 365); } return QString(); }
SummaryEventInfo::List SummaryEventInfo::eventsForDate( const QDate &date, KCal::Calendar *calendar ) { KCal::Event *ev; KCal::Event::List events = calendar->events( date, calendar->timeSpec() ); KCal::Event::List::ConstIterator it = events.constBegin(); KDateTime qdt; KDateTime::Spec spec = KSystemTimeZones::local(); KDateTime currentDateTime = KDateTime::currentDateTime( spec ); QDate currentDate = currentDateTime.date(); // sort the events for this date by summary events = KCal::Calendar::sortEvents( &events, KCal::EventSortSummary, KCal::SortDirectionAscending ); // sort the events for this date by start date events = KCal::Calendar::sortEvents( &events, KCal::EventSortStartDate, KCal::SortDirectionAscending ); List eventInfoList; for ( it=events.constBegin(); it != events.constEnd(); ++it ) { ev = *it; int daysTo = -1; // Count number of days remaining in multiday event int span = 1; int dayof = 1; if ( ev->isMultiDay() ) { QDate d = ev->dtStart().date(); if ( d < currentDate ) { dayof += d.daysTo( currentDate ); span += d.daysTo( currentDate ); d = currentDate; } while ( d < ev->dtEnd().date() ) { if ( d < date ) { dayof++; } span++; d = d.addDays( 1 ); } } QDate startOfMultiday = ev->dtStart().date(); if ( startOfMultiday < currentDate ) { startOfMultiday = currentDate; } bool firstDayOfMultiday = ( date == startOfMultiday ); // If this date is part of a floating, multiday event, then we // only make a print for the first day of the event. if ( ev->isMultiDay() && ev->allDay() && ( currentDate > ev->dtStart().date() || !firstDayOfMultiday ) ) { continue; } // If the event is already over, then it isn't upcoming. so don't print it. if ( !ev->allDay() ) { if ( ev->recurs() ) { KDateTime kdt( date, QTime( 0, 0, 0 ), KSystemTimeZones::local() ); kdt = kdt.addSecs( -1 ); if ( currentDateTime > ev->recurrence()->getNextDateTime( kdt ) ) { continue; } } else { if ( currentDateTime > ev->dtEnd() ) { continue; } } } SummaryEventInfo *summaryEvent = new SummaryEventInfo(); eventInfoList.append( summaryEvent ); // Event summaryEvent->ev = ev; // Start date label QString str = ""; QDate sD = QDate( date.year(), date.month(), date.day() ); if ( ( sD.month() == currentDate.month() ) && ( sD.day() == currentDate.day() ) ) { str = i18nc( "the appointment is today", "Today" ); summaryEvent->makeBold = true; } else if ( ( sD.month() == currentDate.addDays( 1 ).month() ) && ( sD.day() == currentDate.addDays( 1 ).day() ) ) { str = i18nc( "the appointment is tomorrow", "Tomorrow" ); } else { str = KGlobal::locale()->formatDate( sD, KLocale::FancyLongDate ); } summaryEvent->startDate = str; // Print the date span for multiday, floating events, for the // first day of the event only. if ( ev->isMultiDay() && ev->allDay() && firstDayOfMultiday && span > 1 ) { str = IncidenceFormatter::dateToString( ev->dtStart(), false, spec ) + " -\n " + IncidenceFormatter::dateToString( ev->dtEnd(), false, spec ); } summaryEvent->dateSpan = str; // Days to go label str = ""; dateDiff( startOfMultiday, daysTo ); if ( ev->isMultiDay() && !ev->allDay() ) { dateDiff( date, daysTo ); } if ( daysTo > 0 ) { str = i18np( "in 1 day", "in %1 days", daysTo ); } else { if ( !ev->allDay() ) { int secs; if ( !ev->recurs() ) { secs = currentDateTime.secsTo( ev->dtStart() ); } else { KDateTime kdt( date, QTime( 0, 0, 0 ), KSystemTimeZones::local() ); kdt = kdt.addSecs( -1 ); KDateTime next = ev->recurrence()->getNextDateTime( kdt ); secs = currentDateTime.secsTo( next ); } if ( secs > 0 ) { str = i18nc( "eg. in 1 hour 2 minutes", "in " ); int hours = secs / 3600; if ( hours > 0 ) { str += i18ncp( "use abbreviation for hour to keep the text short", "1 hr", "%1 hrs", hours ); str += ' '; secs -= ( hours * 3600 ); } int mins = secs / 60; if ( mins > 0 ) { str += i18ncp( "use abbreviation for minute to keep the text short", "1 min", "%1 mins", mins ); } } else { str = i18n( "now" ); } } else { str = i18n( "all day" ); } } summaryEvent->daysToGo = str; // Summary label str = ev->richSummary(); if ( ev->isMultiDay() && !ev->allDay() ) { str.append( QString( " (%1/%2)" ).arg( dayof ).arg( span ) ); } summaryEvent->summaryText = str; summaryEvent->summaryUrl = ev->uid(); QString tipText( KCal::IncidenceFormatter::toolTipStr( calendar, ev, date, true, spec ) ); if ( !tipText.isEmpty() ) { summaryEvent->summaryTooltip = tipText; } // Time range label (only for non-floating events) str = ""; if ( !ev->allDay() ) { QTime sST = ev->dtStart().toTimeSpec( spec ).time(); QTime sET = ev->dtEnd().toTimeSpec( spec ).time(); if ( ev->isMultiDay() ) { if ( ev->dtStart().date() < date ) { sST = QTime( 0, 0 ); } if ( ev->dtEnd().date() > date ) { sET = QTime( 23, 59 ); } } str = i18nc( "Time from - to", "%1 - %2", KGlobal::locale()->formatTime( sST ), KGlobal::locale()->formatTime( sET ) ); summaryEvent->timeRange = str; } // For recurring events, append the next occurrence to the time range label if ( ev->recurs() ) { KDateTime kdt( date, QTime( 0, 0, 0 ), KSystemTimeZones::local() ); kdt = kdt.addSecs( -1 ); KDateTime next = ev->recurrence()->getNextDateTime( kdt ); QString tmp = IncidenceFormatter::dateTimeToString( ev->recurrence()->getNextDateTime( next ), ev->allDay(), true, KSystemTimeZones::local() ); if ( !summaryEvent->timeRange.isEmpty() ) { summaryEvent->timeRange += "<br>"; } summaryEvent->timeRange += "<font size=\"small\"><i>" + i18nc( "next occurrence", "Next: %1", tmp ) + "</i></font>"; } } return eventInfoList; }