compat.cpp
00001 /* 00002 This file is part of libkcal. 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 */ 00022 00023 #include "compat.h" 00024 00025 #include <kdebug.h> 00026 00027 #include <tqregexp.h> 00028 00029 #include "incidence.h" 00030 00031 using namespace KCal; 00032 00033 Compat *CompatFactory::createCompat( const TQString &productId ) 00034 { 00035 // kdDebug(5800) << "CompatFactory::createCompat(): '" << productId << "'" 00036 // << endl; 00037 00038 Compat *compat = 0; 00039 00040 int korg = productId.find( "KOrganizer" ); 00041 int outl9 = productId.find( "Outlook 9.0" ); 00042 // int kcal = productId.find( "LibKCal" ); 00043 00044 // TODO: Use the version of LibKCal to determine the compat class... 00045 if ( korg >= 0 ) { 00046 int versionStart = productId.find( " ", korg ); 00047 if ( versionStart >= 0 ) { 00048 int versionStop = productId.find( TQRegExp( "[ /]" ), versionStart + 1 ); 00049 if ( versionStop >= 0 ) { 00050 TQString version = productId.mid( versionStart + 1, 00051 versionStop - versionStart - 1 ); 00052 // kdDebug(5800) << "Found KOrganizer version: " << version << endl; 00053 00054 int versionNum = version.section( ".", 0, 0 ).toInt() * 10000 + 00055 version.section( ".", 1, 1 ).toInt() * 100 + 00056 version.section( ".", 2, 2 ).toInt(); 00057 int releaseStop = productId.find( "/", versionStop ); 00058 TQString release; 00059 if ( releaseStop > versionStop ) { 00060 release = productId.mid( versionStop+1, releaseStop-versionStop-1 ); 00061 } 00062 // kdDebug(5800) << "KOrganizer release: \"" << release << "\"" << endl; 00063 00064 // kdDebug(5800) << "Numerical version: " << versionNum << endl; 00065 00066 if ( versionNum < 30100 ) { 00067 compat = new CompatPre31; 00068 } else if ( versionNum < 30200 ) { 00069 compat = new CompatPre32; 00070 } else if ( versionNum == 30200 && release == "pre" ) { 00071 kdDebug(5800) << "Generating compat for KOrganizer 3.2 pre " << endl; 00072 compat = new Compat32PrereleaseVersions; 00073 } else if ( versionNum < 30400 ) { 00074 compat = new CompatPre34; 00075 } else if ( versionNum < 30500 ) { 00076 compat = new CompatPre35; 00077 } 00078 } 00079 } 00080 } else if ( outl9 >= 0 ) { 00081 kdDebug(5800) << "Generating compat for Outlook < 2000 (Outlook 9.0)" << endl; 00082 compat = new CompatOutlook9; 00083 } 00084 00085 if ( !compat ) compat = new Compat; 00086 00087 return compat; 00088 } 00089 00090 void Compat::fixEmptySummary( Incidence *incidence ) 00091 { 00092 // some stupid vCal exporters ignore the standard and use Description 00093 // instead of Summary for the default field. Correct for this: Copy the 00094 // first line of the description to the summary (if summary is just one 00095 // line, move it) 00096 if (incidence->summary().isEmpty() && 00097 !(incidence->description().isEmpty())) { 00098 TQString oldDescription = incidence->description().stripWhiteSpace(); 00099 TQString newSummary( oldDescription ); 00100 newSummary.remove( TQRegExp("\n.*") ); 00101 incidence->setSummary( newSummary ); 00102 if ( oldDescription == newSummary ) 00103 incidence->setDescription(""); 00104 } 00105 } 00106 00107 void Compat::fixRecurrence( Incidence */*incidence*/ ) 00108 { 00109 // Prevent use of compatibility mode during subsequent changes by the application 00110 // incidence->recurrence()->setCompatVersion(); 00111 } 00112 00118 void CompatPre35::fixRecurrence( Incidence *incidence ) 00119 { 00120 Recurrence* recurrence = incidence->recurrence(); 00121 if (recurrence ) { 00122 TQDateTime start( incidence->dtStart() ); 00123 // kde < 3.5 only had one rrule, so no need to loop over all RRULEs. 00124 RecurrenceRule *r = recurrence->defaultRRule(); 00125 if ( r && !r->dateMatchesRules( start ) ) { 00126 recurrence->addExDateTime( start ); 00127 } 00128 } 00129 00130 // Call base class method now that everything else is done 00131 Compat::fixRecurrence( incidence ); 00132 } 00133 00134 int CompatPre34::fixPriority( int prio ) 00135 { 00136 if ( 0<prio && prio<6 ) { 00137 // adjust 1->1, 2->3, 3->5, 4->7, 5->9 00138 return 2*prio - 1; 00139 } else return prio; 00140 } 00141 00146 void CompatPre32::fixRecurrence( Incidence *incidence ) 00147 { 00148 Recurrence* recurrence = incidence->recurrence(); 00149 if ( recurrence->doesRecur() && recurrence->duration() > 0 ) { 00150 recurrence->setDuration( recurrence->duration() + incidence->recurrence()->exDates().count() ); 00151 } 00152 // Call base class method now that everything else is done 00153 CompatPre35::fixRecurrence( incidence ); 00154 } 00155 00167 void CompatPre31::fixFloatingEnd( TQDate &endDate ) 00168 { 00169 endDate = endDate.addDays( 1 ); 00170 } 00171 00172 void CompatPre31::fixRecurrence( Incidence *incidence ) 00173 { 00174 CompatPre32::fixRecurrence( incidence ); 00175 00176 Recurrence *recur = incidence->recurrence(); 00177 RecurrenceRule *r = 0; 00178 if ( recur ) r = recur->defaultRRule(); 00179 if ( recur && r ) { 00180 int duration = r->duration(); 00181 if ( duration > 0 ) { 00182 // Backwards compatibility for KDE < 3.1. 00183 // rDuration was set to the number of time periods to recur, 00184 // with week start always on a Monday. 00185 // Convert this to the number of occurrences. 00186 r->setDuration( -1 ); 00187 TQDate end( r->startDt().date() ); 00188 bool doNothing = false; 00189 // # of periods: 00190 int tmp = ( duration - 1 ) * r->frequency(); 00191 switch ( r->recurrenceType() ) { 00192 case RecurrenceRule::rWeekly: { 00193 end = end.addDays( tmp * 7 + 7 - end.dayOfWeek() ); 00194 break; } 00195 case RecurrenceRule::rMonthly: { 00196 int month = end.month() - 1 + tmp; 00197 end.setYMD( end.year() + month / 12, month % 12 + 1, 31 ); 00198 break; } 00199 case RecurrenceRule::rYearly: { 00200 end.setYMD( end.year() + tmp, 12, 31); 00201 break; } 00202 default: 00203 doNothing = true; 00204 break; 00205 } 00206 if ( !doNothing ) { 00207 duration = r->durationTo( TQDateTime( end, TQTime( 0, 0, 0 ) ) ); 00208 r->setDuration( duration ); 00209 } 00210 } 00211 00212 /* addYearlyNum */ 00213 // Dates were stored as day numbers, with a fiddle to take account of leap years. 00214 // Convert the day number to a month. 00215 TQValueList<int> days = r->byYearDays(); 00216 if ( !days.isEmpty() ) { 00217 TQValueList<int> months = r->byMonths(); 00218 for ( TQValueListConstIterator<int> it = days.begin(); it != days.end(); ++it ) { 00219 int newmonth = TQDate( r->startDt().date().year(), 1, 1).addDays( (*it) - 1 ).month(); 00220 if ( !months.contains( newmonth ) ) 00221 months.append( newmonth ); 00222 } 00223 r->setByMonths( months ); 00224 days.clear(); 00225 r->setByYearDays( days ); 00226 } 00227 } 00228 00229 00230 } 00231 00235 void CompatOutlook9::fixAlarms( Incidence *incidence ) 00236 { 00237 if ( !incidence ) return; 00238 Alarm::List alarms = incidence->alarms(); 00239 Alarm::List::Iterator it; 00240 for ( it = alarms.begin(); it != alarms.end(); ++it ) { 00241 Alarm *al = *it; 00242 if ( al && al->hasStartOffset() ) { 00243 Duration offsetDuration = al->startOffset(); 00244 int offs = offsetDuration.asSeconds(); 00245 if ( offs>0 ) 00246 offsetDuration = Duration( -offs ); 00247 al->setStartOffset( offsetDuration ); 00248 } 00249 } 00250 }