qtopiaformat.cpp
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 <tqdatetime.h> 00023 #include <tqstring.h> 00024 #include <tqptrlist.h> 00025 #include <tqregexp.h> 00026 #include <tqclipboard.h> 00027 #include <tqfile.h> 00028 #include <tqtextstream.h> 00029 #include <tqxml.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 TQtopiaParser : public TQXmlDefaultHandler 00042 { 00043 public: 00044 TQtopiaParser( Calendar *calendar ) : mCalendar( calendar ) {} 00045 00046 bool startElement( const TQString &, const TQString &, const TQString & qName, 00047 const TQXmlAttributes &attributes ) 00048 { 00049 if ( qName == "event" ) { 00050 Event *event = new Event; 00051 TQString uid = "TQtopia" + 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 TQString rtype = attributes.value( "rtype" ); 00067 if ( !rtype.isEmpty() ) { 00068 TQDate startDate = event->dtStart().date(); 00069 00070 TQString freqStr = attributes.value( "rfreq" ); 00071 int freq = freqStr.toInt(); 00072 00073 TQString hasEndDateStr = attributes.value( "rhasenddate" ); 00074 bool hasEndDate = hasEndDateStr == "1"; 00075 00076 TQString endDateStr = attributes.value( "enddt" ); 00077 TQDate endDate = toDateTime( endDateStr ).date(); 00078 00079 TQString weekDaysStr = attributes.value( "rweekdays" ); 00080 int weekDaysNum = weekDaysStr.toInt(); 00081 TQBitArray weekDays( 7 ); 00082 int i; 00083 for( i = 1; i <= 7; ++i ) { 00084 weekDays.setBit( i - 1, ( 2 << i ) & weekDaysNum ); 00085 } 00086 00087 TQString 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 TQBitArray 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 TQString categoryList = attributes.value( "categories" ); 00119 event->setCategories( lookupCategories( categoryList ) ); 00120 00121 TQString 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 TQString uid = "TQtopia" + attributes.value( "Uid" ); 00140 todo->setUid( uid ); 00141 00142 TQString description = attributes.value( "Description" ); 00143 int pos = description.find( '\n' ); 00144 if ( pos > 0 ) { 00145 TQString 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 TQString categoryList = attributes.value( "Categories" ); 00157 todo->setCategories( lookupCategories( categoryList ) ); 00158 00159 TQString completedStr = attributes.value( "Completed" ); 00160 if ( completedStr == "1" ) todo->setCompleted( true ); 00161 00162 TQString 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( TQDateTime( TQDate( 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 TQString id = attributes.value( "id" ); 00178 TQString name = attributes.value( "name" ); 00179 setCategory( id, name ); 00180 } 00181 00182 return true; 00183 } 00184 00185 bool warning ( const TQXmlParseException &exception ) 00186 { 00187 kdDebug(5800) << "WARNING" << endl; 00188 printException( exception ); 00189 return true; 00190 } 00191 00192 bool error ( const TQXmlParseException &exception ) 00193 { 00194 kdDebug(5800) << "ERROR" << endl; 00195 printException( exception ); 00196 return false; 00197 } 00198 00199 bool fatalError ( const TQXmlParseException &exception ) 00200 { 00201 kdDebug(5800) << "FATALERROR" << endl; 00202 printException( exception ); 00203 return false; 00204 } 00205 00206 TQString errorString () 00207 { 00208 return "TQtopiaParser: Error!"; 00209 } 00210 00211 protected: 00212 void printException( const TQXmlParseException &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 TQDateTime toDateTime( const TQString &value ) 00222 { 00223 TQDateTime dt; 00224 dt.setTime_t( value.toUInt() ); 00225 00226 return dt; 00227 } 00228 00229 TQStringList lookupCategories( const TQString &categoryList ) 00230 { 00231 TQStringList categoryIds = TQStringList::split( ";", categoryList ); 00232 TQStringList categories; 00233 TQStringList::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 TQString category( const TQString &id ) 00244 { 00245 TQMap<TQString,TQString>::ConstIterator it = mCategoriesMap.find( id ); 00246 if ( it == mCategoriesMap.end() ) return id; 00247 else return *it; 00248 } 00249 00250 static void setCategory( const TQString &id, const TQString &name ) 00251 { 00252 mCategoriesMap.insert( id, name ); 00253 } 00254 00255 static TQMap<TQString,TQString> mCategoriesMap; 00256 }; 00257 00258 TQMap<TQString,TQString> TQtopiaParser::mCategoriesMap; 00259 00260 TQtopiaFormat::TQtopiaFormat() 00261 { 00262 } 00263 00264 TQtopiaFormat::~TQtopiaFormat() 00265 { 00266 } 00267 00268 bool TQtopiaFormat::load( Calendar *calendar, const TQString &fileName) 00269 { 00270 kdDebug(5800) << "TQtopiaFormat::load() " << fileName << endl; 00271 00272 clearException(); 00273 00274 TQtopiaParser handler( calendar ); 00275 TQFile xmlFile( fileName ); 00276 TQXmlInputSource source( xmlFile ); 00277 TQXmlSimpleReader reader; 00278 reader.setContentHandler( &handler ); 00279 return reader.parse( source ); 00280 } 00281 00282 bool TQtopiaFormat::save( Calendar *calendar, const TQString &fileName ) 00283 { 00284 kdDebug(5800) << "TQtopiaFormat::save(): " << fileName << endl; 00285 00286 clearException(); 00287 00288 TQString text = toString( calendar ); 00289 00290 if ( text.isNull() ) return false; 00291 00292 // TODO: write backup file 00293 00294 TQFile 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 TQTextStream ts( &file ); 00301 ts << text; 00302 file.close(); 00303 00304 return true; 00305 } 00306 00307 bool TQtopiaFormat::fromString( Calendar *, const TQString & ) 00308 { 00309 kdDebug(5800) << "TQtopiaFormat::fromString() not yet implemented." << endl; 00310 return false; 00311 } 00312 00313 TQString TQtopiaFormat::toString( Calendar * ) 00314 { 00315 return TQString(); 00316 }