mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 02:42:51 +00:00
324 lines
11 KiB
C++
324 lines
11 KiB
C++
/*
|
|
This file is part of Kontact.
|
|
|
|
Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
|
|
Copyright (c) 2005-2006,2008-2009 Allen Winter <winter@kde.org>
|
|
Copyright (c) 2008 Thomas McGuire <mcguire@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
As a special exception, permission is given to link this program
|
|
with any edition of Qt, and distribute the resulting executable,
|
|
without including the source code for Qt in the source distribution.
|
|
*/
|
|
|
|
#include "summaryeventinfo.h"
|
|
|
|
#include <KCalCore/Calendar>
|
|
#include <KCalCore/Event>
|
|
using namespace KCalCore;
|
|
|
|
#include <KCalUtils/IncidenceFormatter>
|
|
using namespace KCalUtils;
|
|
|
|
#include <KGlobal>
|
|
#include <KLocalizedString>
|
|
#include <KSystemTimeZones>
|
|
#include <KLocale>
|
|
|
|
#include <QDate>
|
|
#include <QStringList>
|
|
|
|
bool SummaryEventInfo::mShowBirthdays = true;
|
|
bool SummaryEventInfo::mShowAnniversaries = true;
|
|
|
|
static QHash<QString, KDateTime> sDateTimeByUid;
|
|
|
|
static bool eventLessThan(const KCalCore::Event::Ptr &event1, const KCalCore::Event::Ptr &event2)
|
|
{
|
|
KDateTime kdt1 = sDateTimeByUid.value(event1->instanceIdentifier());
|
|
KDateTime kdt2 = sDateTimeByUid.value(event2->instanceIdentifier());
|
|
if (kdt1.date() < kdt2.date()) { // Compare dates first since comparing all day with non-all-day doesn't work
|
|
return true;
|
|
} else if (kdt1.date() > kdt2.date()) {
|
|
return false;
|
|
} else {
|
|
if (kdt1.isDateOnly() && !kdt2.isDateOnly()) {
|
|
return false;
|
|
} else if (!kdt1.isDateOnly() && kdt2.isDateOnly()) {
|
|
return true;
|
|
} else {
|
|
if (kdt1 > kdt2) {
|
|
return true;
|
|
} else if (kdt1 < kdt2) {
|
|
return false;
|
|
} else {
|
|
return event1->summary() > event2->summary();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SummaryEventInfo::setShowSpecialEvents( bool showBirthdays,
|
|
bool showAnniversaries )
|
|
{
|
|
mShowBirthdays = showBirthdays;
|
|
mShowAnniversaries = showAnniversaries;
|
|
}
|
|
|
|
bool SummaryEventInfo::skip( const KCalCore::Event::Ptr &event )
|
|
{
|
|
//simply check categories because the birthdays resource always adds
|
|
//the appropriate category to the event.
|
|
QStringList c = event->categories();
|
|
if ( !mShowBirthdays &&
|
|
c.contains( QLatin1String("BIRTHDAY"), Qt::CaseInsensitive ) ) {
|
|
return true;
|
|
}
|
|
if ( !mShowAnniversaries &&
|
|
c.contains( QLatin1String("ANNIVERSARY"), Qt::CaseInsensitive ) ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SummaryEventInfo::dateDiff( const QDate &date, int &days )
|
|
{
|
|
QDate currentDate;
|
|
QDate eventDate;
|
|
|
|
if ( QDate::isLeapYear( date.year() ) && date.month() == 2 && date.day() == 29 ) {
|
|
currentDate = QDate( date.year(), QDate::currentDate().month(), QDate::currentDate().day() );
|
|
if ( !QDate::isLeapYear( QDate::currentDate().year() ) ) {
|
|
eventDate = QDate( date.year(), date.month(), 28 ); // celebrate one day earlier ;)
|
|
} else {
|
|
eventDate = QDate( date.year(), date.month(), date.day() );
|
|
}
|
|
} else {
|
|
currentDate = QDate( QDate::currentDate().year(),
|
|
QDate::currentDate().month(),
|
|
QDate::currentDate().day() );
|
|
eventDate = QDate( QDate::currentDate().year(), date.month(), date.day() );
|
|
}
|
|
|
|
int offset = currentDate.daysTo( eventDate );
|
|
if ( offset < 0 ) {
|
|
days = 365 + offset;
|
|
if ( QDate::isLeapYear( QDate::currentDate().year() ) ) {
|
|
days++;
|
|
}
|
|
} else {
|
|
days = offset;
|
|
}
|
|
}
|
|
|
|
SummaryEventInfo::SummaryEventInfo()
|
|
: makeBold( false )
|
|
{
|
|
}
|
|
|
|
/**static*/
|
|
SummaryEventInfo::List SummaryEventInfo::eventsForRange( const QDate &start, const QDate &end,
|
|
KCalCore::Calendar *calendar )
|
|
{
|
|
KCalCore::Event::List allEvents = calendar->events(); // calendar->rawEvents() isn't exactly what we want, doesn't handle recurrence right
|
|
KCalCore::Event::List events;
|
|
KDateTime::Spec spec = KSystemTimeZones::local();
|
|
const KDateTime currentDateTime = KDateTime::currentDateTime( spec );
|
|
const QDate currentDate = currentDateTime.date();
|
|
|
|
sDateTimeByUid.clear();
|
|
|
|
for (int i=0; i<allEvents.count(); ++i) {
|
|
KCalCore::Event::Ptr event = allEvents.at(i);
|
|
if (skip(event))
|
|
continue;
|
|
|
|
KDateTime eventStart = event->dtStart().toTimeSpec(spec);
|
|
KDateTime eventEnd = event->dtEnd().toTimeSpec(spec);
|
|
if (event->recurs()) {
|
|
KCalCore::DateTimeList occurrences = event->recurrence()->timesInInterval(KDateTime(start, spec), KDateTime(end, spec));
|
|
if (!occurrences.isEmpty()) {
|
|
events << event;
|
|
sDateTimeByUid.insert(event->instanceIdentifier(), occurrences.first());
|
|
}
|
|
} else {
|
|
if ( ( end >= eventStart.date() && start <= eventEnd.date() ) ||
|
|
( start >= eventStart.date() && end <= eventEnd.date() ) ) {
|
|
events << event;
|
|
if ( eventStart.date() < start ) {
|
|
sDateTimeByUid.insert(event->instanceIdentifier(), KDateTime(start,spec));
|
|
} else {
|
|
sDateTimeByUid.insert(event->instanceIdentifier(), eventStart);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
qSort(events.begin(), events.end(), eventLessThan);
|
|
|
|
SummaryEventInfo::List eventInfoList;
|
|
KCalCore::Event::Ptr ev;
|
|
KCalCore::Event::List::ConstIterator itEnd = events.constEnd();
|
|
for ( KCalCore::Event::List::ConstIterator it=events.constBegin(); it != itEnd; ++it ) {
|
|
ev = *it;
|
|
// Count number of days remaining in multiday event
|
|
int span = 1;
|
|
int dayof = 1;
|
|
const KDateTime eventStart = ev->dtStart().toTimeSpec(spec);
|
|
const KDateTime eventEnd = ev->dtEnd().toTimeSpec(spec);
|
|
const QDate occurrenceStartDate = sDateTimeByUid.value(ev->instanceIdentifier()).date();
|
|
|
|
QDate startOfMultiday = eventStart.date();
|
|
if ( startOfMultiday < currentDate ) {
|
|
startOfMultiday = currentDate;
|
|
}
|
|
bool firstDayOfMultiday = ( start == startOfMultiday );
|
|
|
|
SummaryEventInfo *summaryEvent = new SummaryEventInfo();
|
|
eventInfoList.append( summaryEvent );
|
|
|
|
// Event
|
|
summaryEvent->ev = ev;
|
|
|
|
// Start date label
|
|
QString str;
|
|
QDate sD = occurrenceStartDate;
|
|
if (currentDate >= sD) {
|
|
str = i18nc( "the appointment is today", "Today" );
|
|
summaryEvent->makeBold = true;
|
|
} else if ( sD == currentDate.addDays(1) ) {
|
|
str = i18nc( "the appointment is tomorrow", "Tomorrow" );
|
|
} else {
|
|
str = KGlobal::locale()->formatDate( sD, KLocale::FancyLongDate );
|
|
}
|
|
summaryEvent->startDate = str;
|
|
|
|
if ( ev->isMultiDay() ) {
|
|
dayof = eventStart.date().daysTo(start)+1;
|
|
dayof = dayof <= 0 ? 1 : dayof;
|
|
span = eventStart.date().daysTo(eventEnd.date()) + 1;
|
|
}
|
|
// 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 ) +
|
|
QLatin1String(" -\n ") +
|
|
IncidenceFormatter::dateToString( ev->dtEnd(), false, spec );
|
|
}
|
|
summaryEvent->dateSpan = str;
|
|
|
|
// Days to go label
|
|
str.clear();
|
|
const int daysTo = currentDate.daysTo(occurrenceStartDate);
|
|
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( start, QTime( 0, 0, 0 ), spec );
|
|
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 += QLatin1Char(' ');
|
|
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::fromLatin1( " (%1/%2)" ).arg( dayof ).arg( span ) );
|
|
}
|
|
summaryEvent->summaryText = str;
|
|
summaryEvent->summaryUrl = ev->uid();
|
|
/*
|
|
Commented out because a ETMCalendar doesn't have any name, it's a group of selected
|
|
calendars, not an individual one.
|
|
|
|
QString tipText( KCalUtils::IncidenceFormatter::toolTipStr(
|
|
KCalUtils::IncidenceFormatter::resourceString(
|
|
calendar, ev ), ev, start, true, spec ) );
|
|
if ( !tipText.isEmpty() ) {
|
|
summaryEvent->summaryTooltip = tipText;
|
|
}*/
|
|
|
|
// Time range label (only for non-floating events)
|
|
str.clear();
|
|
if ( !ev->allDay() ) {
|
|
QTime sST = eventStart.time();
|
|
QTime sET = eventEnd.time();
|
|
if ( ev->isMultiDay() ) {
|
|
if ( eventStart.date() < start ) {
|
|
sST = QTime( 0, 0 );
|
|
}
|
|
if ( eventEnd.date() > end ) {
|
|
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( start, QTime( 0, 0, 0 ), spec );
|
|
kdt = kdt.addSecs( -1 );
|
|
KDateTime next = ev->recurrence()->getNextDateTime( kdt );
|
|
QString tmp = IncidenceFormatter::dateTimeToString(
|
|
ev->recurrence()->getNextDateTime( next ), ev->allDay(),
|
|
true, spec );
|
|
if ( !summaryEvent->timeRange.isEmpty() ) {
|
|
summaryEvent->timeRange += QLatin1String("<br>");
|
|
}
|
|
summaryEvent->timeRange += QLatin1String("<font size=\"small\"><i>") +
|
|
i18nc( "next occurrence", "Next: %1", tmp ) +
|
|
QLatin1String("</i></font>");
|
|
}
|
|
}
|
|
|
|
return eventInfoList;
|
|
}
|
|
|
|
SummaryEventInfo::List SummaryEventInfo::eventsForDate( const QDate &date,
|
|
KCalCore::Calendar *calendar )
|
|
{
|
|
return eventsForRange(date, date, calendar);
|
|
}
|