1/*
2 This file is part of libkdepim.
3
4 Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "calendardiffalgo.h"
23
24#include <kcalutils/stringify.h>
25
26#include <KDateTime>
27#include <KLocale>
28
29using namespace KPIM;
30
31#ifndef KDE_USE_FINAL
32static bool compareString( const QString &left, const QString &right )
33{
34 if ( left.isEmpty() && right.isEmpty() )
35 return true;
36 else
37 return left == right;
38}
39#endif
40
41static QString toString( const QDate &date )
42{
43 return date.toString();
44}
45
46static QString toString( const KDateTime &dateTime )
47{
48 return dateTime.dateTime().toString();
49}
50
51static QString toString( const QString str )
52{
53 return str;
54}
55
56static QString toString( bool value )
57{
58 if ( value )
59 return i18n( "Yes" );
60 else
61 return i18n( "No" );
62}
63
64CalendarDiffAlgo::CalendarDiffAlgo( const KCalCore::Incidence::Ptr &leftIncidence,
65 const KCalCore::Incidence::Ptr &rightIncidence )
66 : mLeftIncidence( leftIncidence ), mRightIncidence( rightIncidence )
67{
68}
69
70void CalendarDiffAlgo::run()
71{
72 begin();
73
74 diffIncidenceBase( mLeftIncidence, mRightIncidence );
75 diffIncidence( mLeftIncidence, mRightIncidence );
76
77 KCalCore::Event::Ptr leftEvent = mLeftIncidence.dynamicCast<KCalCore::Event>();
78 KCalCore::Event::Ptr rightEvent = mRightIncidence.dynamicCast<KCalCore::Event>();
79 if ( leftEvent && rightEvent ) {
80 diffEvent( leftEvent, rightEvent );
81 } else {
82 KCalCore::Todo::Ptr leftTodo = mLeftIncidence.dynamicCast<KCalCore::Todo>();
83 KCalCore::Todo::Ptr rightTodo = mRightIncidence.dynamicCast<KCalCore::Todo>();
84 if ( leftTodo && rightTodo ) {
85 diffTodo( leftTodo, rightTodo );
86 }
87 }
88
89 end();
90}
91
92void CalendarDiffAlgo::diffIncidenceBase( const KCalCore::IncidenceBase::Ptr &left, const KCalCore::IncidenceBase::Ptr &right )
93{
94 diffVector( i18n( "Attendees" ), left->attendees(), right->attendees() );
95
96 if ( left->dtStart() != right->dtStart() )
97 conflictField( i18n( "Start time" ), left->dtStart().toString(), right->dtStart().toString() );
98
99 if ( !compareString( left->organizer()->fullName(), right->organizer()->fullName() ) )
100 conflictField( i18n( "Organizer" ), left->organizer()->fullName(), right->organizer()->fullName() );
101
102 if ( !compareString( left->uid(), right->uid() ) )
103 conflictField( i18n( "UID" ), left->uid(), right->uid() );
104
105 if ( left->allDay() != right->allDay() )
106 conflictField( i18n( "Is all-day" ), toString( left->allDay() ), toString( right->allDay() ) );
107
108 if ( left->hasDuration() != right->hasDuration() )
109 conflictField( i18n( "Has duration" ), toString( left->hasDuration() ), toString( right->hasDuration() ) );
110
111 if ( left->duration() != right->duration() )
112 conflictField( i18n( "Duration" ), QString::number( left->duration().asSeconds() ), QString::number( right->duration().asSeconds() ) );
113}
114
115void CalendarDiffAlgo::diffIncidence( const KCalCore::Incidence::Ptr &left,
116 const KCalCore::Incidence::Ptr &right )
117{
118 if ( !compareString( left->description(), right->description() ) )
119 conflictField( i18n( "Description" ), left->description(), right->description() );
120
121 if ( !compareString( left->summary(), right->summary() ) )
122 conflictField( i18n( "Summary" ), left->summary(), right->summary() );
123
124 if ( left->status() != right->status() )
125 conflictField( i18n( "Status" ),
126 KCalUtils::Stringify::incidenceStatus( left->status() ),
127 KCalUtils::Stringify::incidenceStatus( right->status() ) );
128
129
130 if ( left->secrecy() != right->secrecy() )
131 conflictField( i18n( "Secrecy" ), toString( left->secrecy() ), toString( right->secrecy() ) );
132
133 if ( left->priority() != right->priority() )
134 conflictField( i18n( "Priority" ), toString( left->priority() ), toString( right->priority() ) );
135
136 if ( !compareString( left->location(), right->location() ) )
137 conflictField( i18n( "Location" ), left->location(), right->location() );
138
139 diffList( i18n( "Categories" ), left->categories(), right->categories() );
140 diffVector( i18n( "Alarms" ), left->alarms(), right->alarms() );
141 diffList( i18n( "Resources" ), left->resources(), right->resources() );
142 diffVector( i18n( "Attachments" ), left->attachments(), right->attachments() );
143 diffList( i18n( "Exception Dates" ), left->recurrence()->exDates(), right->recurrence()->exDates() );
144 diffList( i18n( "Exception Times" ), left->recurrence()->exDateTimes(), right->recurrence()->exDateTimes() );
145 // TODO: recurrence dates and date/times, exrules, rrules
146
147 if ( left->created() != right->created() )
148 conflictField( i18n( "Created" ), left->created().toString(), right->created().toString() );
149
150 if ( !compareString( left->relatedTo(), right->relatedTo() ) )
151 conflictField( i18n( "Related Uid" ), left->relatedTo(), right->relatedTo() );
152}
153
154void CalendarDiffAlgo::diffEvent( const KCalCore::Event::Ptr &left, const KCalCore::Event::Ptr &right )
155{
156 if ( left->hasEndDate() != right->hasEndDate() )
157 conflictField( i18n( "Has End Date" ), toString( left->hasEndDate() ), toString( right->hasEndDate() ) );
158
159 if ( left->dtEnd() != right->dtEnd() )
160 conflictField( i18n( "End Date" ), left->dtEnd().toString(), right->dtEnd().toString() );
161
162 // TODO: check transparency
163}
164
165void CalendarDiffAlgo::diffTodo( const KCalCore::Todo::Ptr &left, const KCalCore::Todo::Ptr &right )
166{
167 if ( left->hasStartDate() != right->hasStartDate() )
168 conflictField( i18n( "Has Start Date" ), toString( left->hasStartDate() ), toString( right->hasStartDate() ) );
169
170 if ( left->hasDueDate() != right->hasDueDate() )
171 conflictField( i18n( "Has Due Date" ), toString( left->hasDueDate() ), toString( right->hasDueDate() ) );
172
173 if ( left->dtDue() != right->dtDue() )
174 conflictField( i18n( "Due Date" ), left->dtDue().toString(), right->dtDue().toString() );
175
176 if ( left->hasCompletedDate() != right->hasCompletedDate() )
177 conflictField( i18n( "Has Complete Date" ), toString( left->hasCompletedDate() ), toString( right->hasCompletedDate() ) );
178
179 if ( left->percentComplete() != right->percentComplete() )
180 conflictField( i18n( "Complete" ), QString::number( left->percentComplete() ), QString::number( right->percentComplete() ) );
181
182 if ( left->completed() != right->completed() )
183 conflictField( i18n( "Completed" ), toString( left->completed() ), toString( right->completed() ) );
184}
185
186template <class L>
187void CalendarDiffAlgo::diffList( const QString &id,
188 const QList<L> &left, const QList<L> &right )
189{
190 for ( int i = 0; i < left.count(); ++i ) {
191 if ( !right.contains( left[ i ] ) )
192 additionalLeftField( id, toString( left[ i ] ) );
193 }
194
195 for ( int i = 0; i < right.count(); ++i ) {
196 if ( !left.contains( right[ i ] ) )
197 additionalRightField( id, toString( right[ i ] ) );
198 }
199}
200
201template <class L>
202void CalendarDiffAlgo::diffVector( const QString &id,
203 const QVector<L> &left, const QVector<L> &right )
204{
205 for ( int i = 0; i < left.count(); ++i ) {
206 if ( !right.contains( left[ i ] ) )
207 additionalLeftField( id, toString( left[ i ] ) );
208 }
209
210 for ( int i = 0; i < right.count(); ++i ) {
211 if ( !left.contains( right[ i ] ) )
212 additionalRightField( id, toString( right[ i ] ) );
213 }
214}
215