libkcal

compat.cpp

Go to the documentation of this file.
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 <qregexp.h>
00028 
00029 #include "incidence.h"
00030 
00031 using namespace KCal;
00032 
00033 Compat *CompatFactory::createCompat( const QString &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( QRegExp( "[ /]" ), versionStart + 1 );
00049       if ( versionStop >= 0 ) {
00050         QString 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         QString 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     QString oldDescription = incidence->description().stripWhiteSpace();
00099     QString newSummary( oldDescription );
00100     newSummary.remove( QRegExp("\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     QDateTime 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( QDate &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       QDate 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( QDateTime( end, QTime( 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     QValueList<int> days = r->byYearDays();
00216     if ( !days.isEmpty() ) {
00217       QValueList<int> months = r->byMonths();
00218       for ( QValueListConstIterator<int> it = days.begin(); it != days.end(); ++it ) {
00219         int newmonth = QDate( 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 }