libkcal

qtopiaformat.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <qdatetime.h>
00023 #include <qstring.h>
00024 #include <qptrlist.h>
00025 #include <qregexp.h>
00026 #include <qclipboard.h>
00027 #include <qfile.h>
00028 #include <qtextstream.h>
00029 #include <qxml.h>
00030 
00031 #include <kdebug.h>
00032 #include <klocale.h>
00033 
00034 #include "calendar.h"
00035 #include "calendarlocal.h"
00036 
00037 #include "qtopiaformat.h"
00038 
00039 using namespace KCal;
00040 
00041 class QtopiaParser : public QXmlDefaultHandler
00042 {
00043   public:
00044     QtopiaParser( Calendar *calendar ) : mCalendar( calendar ) {}
00045   
00046     bool startElement( const QString &, const QString &, const QString & qName, 
00047                        const QXmlAttributes &attributes )
00048     {
00049       if ( qName == "event" ) {
00050         Event *event = new Event;
00051         QString uid = "Qtopia" + attributes.value( "uid" );
00052         event->setUid( uid );
00053 
00054         event->setSummary( attributes.value( "description" ) );
00055         event->setLocation( attributes.value( "location" ) );
00056         event->setDescription( attributes.value( "note" ) );
00057         event->setDtStart( toDateTime( attributes.value( "start" ) ) );
00058         event->setDtEnd( toDateTime( attributes.value( "end" ) ) );
00059 
00060         if ( attributes.value( "type" ) == "AllDay" ) {
00061           event->setFloats( true );
00062         } else {
00063           event->setFloats( false );
00064         }
00065 
00066         QString rtype = attributes.value( "rtype" );
00067         if ( !rtype.isEmpty() ) {
00068           QDate startDate = event->dtStart().date();
00069         
00070           QString freqStr = attributes.value( "rfreq" );
00071           int freq = freqStr.toInt();
00072 
00073           QString hasEndDateStr = attributes.value( "rhasenddate" );
00074           bool hasEndDate = hasEndDateStr == "1";
00075 
00076           QString endDateStr = attributes.value( "enddt" );
00077           QDate endDate = toDateTime( endDateStr ).date();
00078 
00079           QString weekDaysStr = attributes.value( "rweekdays" );
00080           int weekDaysNum = weekDaysStr.toInt();
00081           QBitArray weekDays( 7 );
00082           int i;
00083           for( i = 1; i <= 7; ++i ) {
00084             weekDays.setBit( i - 1, ( 2 << i ) & weekDaysNum ); 
00085           }
00086 
00087           QString posStr = attributes.value( "rposition" );
00088           int pos = posStr.toInt();
00089 
00090           Recurrence *r = event->recurrence();
00091 
00092           if ( rtype == "Daily" ) {
00093             r->setDaily( freq );
00094             if ( hasEndDate ) r->setEndDate( endDate );
00095           } else if ( rtype == "Weekly" ) {
00096             r->setWeekly( freq, weekDays );
00097             if ( hasEndDate ) r->setEndDate( endDate );
00098           } else if ( rtype == "MonthlyDate" ) {
00099             r->setMonthly( freq );
00100             if ( hasEndDate )
00101               r->setEndDate( endDate );
00102             r->addMonthlyDate( startDate.day() );
00103           } else if ( rtype == "MonthlyDay" ) {
00104             r->setMonthly( freq );
00105             if ( hasEndDate )
00106               r->setEndDate( endDate );
00107             QBitArray days( 7 );
00108             days.fill( false );
00109             days.setBit( startDate.dayOfWeek() - 1 );
00110             r->addMonthlyPos( pos, days );
00111           } else if ( rtype == "Yearly" ) {
00112             r->setYearly( freq );
00113             if ( hasEndDate )
00114               r->setEndDate( endDate );
00115           }
00116         }
00117 
00118         QString categoryList = attributes.value( "categories" );
00119         event->setCategories( lookupCategories( categoryList ) );
00120 
00121         QString alarmStr = attributes.value( "alarm" );
00122         if ( !alarmStr.isEmpty() ) {
00123           kdDebug(5800) << "Alarm: " << alarmStr << endl;
00124           Alarm *alarm = new Alarm( event );
00125           alarm->setType( Alarm::Display );
00126           alarm->setEnabled( true );
00127           int alarmOffset = alarmStr.toInt();
00128           alarm->setStartOffset( alarmOffset * -60 );
00129           event->addAlarm( alarm );
00130         }
00131 
00132         Event *oldEvent = mCalendar->event( uid );
00133         if ( oldEvent ) mCalendar->deleteEvent( oldEvent );
00134 
00135         mCalendar->addEvent( event );
00136       } else if ( qName == "Task" ) {
00137         Todo *todo = new Todo;
00138 
00139         QString uid = "Qtopia" + attributes.value( "Uid" );
00140         todo->setUid( uid );
00141         
00142         QString description = attributes.value( "Description" );
00143         int pos = description.find( '\n' );
00144         if ( pos > 0 ) {
00145           QString summary = description.left( pos );
00146           todo->setSummary( summary );
00147           todo->setDescription( description );
00148         } else {
00149           todo->setSummary( description );
00150         }
00151         
00152         int priority = attributes.value( "Priority" ).toInt();
00153 //        if ( priority == 0 ) priority = 3;
00154         todo->setPriority( priority );
00155         
00156         QString categoryList = attributes.value( "Categories" );
00157         todo->setCategories( lookupCategories( categoryList ) );
00158         
00159         QString completedStr = attributes.value( "Completed" );
00160         if ( completedStr == "1" ) todo->setCompleted( true );
00161         
00162         QString hasDateStr = attributes.value( "HasDate" );
00163         if ( hasDateStr == "1" ) {
00164           int year = attributes.value( "DateYear" ).toInt();
00165           int month = attributes.value( "DateMonth" ).toInt();
00166           int day = attributes.value( "DateDay" ).toInt();
00167           
00168           todo->setDtDue( QDateTime( QDate( year, month, day ) ) );
00169           todo->setHasDueDate( true );
00170         }
00171         
00172         Todo *oldTodo = mCalendar->todo( uid );
00173         if ( oldTodo ) mCalendar->deleteTodo( oldTodo );
00174 
00175         mCalendar->addTodo( todo );
00176       } else if ( qName == "Category" ) {
00177         QString id = attributes.value( "id" );
00178         QString name = attributes.value( "name" );
00179         setCategory( id, name );
00180       }
00181       
00182       return true;
00183     }
00184 
00185     bool warning ( const QXmlParseException &exception )
00186     {
00187       kdDebug(5800) << "WARNING" << endl;
00188       printException( exception );
00189       return true;
00190     }
00191  
00192     bool error ( const QXmlParseException &exception )
00193     {
00194       kdDebug(5800) << "ERROR" << endl;
00195       printException( exception );
00196       return false;
00197     }
00198  
00199     bool fatalError ( const QXmlParseException &exception )
00200     {
00201       kdDebug(5800) << "FATALERROR" << endl;
00202       printException( exception );
00203       return false;
00204     }
00205  
00206     QString errorString ()
00207     {
00208       return "QtopiaParser: Error!";
00209     }
00210 
00211   protected:
00212     void printException( const QXmlParseException &exception )
00213     {
00214       kdError() << "XML Parse Error (line " << exception.lineNumber()
00215                 << ", col " << exception.columnNumber() << "): "
00216                 << exception.message() << "(public ID: '"
00217                 << exception.publicId() << "' system ID: '"
00218                 << exception.systemId() << "')" << endl;
00219     }
00220 
00221     QDateTime toDateTime( const QString &value )
00222     {
00223       QDateTime dt;
00224       dt.setTime_t( value.toUInt() );
00225       
00226       return dt;
00227     }
00228 
00229     QStringList lookupCategories( const QString &categoryList )
00230     {
00231       QStringList categoryIds = QStringList::split( ";", categoryList );
00232       QStringList categories;
00233       QStringList::ConstIterator it;
00234       for( it = categoryIds.begin(); it != categoryIds.end(); ++it ) {
00235         categories.append( category( *it ) );
00236       }
00237       return categories;
00238     }
00239 
00240   private:
00241     Calendar *mCalendar;
00242 
00243     static QString category( const QString &id )
00244     {
00245       QMap<QString,QString>::ConstIterator it = mCategoriesMap.find( id );
00246       if ( it == mCategoriesMap.end() ) return id;
00247       else return *it;
00248     }
00249 
00250     static void setCategory( const QString &id, const QString &name )
00251     {
00252       mCategoriesMap.insert( id, name );
00253     }
00254 
00255     static QMap<QString,QString> mCategoriesMap;
00256 };
00257 
00258 QMap<QString,QString> QtopiaParser::mCategoriesMap;
00259 
00260 QtopiaFormat::QtopiaFormat()
00261 {
00262 }
00263 
00264 QtopiaFormat::~QtopiaFormat()
00265 {
00266 }
00267 
00268 bool QtopiaFormat::load( Calendar *calendar, const QString &fileName)
00269 {
00270   kdDebug(5800) << "QtopiaFormat::load() " << fileName << endl;
00271 
00272   clearException();
00273 
00274   QtopiaParser handler( calendar );
00275   QFile xmlFile( fileName );
00276   QXmlInputSource source( xmlFile );
00277   QXmlSimpleReader reader;
00278   reader.setContentHandler( &handler );
00279   return reader.parse( source );
00280 }
00281 
00282 bool QtopiaFormat::save( Calendar *calendar, const QString &fileName )
00283 {
00284   kdDebug(5800) << "QtopiaFormat::save(): " << fileName << endl;
00285 
00286   clearException();
00287 
00288   QString text = toString( calendar );
00289 
00290   if ( text.isNull() ) return false;
00291 
00292   // TODO: write backup file
00293 
00294   QFile file( fileName );
00295   if (!file.open( IO_WriteOnly ) ) {
00296     setException(new ErrorFormat(ErrorFormat::SaveError,
00297                  i18n("Could not open file '%1'").arg(fileName)));
00298     return false;
00299   }
00300   QTextStream ts( &file );
00301   ts << text;
00302   file.close();
00303 
00304   return true;
00305 }
00306 
00307 bool QtopiaFormat::fromString( Calendar *, const QString & )
00308 {
00309   kdDebug(5800) << "QtopiaFormat::fromString() not yet implemented." << endl;
00310   return false;
00311 }
00312 
00313 QString QtopiaFormat::toString( Calendar * )
00314 {
00315   return QString::null;
00316 }