kitchensync

datebook.cpp

00001 /*
00002     This file is part of KitchenSync.
00003 
00004     Copyright (c) 2002,2003 Holger Freyther <freyther@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 <qdom.h>
00023 #include <qfile.h>
00024 
00025 #include <klocale.h>
00026 
00027 #include <calendarsyncee.h>
00028 #include <libkcal/calendarlocal.h>
00029 
00030 #include "device.h"
00031 #include "datebook.h"
00032 
00033 using namespace OpieHelper;
00034 
00035 namespace {
00036 // from TT
00037 int week ( const QDate &start ) {
00038     int stop = start.day();
00039     int sentinel = start.dayOfWeek();
00040     int dayOfWeek = QDate( start.year(),  start.month(),  1 ).dayOfWeek();
00041     int week = 1;
00042     for ( int i = 1; i < stop; i++ ) {
00043         if ( dayOfWeek++ == sentinel )
00044             week++;
00045         if ( dayOfWeek > 7 )
00046             dayOfWeek = 0;
00047     }
00048     return week;
00049 }
00050 
00051 }
00052 
00053 DateBook::DateBook( CategoryEdit* edit,
00054                     KSync::KonnectorUIDHelper* helper,
00055                     const QString& tz,
00056                     Device *dev )
00057     : Base( edit,  helper,  tz, dev )
00058 {
00059 }
00060 DateBook::~DateBook(){
00061 }
00065 KCal::Event* DateBook::toEvent( QDomElement e, ExtraMap& extraMap, const QStringList& lst) {
00066     KCal::Event* event = new KCal::Event();
00067 
00068     /* Category block */
00069     {
00070     QStringList list = QStringList::split(";",  e.attribute("categories") );
00071     QStringList categories;
00072 
00073     QString cat;
00074     for ( uint i = 0; i < list.count(); i++ ) {
00075         cat = m_edit->categoryById(list[i], "Calendar");
00076     /* only add if name not empty and was not added before */
00077         if (!cat.isEmpty() && !categories.contains(cat) )
00078             categories.append(cat );
00079     }
00080     if (!categories.isEmpty() ) {
00081         event->setCategories( categories );
00082     }
00083 
00084     }
00085 
00086     event->setSummary( e.attribute("description") );
00087     event->setUid( kdeId( "EventSyncEntry",  e.attribute("uid") ) );
00088     event->setDescription( e.attribute("note") );
00089     event->setLocation( e.attribute("location") );
00090     // time
00091 
00092     QString start = e.attribute("start");
00093     event->setDtStart( fromUTC( (time_t) start.toLong() ) );
00094 
00095     QString end = e.attribute("end");
00096     event->setDtEnd( fromUTC( (time_t) end.toLong() ) );
00097 
00098     // type
00099     if ( e.attribute("type") == "AllDay" ) {
00100         event->setFloats( true );
00101     }else{
00102         event->setFloats( false );
00103     }
00104 
00105     // FIXME alarm
00106 
00107 
00108     // Recurrence damn I feared to do that
00109     QString type = e.attribute("rtype");
00110     int freq = e.attribute("rfreq").toInt();
00111     bool hasEnd = e.attribute("rhasenddate").toInt();
00112 
00113     KCal::Recurrence *rec = event->recurrence();
00114     start = e.attribute("created");
00115     rec->setStartDateTime( fromUTC( (time_t) start.toLong() ) );
00116         bool haveRecurrence = true;
00117 
00118     if ( type == "Daily" ) {
00119             rec->setDaily( freq );
00120         // weekly
00121     }else if ( type == "Weekly") {
00122         int days = e.attribute("rweekdays").toInt();
00123         QBitArray bits( 7 );
00124         bits.fill( false );
00125         if ( Monday & days )
00126             bits.setBit( 0 );
00127         if ( Tuesday & days )
00128             bits.setBit( 1 );
00129         if ( Wednesday & days )
00130             bits.setBit( 2 );
00131         if ( Thursday & days )
00132             bits.setBit( 3 );
00133         if ( Friday & days )
00134             bits.setBit( 4 );
00135         if ( Saturday & days )
00136             bits.setBit( 5 );
00137         if ( Sunday & days )
00138             bits.setBit( 6 );
00139 
00140         rec->setWeekly( freq,  bits );
00141     // monthly
00142     }else if ( type == "MonthlyDay" ) {
00143             rec->setMonthly( freq );
00144         // monthly day the  1st Saturday of the month
00145         int rposition = e.attribute("rposition").toInt();
00146         QBitArray array( 7);
00147         array.fill( false );
00148         QDate date = event->dtStart().date();
00149         array.setBit( date.dayOfWeek() - 1 );
00150         rec->addMonthlyPos( rposition, array );
00151 
00152     }else if ( type == "MonthlyDate" ) {
00153             rec->setMonthly( freq );
00154         // int rposition = e.attribute("rposition").toInt();
00155         // That's the default anyway:
00156 //        rec->addMonthlyDay( event->dtStart().date().day() );
00157 
00158     }else if ( type == "Yearly" ) {
00159             rec->setYearly( freq );
00160                 // That's the default anyway:
00161 //        rec->addYearlyNum( event->dtStart().date().dayOfYear() );
00162     } else {
00163             haveRecurrence = false;
00164         }
00165         if ( haveRecurrence && hasEnd ) {
00166         start = e.attribute("enddt");
00167         rec->setEndDate( fromUTC( (time_t) start.toLong() ).date() );
00168     }
00169 
00170     // now save the attributes for later use
00171     extraMap.add("datebook", e.attribute("uid"), e.attributes(), lst );
00172 
00173     return event;
00174 }
00175 
00176 bool DateBook::toKDE( const QString& fileName, ExtraMap& extraMap, KSync::CalendarSyncee *syncee )
00177 {
00178     QFile file( fileName );
00179     if ( !file.open( IO_ReadOnly ) ) {
00180         return false;
00181     }
00182     QDomDocument doc("mydocument");
00183     if ( !doc.setContent( &file ) ) {
00184         return false;
00185     }
00186 
00187     QDomElement docElem = doc.documentElement();
00188     QDomNode n = docElem.firstChild();
00189     QString dummy;
00190     QStringList attr = supportedAttributes();
00191     while (!n.isNull() ) {
00192         QDomElement el = n.toElement();
00193         if (!el.isNull() ) {
00194 
00195             if ( el.tagName() == "events") {
00196 
00197                 QDomNode no = el.firstChild();
00198                 while (!no.isNull() ) {
00199                     QDomElement e = no.toElement();
00200 
00201                     if (!e.isNull() ) {
00202                         if (e.tagName() == "event") {
00203                             KCal::Event* event = toEvent( e, extraMap, attr );
00204                             if (event != 0 ) {
00205                                 KSync::CalendarSyncEntry* entry;
00206                                 entry = new KSync::CalendarSyncEntry( event, syncee );
00207                                 syncee->addEntry( entry );
00208                             }
00209                         }
00210                     }
00211                     no = no.nextSibling();
00212                 }
00213             }
00214             n = n.nextSibling();
00215         }// n.isNULL
00216     }
00217 
00218     return true;
00219 }
00220 
00221 KTempFile* DateBook::fromKDE( KSync::CalendarSyncee* syncee, ExtraMap& extraMap )
00222 {
00223     m_kde2opie.clear();
00224     Kontainer::ValueList newIds = syncee->ids( "EventSyncEntry");
00225     Kontainer::ValueList::ConstIterator idIt;
00226     for ( idIt = newIds.begin(); idIt != newIds.end(); ++idIt ) {
00227         m_helper->addId("EventSyncEntry",  (*idIt).first,  (*idIt).second );
00228     }
00229     KTempFile* tempFile = file();
00230     if ( tempFile->textStream() ) {
00231         QTextStream *stream = tempFile->textStream();
00232         stream->setEncoding( QTextStream::UnicodeUTF8 );
00233         *stream <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
00234         *stream << "<!DOCTYPE DATEBOOK><DATEBOOK>" << endl;
00235         KSync::CalendarSyncEntry *entry;
00236         KCal::Event *event;
00237         *stream << "<events>" << endl;
00238         for ( entry = (KSync::CalendarSyncEntry*) syncee->firstEntry();
00239               entry != 0;
00240               entry = (KSync::CalendarSyncEntry*) syncee->nextEntry() )
00241         {
00242             /*  do not safe deleted records */
00243             if ( entry->wasRemoved() )
00244               continue;
00245             event = dynamic_cast<KCal::Event*>( entry->incidence() );
00246             if ( !event )
00247               continue;
00248 
00249             *stream << event2string( event, extraMap ) << endl;
00250         }
00251         *stream << "</events>" << endl;
00252         *stream << "</DATEBOOK>" << endl;
00253 
00254     }
00255     if (m_helper )
00256         m_helper->replaceIds( "EventSyncEntry",  m_kde2opie );
00257 
00258     tempFile->close();
00259     return tempFile;
00260 }
00261 QString DateBook::event2string( KCal::Event *event, ExtraMap& map )
00262 {
00263     QString uid = konnectorId("EventSyncEntry", event->uid() );
00264     bool doesFloat = event->doesFloat();
00265     QString str;
00266     str.append( "<event ");
00267     str.append( "description=\"" +escape( event->summary() ) + "\" ");
00268 
00269     str.append( appendText( "location=\"" + escape( event->location() ) + "\" ",
00270                             "location=\"\" ") );
00271     str.append( appendText( "categories=\"" +
00272                             categoriesToNumber( event->categories() ) + "\" ",
00273                             "categories=\"\" ") );
00274 
00275     str.append( "uid=\"" + uid  + "\" ");
00276     str.append( "start=\"" +startDate( event->dtStart(), doesFloat ) + "\" ");
00277     str.append( "end=\"" +  endDate( event->dtEnd(), doesFloat) + "\" ");
00278 
00279     str.append( appendText("note=\"" + escape( event->description() ) + "\" ",
00280                            "note=\"\" ")); //use escapeString copied from TT
00281     if ( doesFloat )
00282         str.append( "type=\"AllDay\" ");
00283     // recurrence
00284     KCal::Recurrence *rec = event->recurrence();
00285     if ( rec->doesRecur() ) {
00286         QString type;
00287         switch( rec->recurrenceType() ) {
00288         case KCal::Recurrence::rDaily :{
00289             type = "Daily";
00290             break;
00291         }
00292         case KCal::Recurrence::rWeekly :{
00293             type = "Weekly";
00294             signed char day = 0;
00295             QBitArray array = rec->days();
00296             if ( array.testBit(0 ) ) day |= Monday;
00297             if ( array.testBit(1 ) ) day |= Tuesday;
00298             if ( array.testBit(2 ) ) day |= Wednesday;
00299             if ( array.testBit(3 ) ) day |= Thursday;
00300             if ( array.testBit(4 ) ) day |= Friday;
00301             if ( array.testBit(5 ) ) day |= Saturday;
00302             if ( array.testBit(6 ) ) day |= Sunday;
00303 
00304             /* need to be > 0  we set the repeat day to the day where the event takes place*/
00305             if ( day < 0 ) {
00306                 switch( event->dtStart().date().dayOfWeek() ) {
00307                 case 1: // Monday
00308                     day = Monday;
00309                     break;
00310                 case 2: // Tuesday
00311                     day = Tuesday;
00312                     break;
00313                 case 3: // Wednesday
00314                     day = Wednesday;
00315                     break;
00316                 case 4: //  Thursday
00317                     day = Thursday;
00318                     break;
00319                 case 5: // Friday
00320                     day = Friday;
00321                     break;
00322                 case 6: // Staurday
00323                     day = Saturday;
00324                     break;
00325                 default:// should never happen
00326                 case 7: // Sunday
00327                     day = Sunday;
00328                     break;
00329                 }
00330 
00331             }
00332             str.append( "rweekdays=\"" + QString::number(static_cast<int> (day) ) + "\" ");
00333             break;
00334         }
00335         case KCal::Recurrence::rMonthlyPos :{
00336             int rpos = week( event->dtStart().date() );
00337             if ( rpos != 0 )
00338                 str.append( "rposition=\"" + QString::number(rpos)  + "\" ");
00339             type = "MonthlyDay";
00340             break;
00341         }
00342         case KCal::Recurrence::rMonthlyDay :{
00343             type = "MonthlyDate";
00344 
00345             break;
00346         }
00347         case KCal::Recurrence::rYearlyMonth: // fall through
00348         case KCal::Recurrence::rYearlyPos: // fall through Might be wrong though
00349         case KCal::Recurrence::rYearlyDay :{
00350             type = "Yearly";
00351             break;
00352         }
00353         case KCal::Recurrence::rNone : // fall through
00354         default :
00355             type = QString::null;
00356             break;
00357         }
00358         if (!type.isEmpty() ) {
00359             str.append( "rtype=\"" + type + "\" ");
00360             str.append( "rfreq=\"" + QString::number( rec->frequency() ) + "\" ");
00361             if ( rec->duration() == -1 || rec->duration() != 0 )
00362                 str.append( "rhasenddate=\"0\" ");
00363             else if ( rec->duration() == 0 ) {
00364                 str.append( "rhasenddate=\"1\" ");
00365                 str.append( "enddt=\"" + QString::number( toUTC(rec->endDate() ) ) + "\" ");
00366             }
00367             str.append( "created=\"" + QString::number( toUTC(rec->startDateTime() ) ) + "\" ");
00368         }
00369     }
00370     // FIXME alarm
00371     str += map.toString( "datebook", uid );
00372     str.append( " />" );
00373     return str;
00374 }
00375 /*
00376  * A list of attributes we handle
00377  */
00378 QStringList DateBook::supportedAttributes(){
00379     QStringList lst;
00380     lst << "description";
00381     lst << "location";
00382     lst << "categories";
00383     lst << "uid";
00384     lst << "start";
00385     lst << "end";
00386     lst << "note";
00387     lst << "type";
00388     lst << "rweekdays";
00389     lst << "rposition";
00390     lst << "rtype";
00391     lst << "rfreq";
00392     lst << "rhasenddate";
00393     lst << "enddt";
00394     lst << "created";
00395     /*
00396      * we need to handle Recurrence Exceptions
00397      * alarms, timezones later
00398      */
00399     return lst;
00400 }
00401 /*
00402  * Qtopia etwartet AllDay events in einer Zeitspanne von 00:00:00
00403  * bis 23:59:59... but in korg bdays are from 00:00:00 - 00:00:00 (
00404  * no time associated )
00405  * He'll help Qtopia here if it's an all day event we will produce
00406  * a better time...
00407  */
00408 QString DateBook::startDate( const QDateTime& _dt,  bool allDay ) {
00409     QDateTime dt = _dt;
00410     if (allDay )
00411         dt.setTime( QTime(0, 0, 0 ) );
00412 
00413     return QString::number( toUTC( dt ) );
00414 }
00415 QString DateBook::endDate( const QDateTime& _dt,  bool allDay ) {
00416     QDateTime dt = _dt;
00417     if (allDay )
00418         dt.setTime( QTime(23, 59, 59 ) );
00419 
00420     return QString::number( toUTC(dt ) );
00421 }
00422 
KDE Home | KDE Accessibility Home | Description of Access Keys