diff --git a/src/sorting.cpp b/src/sorting.cpp index 3e3592a09..a3e7a1ac3 100644 --- a/src/sorting.cpp +++ b/src/sorting.cpp @@ -1,442 +1,434 @@ /* This file is part of the kcalcore library. Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. Contact: Alvaro Manera This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sorting.h" #include "event.h" #include "journal.h" #include "todo.h" #include "utils.h" -#include - // PENDING(kdab) Review // The QString::compare() need to be replace by a DUI string comparisons. // See http://qt.gitorious.org/maemo-6-ui-framework/libdui // If not compiled in "meego-mode" should we be using locale compares? using namespace KCalCore; /** * How one QDateTime compares with another. * * If any all-day events are involved, comparison of QDateTime values * requires them to be considered as representing time periods. An all-day * instance represents a time period from 00:00:00 to 23:59:59.999 on a given * date, while a date/time instance can be considered to represent a time * period whose start and end times are the same. They may therefore be * earlier or later, or may overlap or be contained one within the other. * * Values may be OR'ed with each other in any combination of 'consecutive' * intervals to represent different types of relationship. * * In the descriptions of the values below, * - s1 = start time of first instance * - e1 = end time of first instance * - s2 = start time of second instance * - e2 = end time of second instance. */ enum DateTimeComparison { Before = 0x01, /**< The first QDateTime is strictly earlier than the second, * i.e. e1 < s2. */ AtStart = 0x02, /**< The first QDateTime starts at the same time as the second, * and ends before the end of the second, * i.e. s1 = s2, e1 < e2. */ Inside = 0x04, /**< The first QDateTime starts after the start of the second, * and ends before the end of the second, * i.e. s1 > s2, e1 < e2. */ AtEnd = 0x08, /**< The first QDateTime starts after the start of the second, * and ends at the same time as the second, * i.e. s1 > s2, e1 = e2. */ After = 0x10, /**< The first QDateTime is strictly later than the second, * i.e. s1 > e2. */ Equal = AtStart | Inside | AtEnd, /**< Simultaneous, i.e. s1 = s2 && e1 = e2. */ Outside = Before | AtStart | Inside | AtEnd | After, /**< The first QDateTime starts before the start of the other, * and ends after the end of the other, * i.e. s1 < s2, e1 > e2. */ StartsAt = AtStart | Inside | AtEnd | After, /**< The first QDateTime starts at the same time as the other, * and ends after the end of the other, * i.e. s1 = s2, e1 > e2. */ EndsAt = Before | AtStart | Inside | AtEnd /**< The first QDateTime starts before the start of the other, * and ends at the same time as the other, * i.e. s1 < s2, e1 = e2. */ }; /** * Compare two QDateTime instances to determine whether they are * simultaneous, earlier or later. * The comparison takes time zones into account: if the two instances have * different time zones, they are first converted to UTC before comparing. * * If both instances are not all-day values, the first instance is considered to * be either simultaneous, earlier or later, and does not overlap. * * If one instance is all-day and the other is a not all-day, the first instance * is either strictly earlier, strictly later, or overlaps. * * If both instance are all-day, they are considered simultaneous if both * their start of day and end of day times are simultaneous with each * other. (Both start and end of day times need to be considered in case a * daylight savings change occurs during that day.) Otherwise, the first instance * can be strictly earlier, earlier but overlapping, later but overlapping, * or strictly later. * * Note that if either instance is a local time (Qt::TimeSpec of Qt::LocalTime), * the result cannot be guaranteed to be correct, since by definition they * contain no information about time zones or daylight savings changes. * * @return DateTimeComparison indicating teh relationship of dt1 to dt2 * @see operator==(), operator!=(), operator<(), operator<=(), operator>=(), operator>() */ DateTimeComparison compare(const QDateTime &dt1, bool isAllDay1, const QDateTime &dt2, bool isAllDay2) { QDateTime start1, start2; //FIXME When secondOccurrence is available in QDateTime //const bool conv = (!d->equalSpec(*other.d) || d->secondOccurrence() != other.d->secondOccurrence()); const bool conv = dt1.timeSpec() != dt2.timeSpec() || (dt1.timeSpec() == Qt::OffsetFromUTC && dt1.offsetFromUtc() != dt2.offsetFromUtc()) || (dt1.timeSpec() == Qt::TimeZone && dt1.timeZone() != dt2.timeZone()); if (conv) { // Different time specs or one is a time which occurs twice, // so convert to UTC before comparing start1 = dt1.toUTC(); start2 = dt2.toUTC(); } else { // Same time specs, so no need to convert to UTC start1 = dt1; start2 = dt2; } if (isAllDay1 || isAllDay2) { // At least one of the instances is date-only, so we need to compare // time periods rather than just times. QDateTime end1, end2; if (conv) { if (isAllDay1) { QDateTime dt(dt1); dt.setTime(QTime(23, 59, 59, 999)); end1 = dt.toUTC(); } else { end1 = start1; } if (isAllDay2) { QDateTime dt(dt2); dt.setTime(QTime(23, 59, 59, 999)); end2 = dt.toUTC(); } else { end2 = start2; } } else { if (isAllDay1) { end1 = QDateTime(dt1.date(), QTime(23, 59, 59, 999), Qt::LocalTime); } else { end1 = dt1; } if (isAllDay2) { end2 = QDateTime(dt2.date(), QTime(23, 59, 59, 999), Qt::LocalTime); } else { end2 = dt2; } } if (start1 == start2) return !isAllDay1 ? AtStart : (end1 == end2) ? Equal : (end1 < end2) ? static_cast(AtStart | Inside) : static_cast(AtStart | Inside | AtEnd | After); if (start1 < start2) return (end1 < start2) ? Before : (end1 == end2) ? static_cast(Before | AtStart | Inside | AtEnd) : (end1 == start2) ? static_cast(Before | AtStart) : (end1 < end2) ? static_cast(Before | AtStart | Inside) : Outside; else return (start1 > end2) ? After : (start1 == end2) ? (end1 == end2 ? AtEnd : static_cast(AtEnd | After)) : (end1 == end2) ? static_cast(Inside | AtEnd) : (end1 < end2) ? Inside : static_cast(Inside | AtEnd | After); } return (start1 == start2) ? Equal : (start1 < start2) ? Before : After; } -// ### temporary porting helper -DateTimeComparison compare(const KDateTime &dt1, bool isAllDay1, const KDateTime &dt2, bool isAllDay2) -{ - return compare(k2q(dt1), isAllDay1, k2q(dt2), isAllDay2); -} - bool KCalCore::Events::startDateLessThan(const Event::Ptr &e1, const Event::Ptr &e2) { DateTimeComparison res = compare(e1->dtStart(), e1->allDay(), e2->dtStart(), e2->allDay()); if (res == Equal) { return Events::summaryLessThan(e1, e2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Events::startDateMoreThan(const Event::Ptr &e1, const Event::Ptr &e2) { DateTimeComparison res = compare(e1->dtStart(), e1->allDay(), e2->dtStart(), e2->allDay()); if (res == Equal) { return Events::summaryMoreThan(e1, e2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Events::summaryLessThan(const Event::Ptr &e1, const Event::Ptr &e2) { return QString::compare(e1->summary(), e2->summary(), Qt::CaseInsensitive) < 0; } bool KCalCore::Events::summaryMoreThan(const Event::Ptr &e1, const Event::Ptr &e2) { return QString::compare(e1->summary(), e2->summary(), Qt::CaseInsensitive) > 0; } bool KCalCore::Events::endDateLessThan(const Event::Ptr &e1, const Event::Ptr &e2) { DateTimeComparison res = compare(e1->dtEnd(), e1->allDay(), e2->dtEnd(), e2->allDay()); if (res == Equal) { return Events::summaryLessThan(e1, e2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Events::endDateMoreThan(const Event::Ptr &e1, const Event::Ptr &e2) { DateTimeComparison res = compare(e1->dtEnd(), e1->allDay(), e2->dtEnd(), e2->allDay()); if (res == Equal) { return Events::summaryMoreThan(e1, e2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Journals::dateLessThan(const Journal::Ptr &j1, const Journal::Ptr &j2) { DateTimeComparison res = compare(j1->dtStart(), j1->allDay(), j2->dtStart(), j2->allDay()); return (res & Before || res & AtStart); } bool KCalCore::Journals::dateMoreThan(const Journal::Ptr &j1, const Journal::Ptr &j2) { DateTimeComparison res = compare(j1->dtStart(), j1->allDay(), j2->dtStart(), j2->allDay()); return (res & After || res & AtEnd); } bool KCalCore::Journals::summaryLessThan(const Journal::Ptr &j1, const Journal::Ptr &j2) { return QString::compare(j1->summary(), j2->summary(), Qt::CaseInsensitive) < 0; } bool KCalCore::Journals::summaryMoreThan(const Journal::Ptr &j1, const Journal::Ptr &j2) { return QString::compare(j1->summary(), j2->summary(), Qt::CaseInsensitive) > 0; } bool KCalCore::Todos::startDateLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->dtStart(), t1->allDay(), t2->dtStart(), t2->allDay()); if (res == Equal) { return Todos::summaryLessThan(t1, t2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Todos::startDateMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->dtStart(), t1->allDay(), t2->dtStart(), t2->allDay()); if (res == Equal) { return Todos::summaryMoreThan(t1, t2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Todos::dueDateLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->dtDue(), t1->allDay(), t2->dtDue(), t2->allDay()); if (res == Equal) { return Todos::summaryLessThan(t1, t2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Todos::dueDateMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->dtDue(), t1->allDay(), t2->dtDue(), t2->allDay()); if (res == Equal) { return Todos::summaryMoreThan(t1, t2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Todos::priorityLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { if (t1->priority() < t2->priority()) { return true; } else if (t1->priority() == t2->priority()) { return Todos::summaryLessThan(t1, t2); } else { return false; } } bool KCalCore::Todos::priorityMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { if (t1->priority() > t2->priority()) { return true; } else if (t1->priority() == t2->priority()) { return Todos::summaryMoreThan(t1, t2); } else { return false; } } bool KCalCore::Todos::percentLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { if (t1->percentComplete() < t2->percentComplete()) { return true; } else if (t1->percentComplete() == t2->percentComplete()) { return Todos::summaryLessThan(t1, t2); } else { return false; } } bool KCalCore::Todos::percentMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { if (t1->percentComplete() > t2->percentComplete()) { return true; } else if (t1->percentComplete() == t2->percentComplete()) { return Todos::summaryMoreThan(t1, t2); } else { return false; } } bool KCalCore::Todos::summaryLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { return QString::compare(t1->summary(), t2->summary(), Qt::CaseInsensitive) < 0; } bool KCalCore::Todos::summaryMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { return QString::compare(t1->summary(), t2->summary(), Qt::CaseInsensitive) > 0; } bool KCalCore::Todos::createdLessThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->created(), t1->allDay(), t2->created(), t2->allDay()); if (res == Equal) { return Todos::summaryLessThan(t1, t2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Todos::createdMoreThan(const Todo::Ptr &t1, const Todo::Ptr &t2) { DateTimeComparison res = compare(t1->created(), t1->allDay(), t2->created(), t2->allDay()); if (res == Equal) { return Todos::summaryMoreThan(t1, t2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Incidences::dateLessThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { DateTimeComparison res = compare(i1->dateTime(Incidence::RoleSort), i1->allDay(), i2->dateTime(Incidence::RoleSort), i2->allDay()); if (res == Equal) { return Incidences::summaryLessThan(i1, i2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Incidences::dateMoreThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { DateTimeComparison res = compare(i1->dateTime(Incidence::RoleSort), i1->allDay(), i2->dateTime(Incidence::RoleSort), i2->allDay()); if (res == Equal) { return Incidences::summaryMoreThan(i1, i2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Incidences::createdLessThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { DateTimeComparison res = compare(i1->created(), i1->allDay(), i2->created(), i2->allDay()); if (res == Equal) { return Incidences::summaryLessThan(i1, i2); } else { return (res & Before || res & AtStart); } } bool KCalCore::Incidences::createdMoreThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { DateTimeComparison res = compare(i1->created(), i1->allDay(), i2->created(), i2->allDay()); if (res == Equal) { return Incidences::summaryMoreThan(i1, i2); } else { return (res & After || res & AtEnd); } } bool KCalCore::Incidences::summaryLessThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { return QString::compare(i1->summary(), i2->summary(), Qt::CaseInsensitive) < 0; } bool KCalCore::Incidences::summaryMoreThan(const Incidence::Ptr &i1, const Incidence::Ptr &i2) { return QString::compare(i1->summary(), i2->summary(), Qt::CaseInsensitive) > 0; } bool KCalCore::Persons::countMoreThan(const Person::Ptr &p1, const Person::Ptr &p2) { return p1->count() > p2->count(); }