compat.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the kcal library. 00003 00004 Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> 00005 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00034 #include "compat.h" 00035 #include "incidence.h" 00036 00037 #include <kdatetime.h> 00038 #include <kdebug.h> 00039 00040 #include <QtCore/QRegExp> 00041 #include <QtCore/QList> 00042 00043 using namespace KCal; 00044 00045 Compat *CompatFactory::createCompat( const QString &productId ) 00046 { 00047 Compat *compat = 0; 00048 00049 int korg = productId.indexOf( "KOrganizer" ); 00050 int outl9 = productId.indexOf( "Outlook 9.0" ); 00051 00052 // TODO: Use the version of LibKCal to determine the compat class... 00053 if ( korg >= 0 ) { 00054 int versionStart = productId.indexOf( " ", korg ); 00055 if ( versionStart >= 0 ) { 00056 int versionStop = productId.indexOf( QRegExp( "[ /]" ), versionStart + 1 ); 00057 if ( versionStop >= 0 ) { 00058 QString version = productId.mid( versionStart + 1, 00059 versionStop - versionStart - 1 ); 00060 00061 int versionNum = version.section( '.', 0, 0 ).toInt() * 10000 + 00062 version.section( '.', 1, 1 ).toInt() * 100 + 00063 version.section( '.', 2, 2 ).toInt(); 00064 int releaseStop = productId.indexOf( "/", versionStop ); 00065 QString release; 00066 if ( releaseStop > versionStop ) { 00067 release = productId.mid( versionStop+1, releaseStop-versionStop-1 ); 00068 } 00069 if ( versionNum < 30100 ) { 00070 compat = new CompatPre31; 00071 } else if ( versionNum < 30200 ) { 00072 compat = new CompatPre32; 00073 } else if ( versionNum == 30200 && release == "pre" ) { 00074 kDebug() << "Generating compat for KOrganizer 3.2 pre"; 00075 compat = new Compat32PrereleaseVersions; 00076 } else if ( versionNum < 30400 ) { 00077 compat = new CompatPre34; 00078 } else if ( versionNum < 30500 ) { 00079 compat = new CompatPre35; 00080 } 00081 } 00082 } 00083 } else if ( outl9 >= 0 ) { 00084 kDebug() << "Generating compat for Outlook < 2000 (Outlook 9.0)"; 00085 compat = new CompatOutlook9; 00086 } 00087 00088 if ( !compat ) { 00089 compat = new Compat; 00090 } 00091 00092 return compat; 00093 } 00094 00095 void Compat::fixEmptySummary( Incidence *incidence ) 00096 { 00097 // some stupid vCal exporters ignore the standard and use Description 00098 // instead of Summary for the default field. Correct for this: Copy the 00099 // first line of the description to the summary (if summary is just one 00100 // line, move it) 00101 if ( incidence->summary().isEmpty() && !( incidence->description().isEmpty() ) ) { 00102 QString oldDescription = incidence->description().trimmed(); 00103 QString newSummary( oldDescription ); 00104 newSummary.remove( QRegExp( "\n.*" ) ); 00105 incidence->setSummary( newSummary ); 00106 if ( oldDescription == newSummary ) { 00107 incidence->setDescription( "" ); 00108 } 00109 } 00110 } 00111 00112 void Compat::fixFloatingEnd( QDate &date ) 00113 { 00114 Q_UNUSED( date ); 00115 } 00116 00117 void Compat::fixRecurrence( Incidence *incidence ) 00118 { 00119 Q_UNUSED( incidence ); 00120 // Prevent use of compatibility mode during subsequent changes by the application 00121 // incidence->recurrence()->setCompatVersion(); 00122 } 00123 00124 void CompatPre35::fixRecurrence( Incidence *incidence ) 00125 { 00126 Recurrence *recurrence = incidence->recurrence(); 00127 if ( recurrence ) { 00128 KDateTime start( incidence->dtStart() ); 00129 // kde < 3.5 only had one rrule, so no need to loop over all RRULEs. 00130 RecurrenceRule *r = recurrence->defaultRRule(); 00131 if ( r && !r->dateMatchesRules( start ) ) { 00132 recurrence->addExDateTime( start ); 00133 } 00134 } 00135 00136 // Call base class method now that everything else is done 00137 Compat::fixRecurrence( incidence ); 00138 } 00139 00140 int CompatPre34::fixPriority( int priority ) 00141 { 00142 if ( 0 < priority && priority < 6 ) { 00143 // adjust 1->1, 2->3, 3->5, 4->7, 5->9 00144 return 2 * priority - 1; 00145 } else { 00146 return priority; 00147 } 00148 } 00149 00150 void CompatPre32::fixRecurrence( Incidence *incidence ) 00151 { 00152 Recurrence *recurrence = incidence->recurrence(); 00153 if ( recurrence->recurs() && recurrence->duration() > 0 ) { 00154 recurrence->setDuration( recurrence->duration() + incidence->recurrence()->exDates().count() ); 00155 } 00156 // Call base class method now that everything else is done 00157 CompatPre35::fixRecurrence( incidence ); 00158 } 00159 00160 void CompatPre31::fixFloatingEnd( QDate &endDate ) 00161 { 00162 endDate = endDate.addDays( 1 ); 00163 } 00164 00165 void CompatPre31::fixRecurrence( Incidence *incidence ) 00166 { 00167 CompatPre32::fixRecurrence( incidence ); 00168 00169 Recurrence *recur = incidence->recurrence(); 00170 RecurrenceRule *r = 0; 00171 if ( recur ) { 00172 r = recur->defaultRRule(); 00173 } 00174 if ( recur && r ) { 00175 int duration = r->duration(); 00176 if ( duration > 0 ) { 00177 // Backwards compatibility for KDE < 3.1. 00178 // rDuration was set to the number of time periods to recur, 00179 // with week start always on a Monday. 00180 // Convert this to the number of occurrences. 00181 r->setDuration( -1 ); 00182 QDate end( r->startDt().date() ); 00183 bool doNothing = false; 00184 // # of periods: 00185 int tmp = ( duration - 1 ) * r->frequency(); 00186 switch ( r->recurrenceType() ) { 00187 case RecurrenceRule::rWeekly: 00188 { 00189 end = end.addDays( tmp * 7 + 7 - end.dayOfWeek() ); 00190 break; 00191 } 00192 case RecurrenceRule::rMonthly: 00193 { 00194 int month = end.month() - 1 + tmp; 00195 end.setYMD( end.year() + month / 12, month % 12 + 1, 31 ); 00196 break; 00197 } 00198 case RecurrenceRule::rYearly: 00199 { 00200 end.setYMD( end.year() + tmp, 12, 31 ); 00201 break; 00202 } 00203 default: 00204 doNothing = true; 00205 break; 00206 } 00207 if ( !doNothing ) { 00208 duration = r->durationTo( 00209 KDateTime( end, QTime( 0, 0, 0 ), incidence->dtStart().timeSpec() ) ); 00210 r->setDuration( duration ); 00211 } 00212 } 00213 00214 /* addYearlyNum */ 00215 // Dates were stored as day numbers, with a fiddle to take account of 00216 // leap years. Convert the day number to a month. 00217 QList<int> days = r->byYearDays(); 00218 if ( !days.isEmpty() ) { 00219 QList<int> months = r->byMonths(); 00220 for ( int i = 0; i < months.size(); ++i ) { 00221 int newmonth = 00222 QDate( r->startDt().date().year(), 1, 1 ).addDays( months.at( i ) - 1 ).month(); 00223 if ( !months.contains( newmonth ) ) { 00224 months.append( newmonth ); 00225 } 00226 } 00227 00228 r->setByMonths( months ); 00229 days.clear(); 00230 r->setByYearDays( days ); 00231 } 00232 } 00233 } 00234 00235 void CompatOutlook9::fixAlarms( Incidence *incidence ) 00236 { 00237 if ( !incidence ) { 00238 return; 00239 } 00240 Alarm::List alarms = incidence->alarms(); 00241 Alarm::List::Iterator it; 00242 for ( it = alarms.begin(); it != alarms.end(); ++it ) { 00243 Alarm *al = *it; 00244 if ( al && al->hasStartOffset() ) { 00245 Duration offsetDuration = al->startOffset(); 00246 int offs = offsetDuration.asSeconds(); 00247 if ( offs > 0 ) { 00248 offsetDuration = Duration( -offs ); 00249 } 00250 al->setStartOffset( offsetDuration ); 00251 } 00252 } 00253 }