29 files changed, 1751 insertions, 1104 deletions
diff --git a/libopie/libopie.pro b/libopie/libopie.pro index 675e1fa..2b843c1 100644 --- a/libopie/libopie.pro +++ b/libopie/libopie.pro @@ -1,108 +1,112 @@ TEMPLATE = lib CONFIG += qte warn_on release HEADERS = ofontmenu.h \ ocolorbutton.h \ - ofiledialog.h ofileselector.h tododb.h \ - ocheckitem.h todoevent.h todoresource.h \ - todovcalresource.h xmltree.h \ + ofiledialog.h ofileselector.h \ + ocheckitem.h \ + xmltree.h \ colordialog.h colorpopupmenu.h \ oclickablelabel.h oprocctrl.h \ oprocess.h odevice.h odevicebutton.h \ otimepicker.h otabwidget.h \ otabbar.h otabinfo.h \ ofontselector.h \ pim/opimrecord.h \ pim/otodo.h \ pim/orecordlist.h \ pim/opimaccesstemplate.h \ pim/opimaccessbackend.h \ pim/otodoaccess.h \ pim/otodoaccessbackend.h \ pim/ocontact.h \ pim/ocontactaccess.h \ pim/ocontactaccessbackend.h \ pim/ocontactaccessbackend_xml.h \ pim/ocontactaccessbackend_vcard.h \ pim/obackendfactory.h \ pim/opimcache.h \ pim/otodoaccessvcal.h \ pim/orecur.h \ pim/opimstate.h \ pim/opimxrefpartner.h \ pim/opimxref.h \ pim/opimxrefmanager.h \ pim/opimmaintainer.h \ pim/opimnotify.h \ pim/opimnotifymanager.h \ pim/opimmainwindow.h \ pim/opimresolver.h \ + pim/oevent.h \ + pim/otimezone.h \ orecurrancewidget.h \ oticker.h # pim/otodoaccesssql.h \ SOURCES = ofontmenu.cc \ ocolorbutton.cpp \ sharp_compat.cpp \ xmltree.cc \ ofiledialog.cc ofileselector.cc \ - ocheckitem.cpp tododb.cpp todoevent.cpp \ - todovcalresource.cpp colordialog.cpp \ + ocheckitem.cpp \ + colordialog.cpp \ colorpopupmenu.cpp oclickablelabel.cpp \ oprocctrl.cpp oprocess.cpp \ odevice.cpp odevicebutton.cpp otimepicker.cpp \ otabwidget.cpp otabbar.cpp \ ofontselector.cpp \ pim/otodo.cpp \ pim/opimrecord.cpp \ pim/otodoaccess.cpp \ pim/otodoaccessbackend.cpp \ pim/otodoaccessxml.cpp \ pim/ocontact.cpp \ pim/ocontactaccess.cpp \ pim/ocontactaccessbackend_vcard.cpp \ pim/otodoaccessvcal.cpp \ pim/orecur.cpp \ pim/opimstate.cpp \ pim/opimxrefpartner.cpp \ pim/opimxref.cpp \ pim/opimxrefmanager.cpp \ pim/opimmaintainer.cpp \ pim/opimnotify.cpp \ pim/opimnotifymanager.cpp \ pim/opimmainwindow.cpp \ pim/opimresolver.cpp \ + pim/oevent.cpp \ + pim/otimezone.cpp \ orecurrancewidget.cpp \ oticker.cpp # pim/otodoaccesssql.cpp \ TARGET = opie INCLUDEPATH += $(OPIEDIR)/include DESTDIR = $(OPIEDIR)/lib$(PROJMAK) #VERSION = 1.0.0 LIBS += -lqpe # LIBS += -lopiesql INTERFACES = otimepickerbase.ui orecurrancebase.ui TRANSLATIONS = ../i18n/de/libopie.ts \ ../i18n/xx/libopie.ts \ ../i18n/en/libopie.ts \ ../i18n/es/libopie.ts \ ../i18n/fr/libopie.ts \ ../i18n/hu/libopie.ts \ ../i18n/ja/libopie.ts \ ../i18n/ko/libopie.ts \ ../i18n/no/libopie.ts \ ../i18n/pl/libopie.ts \ ../i18n/pt/libopie.ts \ ../i18n/pt_BR/libopie.ts \ ../i18n/sl/libopie.ts \ ../i18n/zh_CN/libopie.ts \ ../i18n/zh_TW/libopie.ts \ ../i18n/da/libopie.ts include ( $(OPIEDIR)/include.pro ) diff --git a/libopie/orecurrancewidget.cpp b/libopie/orecurrancewidget.cpp index 0484ab9..db86184 100644 --- a/libopie/orecurrancewidget.cpp +++ b/libopie/orecurrancewidget.cpp @@ -1,564 +1,564 @@ #include <qapplication.h> #include <qlabel.h> #include <qpopupmenu.h> #include <qspinbox.h> #include <qpe/timestring.h> #include "orecurrancewidget.h" // Global Templates for use in setting up the repeat label... const QString strDayTemplate = QObject::tr("Every"); const QString strYearTemplate = QObject::tr("%1 %2 every "); const QString strMonthDateTemplate = QObject::tr("The %1 every "); const QString strMonthDayTemplate = QObject::tr("The %1 %1 of every"); const QString strWeekTemplate = QObject::tr("Every "); const QString dayLabel[] = { QObject::tr("Monday"), QObject::tr("Tuesday"), QObject::tr("Wednesday"), QObject::tr("Thursday"), QObject::tr("Friday"), QObject::tr("Saturday"), QObject::tr("Sunday") }; static QString numberPlacing( int x ); // return the proper word format for // x (1st, 2nd, etc) static int week( const QDate &dt ); // what week in the month is dt? ORecurranceWidget::ORecurranceWidget( bool startOnMonday, const QDate& newStart, QWidget* parent, const char* name, bool modal, WFlags fl ) : ORecurranceBase( parent, name, modal, fl ), start( newStart ), currInterval( None ), startWeekOnMonday( startOnMonday ) { init(); fraType->setButton( currInterval ); chkNoEnd->setChecked( TRUE ); setupNone(); } ORecurranceWidget::ORecurranceWidget( bool startOnMonday, const ORecur& rp, const QDate& startDate, QWidget* parent, const char* name, bool modal, WFlags fl) : ORecurranceBase( parent, name, modal, fl ), start( startDate ), end( rp.endDate() ), startWeekOnMonday( startOnMonday ) { // do some stuff with the repeat pattern init(); setRecurrence( rp ); } ORecurranceWidget::~ORecurranceWidget() { } void ORecurranceWidget::setStartDate( const QDate& date ) { qWarning("ORecurranceWidget::setStartDate"); setRecurrence( recurrence(), date ); } void ORecurranceWidget::setRecurrence( const ORecur& rp ) { setRecurrence( rp, start ); } void ORecurranceWidget::setRecurrence( const ORecur& rp, const QDate& date ) { start = date; end = rp.endDate(); switch ( rp.type() ) { default: case ORecur::NoRepeat: currInterval = None; setupNone(); break; case ORecur::Daily: currInterval = Day; setupDaily(); break; case ORecur::Weekly: currInterval = Week; setupWeekly(); int day, buttons; for ( day = 0x01, buttons = 0; buttons < 7; day = day << 1, buttons++ ) { if ( rp.days() & day ) { if ( startWeekOnMonday ) fraExtra->setButton( buttons ); else { if ( buttons == 7 ) fraExtra->setButton( 0 ); else fraExtra->setButton( buttons + 1 ); } } } slotWeekLabel(); break; case ORecur::MonthlyDay: currInterval = Month; setupMonthly(); fraExtra->setButton( 0 ); slotMonthLabel( 0 ); break; case ORecur::MonthlyDate: currInterval = Month; setupMonthly(); fraExtra->setButton( 1 ); slotMonthLabel( 1 ); break; case ORecur::Yearly: currInterval = Year; setupYearly(); break; } fraType->setButton( currInterval ); spinFreq->setValue( rp.frequency() ); if ( !rp.hasEndDate() ) { cmdEnd->setText( tr("No End Date") ); chkNoEnd->setChecked( TRUE ); } else cmdEnd->setText( TimeString::shortDate( end ) ); } ORecur ORecurranceWidget::recurrence()const { QListIterator<QToolButton> it( listRTypeButtons ); QListIterator<QToolButton> itExtra( listExtra ); ORecur rpTmp; int i; for ( i = 0; *it; ++it, i++ ) { if ( (*it)->isOn() ) { switch ( i ) { case None: rpTmp.setType( ORecur::NoRepeat ); break; case Day: rpTmp.setType( ORecur::Daily ); break; case Week:{ rpTmp.setType( ORecur::Weekly ); int day; int day2 = 0; for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) { if ( (*itExtra)->isOn() ) { if ( startWeekOnMonday ) day2 |= day; else { if ( day == 1 ) day2 |= Event::SUN; else day2 |= day >> 1; } } } rpTmp.setDays( day2 ); } break; case Month: if ( cmdExtra1->isOn() ) rpTmp.setType( ORecur::MonthlyDay ); else if ( cmdExtra2->isOn() ) rpTmp.setType( ORecur::MonthlyDate ); // figure out the montly day... rpTmp.setPosition( week( start ) ); break; case Year: rpTmp.setType( ORecur::Yearly ); break; } break; // no need to keep looking! } } rpTmp.setFrequency(spinFreq->value() ); rpTmp.setHasEndDate( !chkNoEnd->isChecked() ); if ( rpTmp.hasEndDate() ) { rpTmp.setEndDate( end ); } // timestamp it... - rpTmp.setCreateTime( time( NULL ) ); +// rpTmp.setCreateTime( ); current DateTime is already set -zecke return rpTmp; } QDate ORecurranceWidget::endDate()const { return end; } void ORecurranceWidget::slotSetRType(int rtype) { // now call the right function based on the type... currInterval = static_cast<repeatButtons>(rtype); switch ( currInterval ) { case None: setupNone(); break; case Day: setupDaily(); break; case Week: setupWeekly(); slotWeekLabel(); break; case Month: setupMonthly(); cmdExtra2->setOn( TRUE ); slotMonthLabel( 1 ); break; case Year: setupYearly(); break; } } void ORecurranceWidget::endDateChanged(int y, int m, int d) { end.setYMD( y, m, d ); if ( end < start ) end = start; cmdEnd->setText( TimeString::shortDate( end ) ); repeatPicker->setDate( end.year(), end.month(), end.day() ); } void ORecurranceWidget::slotNoEnd( bool unused) { // if the item was toggled, then go ahead and set it to the maximum date if ( unused ) { end.setYMD( 3000, 12, 31 ); cmdEnd->setText( tr("No End Date") ); } else { end = start; cmdEnd->setText( TimeString::shortDate(end) ); } } void ORecurranceWidget::setupRepeatLabel( const QString& s) { lblVar1->setText( s ); } void ORecurranceWidget::setupRepeatLabel( int x) { // change the spelling based on the value of x QString strVar2; if ( x > 1 ) lblVar1->show(); else lblVar1->hide(); switch ( currInterval ) { case None: break; case Day: if ( x > 1 ) strVar2 = tr( "days" ); else strVar2 = tr( "day" ); break; case Week: if ( x > 1 ) strVar2 = tr( "weeks" ); else strVar2 = tr( "week" ); break; case Month: if ( x > 1 ) strVar2 = tr( "months" ); else strVar2 = tr( "month" ); break; case Year: if ( x > 1 ) strVar2 = tr( "years" ); else strVar2 = tr( "year" ); break; } if ( !strVar2.isNull() ) lblVar2->setText( strVar2 ); } void ORecurranceWidget::slotWeekLabel() { QString str; QListIterator<QToolButton> it( listExtra ); unsigned int i; unsigned int keepMe; bool bNeedCarriage = FALSE; // don't do something we'll regret!!! if ( currInterval != Week ) return; if ( startWeekOnMonday ) keepMe = start.dayOfWeek() - 1; else keepMe = start.dayOfWeek() % 7; QStringList list; for ( i = 0; *it; ++it, i++ ) { // a crazy check, if you are repeating weekly, the current day // must be selected!!! if ( i == keepMe && !( (*it)->isOn() ) ) (*it)->setOn( TRUE ); if ( (*it)->isOn() ) { if ( startWeekOnMonday ) list.append( dayLabel[i] ); else { if ( i == 0 ) list.append( dayLabel[6] ); else list.append( dayLabel[i - 1] ); } } } QStringList::Iterator itStr; for ( i = 0, itStr = list.begin(); itStr != list.end(); ++itStr, i++ ) { if ( i == 3 ) bNeedCarriage = TRUE; else bNeedCarriage = FALSE; if ( str.isNull() ) str = *itStr; else if ( i == list.count() - 1 ) { if ( i < 2 ) str += tr(" and ") + *itStr; else { if ( bNeedCarriage ) str += tr( ",\nand " ) + *itStr; else str += tr( ", and " ) + *itStr; } } else { if ( bNeedCarriage ) str += ",\n" + *itStr; else str += ", " + *itStr; } } str = str.prepend( "on " ); lblWeekVar->setText( str ); } void ORecurranceWidget::slotMonthLabel(int type) { QString str; if ( currInterval != Month || type > 1 ) return; if ( type == 1 ) str = strMonthDateTemplate.arg( numberPlacing(start.day()) ); else str = strMonthDayTemplate.arg( numberPlacing(week(start))) .arg( dayLabel[start.dayOfWeek() - 1] ); lblRepeat->setText( str ); } void ORecurranceWidget::slotChangeStartOfWeek( bool onMonday ) { startWeekOnMonday = onMonday; // we need to make this unintrusive as possible... int saveSpin = spinFreq->value(); char days = 0; int day; QListIterator<QToolButton> itExtra( listExtra ); for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) { if ( (*itExtra)->isOn() ) { if ( !startWeekOnMonday ) days |= day; else { if ( day == 1 ) days |= ORecur::SUN; else days |= day >> 1; } } } setupWeekly(); spinFreq->setValue( saveSpin ); int buttons; for ( day = 0x01, buttons = 0; buttons < 7; day = day << 1, buttons++ ) { if ( days & day ) { if ( startWeekOnMonday ) fraExtra->setButton( buttons ); else { if ( buttons == 7 ) fraExtra->setButton( 0 ); else fraExtra->setButton( buttons + 1 ); } } } slotWeekLabel(); } void ORecurranceWidget::setupNone() { lblRepeat->setText( tr("No Repeat") ); lblVar1->hide(); lblVar2->hide(); hideExtras(); cmdEnd->hide(); lblFreq->hide(); lblEvery->hide(); lblFreq->hide(); spinFreq->hide(); lblEnd->hide(); lblWeekVar->hide(); } void ORecurranceWidget::setupDaily() { hideExtras(); lblWeekVar->hide(); spinFreq->setValue( 1 ); lblFreq->setText( tr("day(s)") ); lblVar2->show(); showRepeatStuff(); lblRepeat->setText( strDayTemplate ); setupRepeatLabel( 1 ); } void ORecurranceWidget::setupWeekly() { // reshow the buttons... fraExtra->setTitle( tr("Repeat On") ); fraExtra->setExclusive( FALSE ); fraExtra->show(); if ( startWeekOnMonday ) { cmdExtra1->setText( tr("Mon") ); cmdExtra2->setText( tr("Tue") ); cmdExtra3->setText( tr("Wed") ); cmdExtra4->setText( tr("Thu") ); cmdExtra5->setText( tr("Fri") ); cmdExtra6->setText( tr("Sat") ); cmdExtra7->setText( tr("Sun") ); } else { cmdExtra1->setText( tr("Sun") ); cmdExtra2->setText( tr("Mon") ); cmdExtra3->setText( tr("Tue") ); cmdExtra4->setText( tr("Wed") ); cmdExtra5->setText( tr("Thu") ); cmdExtra6->setText( tr("Fri") ); cmdExtra7->setText( tr("Sat") ); } // I hope clustering these improve performance.... cmdExtra1->setOn( FALSE ); cmdExtra2->setOn( FALSE ); cmdExtra3->setOn( FALSE ); cmdExtra4->setOn( FALSE ); cmdExtra5->setOn( FALSE ); cmdExtra6->setOn( FALSE ); cmdExtra7->setOn( FALSE ); cmdExtra1->show(); cmdExtra2->show(); cmdExtra3->show(); cmdExtra4->show(); cmdExtra5->show(); cmdExtra6->show(); cmdExtra7->show(); lblWeekVar->show(); spinFreq->setValue( 1 ); // might as well set the day too... if ( startWeekOnMonday ) { fraExtra->setButton( start.dayOfWeek() - 1 ); } else { fraExtra->setButton( start.dayOfWeek() % 7 ); } lblFreq->setText( tr("week(s)") ); lblVar2->show(); showRepeatStuff(); setupRepeatLabel( 1 ); } void ORecurranceWidget::setupMonthly() { hideExtras(); lblWeekVar->hide(); fraExtra->setTitle( tr("Repeat By") ); fraExtra->setExclusive( TRUE ); fraExtra->show(); cmdExtra1->setText( tr("Day") ); cmdExtra1->show(); cmdExtra2->setText( tr("Date") ); cmdExtra2->show(); spinFreq->setValue( 1 ); lblFreq->setText( tr("month(s)") ); lblVar2->show(); showRepeatStuff(); setupRepeatLabel( 1 ); } void ORecurranceWidget::setupYearly() { hideExtras(); lblWeekVar->hide(); spinFreq->setValue( 1 ); lblFreq->setText( tr("year(s)") ); lblFreq->show(); lblFreq->show(); showRepeatStuff(); lblVar2->show(); QString strEvery = strYearTemplate.arg( start.monthName(start.month()) ).arg( numberPlacing(start.day()) ); lblRepeat->setText( strEvery ); setupRepeatLabel( 1 ); } void ORecurranceWidget::init() { QPopupMenu *m1 = new QPopupMenu( this ); repeatPicker = new DateBookMonth( m1, 0, TRUE ); m1->insertItem( repeatPicker ); cmdEnd->setPopup( m1 ); cmdEnd->setPopupDelay( 0 ); QObject::connect( repeatPicker, SIGNAL(dateClicked(int, int, int)), this, SLOT(endDateChanged(int, int, int)) ); QObject::connect( qApp, SIGNAL(weekChanged(bool)), this, SLOT(slotChangeStartOfWeek(bool)) ); listRTypeButtons.setAutoDelete( TRUE ); listRTypeButtons.append( cmdNone ); listRTypeButtons.append( cmdDay ); listRTypeButtons.append( cmdWeek ); listRTypeButtons.append( cmdMonth ); listRTypeButtons.append( cmdYear ); listExtra.setAutoDelete( TRUE ); listExtra.append( cmdExtra1 ); listExtra.append( cmdExtra2 ); listExtra.append( cmdExtra3 ); listExtra.append( cmdExtra4 ); listExtra.append( cmdExtra5 ); listExtra.append( cmdExtra6 ); listExtra.append( cmdExtra7 ); } void ORecurranceWidget::hideExtras() { // hide the extra buttons... fraExtra->hide(); chkNoEnd->hide(); QListIterator<QToolButton> it( listExtra ); for ( ; *it; ++it ) { (*it)->hide(); (*it)->setOn( FALSE ); } } void ORecurranceWidget::showRepeatStuff() { cmdEnd->show(); chkNoEnd->show(); lblFreq->show(); lblEvery->show(); lblFreq->show(); spinFreq->show(); lblEnd->show(); lblRepeat->setText( tr("Every") ); } static int week( const QDate &start ) { // figure out the week... int stop = start.day(), sentinel = start.dayOfWeek(), dayOfWeek = QDate( start.year(), start.month(), 1 ).dayOfWeek(), week = 1, i; for ( i = 1; i < stop; i++ ) { if ( dayOfWeek++ == sentinel ) week++; if ( dayOfWeek > 7 ) dayOfWeek = 0; } return week; } static QString numberPlacing( int x ) { // I hope this works in other languages besides english... QString str = QString::number( x ); switch ( x % 10 ) { case 1: str += QWidget::tr( "st" ); break; case 2: str += QWidget::tr( "nd" ); break; case 3: str += QWidget::tr( "rd" ); break; default: str += QWidget::tr( "th" ); diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp index 622d40a..e537269 100644 --- a/libopie/pim/ocontactaccessbackend_vcard.cpp +++ b/libopie/pim/ocontactaccessbackend_vcard.cpp @@ -1,461 +1,470 @@ /* * VCard Backend for the OPIE-Contact Database. * * Copyright (C) 2000 Trolltech AS. All rights reserved. * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) * * ===================================================================== * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * ===================================================================== * ToDo: * * ===================================================================== * Version: $Id$ * ===================================================================== * History: * $Log$ + * Revision 1.8 2003/02/21 16:52:49 zecke + * -Remove old Todo classes they're deprecated and today I already using the + * new API + * -Guard against self assignment in OTodo + * -Add test apps for OPIM + * -Opiefied Event classes + * -Added TimeZone handling and pinning of TimeZones to OEvent + * -Adjust ORecur and the widget to better timezone behaviour + * * Revision 1.7 2003/02/16 22:25:46 zecke * 0000276 Fix for that bug.. or better temp workaround * A Preferred Number is HOME|VOICE * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test * triggers both * and the cell phone number overrides the other entries.. * * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the * number * * The right and final fix would be to reorder the if statement to make it * if else based and the less common thing put to the bottom * * OTodoAccessVcal fix the date for beaming * * Revision 1.6 2003/01/13 15:49:31 eilers * Fixing crash when businesscard.vcf is missing.. * * Revision 1.5 2002/12/07 13:26:22 eilers * Fixing bug in storing anniversary.. * * Revision 1.4 2002/11/13 14:14:51 eilers * Added sorted for Contacts.. * * Revision 1.3 2002/11/11 16:41:09 kergoth * no default arguments in implementation * * Revision 1.2 2002/11/10 15:41:53 eilers * Bugfixes.. * * Revision 1.1 2002/11/09 14:34:52 eilers * Added VCard Backend. * */ #include "ocontactaccessbackend_vcard.h" #include "../../library/backend/vobject_p.h" #include "../../library/backend/qfiledirect_p.h" #include <qpe/timeconversion.h> #include <qfile.h> OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename ): m_dirty( false ), m_file( filename ) { load(); } bool OContactAccessBackend_VCard::load () { m_map.clear(); m_dirty = false; VObject* obj = 0l; - if ( QFile( m_file ).exists() ){ + if ( QFile::exists(m_file) ){ obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); if ( !obj ) return false; }else{ qWarning("File \"%s\" not found !", m_file.latin1() ); return false; } while ( obj ) { OContact con = parseVObject( obj ); /* * if uid is 0 assign a new one * this at least happens on * Nokia6210 */ if ( con.uid() == 0 ){ con.setUid( 1 ); qWarning("assigned new uid %d",con.uid() ); } m_map.insert( con.uid(), con ); VObject *t = obj; obj = nextVObjectInList(obj); cleanVObject( t ); } return true; } bool OContactAccessBackend_VCard::reload() { return load(); } bool OContactAccessBackend_VCard::save() { if (!m_dirty ) return true; QFileDirect file( m_file ); if (!file.open(IO_WriteOnly ) ) return false; VObject *obj; obj = newVObject( VCCalProp ); addPropValue( obj, VCVersionProp, "1.0" ); VObject *vo; for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ vo = createVObject( *it ); writeVObject( file.directHandle() , vo ); cleanVObject( vo ); } cleanStrTbl(); m_dirty = false; return true; } void OContactAccessBackend_VCard::clear () { m_map.clear(); m_dirty = true; // ??? sure ? (se) } bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) { m_map.insert( newcontact.uid(), newcontact ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::remove ( int uid ) { m_map.remove( uid ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::replace ( const OContact &contact ) { m_map.replace( contact.uid(), contact ); m_dirty = true; return true; } OContact OContactAccessBackend_VCard::find ( int uid ) const { return m_map[uid]; } QArray<int> OContactAccessBackend_VCard::allRecords() const { QArray<int> ar( m_map.count() ); QMap<int, OContact>::ConstIterator it; int i = 0; for ( it = m_map.begin(); it != m_map.end(); ++it ) { ar[i] = it.key(); i++; } return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) { QArray<int> ar(0); return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const { QArray<int> ar(0); return ar; } const uint OContactAccessBackend_VCard::querySettings() { return 0; // No search possible } bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const { return false; // No search possible, therefore all settings invalid ;) } bool OContactAccessBackend_VCard::wasChangedExternally() { return false; // Don't expect concurrent access } // Not implemented QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int ) { QArray<int> ar(0); return ar; } // *** Private stuff *** OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) { OContact c; VObjectIterator it; initPropIterator( &it, obj ); while( moreIteration( &it ) ) { VObject *o = nextVObject( &it ); QCString name = vObjectName( o ); QCString value = vObjectStringZValue( o ); if ( name == VCNameProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); QString value = vObjectStringZValue( o ); if ( name == VCNamePrefixesProp ) c.setTitle( value ); else if ( name == VCNameSuffixesProp ) c.setSuffix( value ); else if ( name == VCFamilyNameProp ) c.setLastName( value ); else if ( name == VCGivenNameProp ) c.setFirstName( value ); else if ( name == VCAdditionalNamesProp ) c.setMiddleName( value ); } } else if ( name == VCAdrProp ) { bool work = TRUE; // default address is work address QString street; QString city; QString region; QString postal; QString country; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCHomeProp ) work = FALSE; else if ( name == VCWorkProp ) work = TRUE; else if ( name == VCStreetAddressProp ) street = value; else if ( name == VCCityProp ) city = value; else if ( name == VCRegionProp ) region = value; else if ( name == VCPostalCodeProp ) postal = value; else if ( name == VCCountryNameProp ) country = value; } if ( work ) { c.setBusinessStreet( street ); c.setBusinessCity( city ); c.setBusinessCountry( country ); c.setBusinessZip( postal ); c.setBusinessState( region ); } else { c.setHomeStreet( street ); c.setHomeCity( city ); c.setHomeCountry( country ); c.setHomeZip( postal ); c.setHomeState( region ); } } else if ( name == VCTelephoneProp ) { enum { HOME = 0x01, WORK = 0x02, VOICE = 0x04, CELL = 0x08, FAX = 0x10, PAGER = 0x20, UNKNOWN = 0x80 }; int type = 0; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) type |= HOME; else if ( name == VCWorkProp ) type |= WORK; else if ( name == VCVoiceProp ) type |= VOICE; else if ( name == VCCellularProp ) type |= CELL; else if ( name == VCFaxProp ) type |= FAX; else if ( name == VCPagerProp ) type |= PAGER; else if ( name == VCPreferredProp ) ; else type |= UNKNOWN; } if ( (type & UNKNOWN) != UNKNOWN ) { if ( ( type & (HOME|WORK) ) == 0 ) // default type |= HOME; if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default type |= VOICE; qWarning("value %s %d", value.data(), type ); if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) ) c.setHomePhone( value ); if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) c.setHomeFax( value ); if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) c.setHomeMobile( value ); if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) ) c.setBusinessPhone( value ); if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) c.setBusinessFax( value ); if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) c.setBusinessMobile( value ); if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) c.setBusinessPager( value ); } } else if ( name == VCEmailAddressProp ) { QString email = vObjectStringZValue( o ); bool valid = TRUE; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name != VCInternetProp && name != VCHomeProp && name != VCWorkProp && name != VCPreferredProp ) // ### preffered should map to default email valid = FALSE; } if ( valid ) { c.insertEmail( email ); } } else if ( name == VCURLProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) c.setHomeWebpage( value ); else if ( name == VCWorkProp ) c.setBusinessWebpage( value ); } } else if ( name == VCOrgProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCOrgNameProp ) c.setCompany( value ); else if ( name == VCOrgUnitProp ) c.setDepartment( value ); else if ( name == VCOrgUnit2Prop ) c.setOffice( value ); } } else if ( name == VCTitleProp ) { c.setJobTitle( value ); } else if ( name == "X-Qtopia-Profession" ) { c.setProfession( value ); } else if ( name == "X-Qtopia-Manager" ) { c.setManager( value ); } else if ( name == "X-Qtopia-Assistant" ) { c.setAssistant( value ); } else if ( name == "X-Qtopia-Spouse" ) { c.setSpouse( value ); } else if ( name == "X-Qtopia-Gender" ) { c.setGender( value ); } else if ( name == "X-Qtopia-Anniversary" ) { c.setAnniversary( convVCardDateToDate( value ) ); } else if ( name == "X-Qtopia-Nickname" ) { c.setNickname( value ); } else if ( name == "X-Qtopia-Children" ) { c.setChildren( value ); } else if ( name == VCBirthDateProp ) { // Reading Birthdate regarding RFC 2425 (5.8.4) c.setBirthday( convVCardDateToDate( value ) ); } #if 0 else { printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); printf(" subprop: %s = %s\n", name.data(), value.latin1() ); } } #endif } c.setFileAs(); return c; } VObject* OContactAccessBackend_VCard::createVObject( const OContact &c ) { VObject *vcard = newVObject( VCCardProp ); safeAddPropValue( vcard, VCVersionProp, "2.1" ); safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); // full name safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); // name properties VObject *name = safeAddProp( vcard, VCNameProp ); safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); safeAddPropValue( name, VCGivenNameProp, c.firstName() ); safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp new file mode 100644 index 0000000..71b9441 --- a/dev/null +++ b/libopie/pim/oevent.cpp @@ -0,0 +1,427 @@ +#include <qshared.h> + +#include <qpe/palmtopuidgen.h> +#include <qpe/categories.h> + +#include "orecur.h" +#include "opimresolver.h" +#include "opimnotifymanager.h" + +#include "oevent.h" + +namespace OCalendarHelper { + static int week( const QDate& date) { + // Calculates the week this date is in within that + // month. Equals the "row" is is in in the month view + int week = 1; + QDate tmp( date.year(), date.month(), 1 ); + if ( date.dayOfWeek() < tmp.dayOfWeek() ) + ++week; + + week += ( date.day() - 1 ) / 7; + + return week; + } + static int occurence( const QDate& date) { + // calculates the number of occurrances of this day of the + // week till the given date (e.g 3rd Wednesday of the month) + return ( date.day() - 1 ) / 7 + 1; + } + static int dayOfWeek( char day ) { + int dayOfWeek = 1; + char i = ORecur::MON; + while ( !( i & day ) && i <= ORecur::SUN ) { + i <<= 1; + ++dayOfWeek; + } + return dayOfWeek; + } + static int monthDiff( const QDate& first, const QDate& second ) { + return ( second.year() - first.year() ) * 12 + + second.month() - first.month(); + } +} + +struct OEvent::Data : public QShared { + Data() : QShared() { + recur = 0; + manager = 0; + isAllDay = false; + } + ~Data() { + delete manager; + delete recur; + } + QString description; + QString location; + OPimNotifyManager* manager; + ORecur* recur; + QString note; + QDateTime created; + QDateTime start; + QDateTime end; + bool isAllDay : 1; + QString timezone; +}; + +OEvent::OEvent( int uid ) + : OPimRecord( uid ) { + data = new Data; +} +OEvent::OEvent( const OEvent& ev) + : OPimRecord( ev ), data( ev.data ) +{ + data->ref(); +} +OEvent::~OEvent() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +OEvent& OEvent::operator=( const OEvent& ev) { + if ( *this == ev ) return *this; + + OPimRecord::operator=( ev ); + ev.data->ref(); + deref(); + data = ev.data; + + + return *this; +} +QString OEvent::description()const { + return data->description; +} +void OEvent::setDescription( const QString& description ) { + changeOrModify(); + data->description = description; +} +void OEvent::setLocation( const QString& loc ) { + changeOrModify(); + data->location = loc; +} +QString OEvent::location()const { + return data->location; +} +OPimNotifyManager &OEvent::notifiers() { + // I hope we can skip the changeOrModify here + // the notifier should take care of it + // and OPimNotify is shared too + if (!data->manager ) + data->manager = new OPimNotifyManager; + + return *data->manager; +} +bool OEvent::hasNotifiers()const { + return ( data->manager); +} +ORecur OEvent::recurrence()const { + if (!data->recur) + data->recur = new ORecur; + + return *data->recur; +} +void OEvent::setRecurrence( const ORecur& rec) { + changeOrModify(); + if (data->recur ) + (*data->recur) = rec; + else + data->recur = new ORecur( rec ); +} +bool OEvent::hasRecurrence()const { + return data->recur; +} +QString OEvent::note()const { + return data->note; +} +void OEvent::setNote( const QString& note ) { + changeOrModify(); + data->note = note; +} +QDateTime OEvent::createdDateTime()const { + return data->created; +} +void OEvent::setCreatedDateTime( const QDateTime& time ) { + changeOrModify(); + data->created = time; +} +QDateTime OEvent::startDateTime()const { + if ( data->isAllDay ) + return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); + return data->start; +} +QDateTime OEvent::startDateTimeInZone()const { + /* if no timezone, or all day event or if the current and this timeZone match... */ + if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); + + OTimeZone zone(data->timezone ); + return zone.toDateTime( data->start, OTimeZone::current() ); +} +void OEvent::setStartDateTime( const QDateTime& dt ) { + changeOrModify(); + data->start = dt; +} +QDateTime OEvent::endDateTime()const { + /* + * if all Day event the end time needs + * to be on the same day as the start + */ + if ( data->isAllDay ) + return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); + return data->end; +} +QDateTime OEvent::endDateTimeInZone()const { + /* if no timezone, or all day event or if the current and this timeZone match... */ + if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); + + OTimeZone zone(data->timezone ); + return zone.toDateTime( data->end, OTimeZone::current() ); +} +void OEvent::setEndDateTime( const QDateTime& dt ) { + changeOrModify(); + data->end = dt; +} +bool OEvent::isMultipleDay()const { + return data->end.date().day() - data->start.date().day(); +} +bool OEvent::isAllDay()const { + return data->isAllDay; +} +void OEvent::setTimeZone( const QString& tz ) { + changeOrModify(); + data->timezone = tz; +} +QString OEvent::timeZone()const { + return data->timezone; +} +bool OEvent::match( const QRegExp& )const { + // FIXME + return false; +} +QString OEvent::toRichText()const { + // FIXME + return "OEvent test"; +} +QString OEvent::toShortText()const { + return "OEvent shotText"; +} +QString OEvent::type()const { + return QString::fromLatin1("OEvent"); +} +QString OEvent::recordField( int /*id */ )const { + return QString::null; +} +int OEvent::rtti() { + return OPimResolver::DateBook; +} +bool OEvent::loadFromStream( QDataStream& ) { + return true; +} +bool OEvent::saveToStream( QDataStream& )const { + return true; +} +void OEvent::changeOrModify() { + if ( data->count != 1 ) { + data->deref(); + Data* d2 = new Data; + d2->description = data->description; + d2->location = data->location; + d2->manager = data->manager; + d2->recur = data->recur; + d2->note = data->note; + d2->created = data->created; + d2->start = data->start; + d2->end = data->end; + d2->isAllDay = data->isAllDay; + d2->timezone = data->timezone; + + data = d2; + } +} +void OEvent::deref() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +// FIXME +QMap<int, QString> OEvent::toMap()const { + return QMap<int, QString>(); +} +QMap<QString, QString> OEvent::toExtraMap()const { + return QMap<QString, QString>(); +} + + +struct OEffectiveEvent::Data : public QShared { + Data() : QShared() { + } + OEvent event; + QDate date; + QTime start, end; + QDate startDate, endDate; + bool dates : 1; +}; + +OEffectiveEvent::OEffectiveEvent() { + data = new Data; + data->date = QDate::currentDate(); + data->start = data->end = QTime::currentTime(); + data->dates = false; +} +OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, + Position pos ) { + data = new Data; + data->event = ev; + data->date = startDate; + if ( pos & Start ) + data->start = ev.startDateTime().time(); + else + data->start = QTime( 0, 0, 0 ); + + if ( pos & End ) + data->end = ev.endDateTime().time(); + else + data->end = QTime( 23, 59, 59 ); + + data->dates = false; +} +OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { + data = ev.data; + data->ref(); +} +OEffectiveEvent::~OEffectiveEvent() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { + if ( *this == ev ) return *this; + + ev.data->ref(); + deref(); + data = ev.data; + + return *this; +} + +void OEffectiveEvent::setStartTime( const QTime& ti) { + changeOrModify(); + data->start = ti; +} +void OEffectiveEvent::setEndTime( const QTime& en) { + changeOrModify(); + data->end = en; +} +void OEffectiveEvent::setEvent( const OEvent& ev) { + changeOrModify(); + data->event = ev; +} +void OEffectiveEvent::setDate( const QDate& da) { + changeOrModify(); + data->date = da; +} +void OEffectiveEvent::setEffectiveDates( const QDate& from, + const QDate& to ) { + if (!from.isValid() ) { + data->dates = false; + return; + } + + data->startDate = from; + data->endDate = to; +} +QString OEffectiveEvent::description()const { + return data->event.description(); +} +QString OEffectiveEvent::location()const { + return data->event.location(); +} +QString OEffectiveEvent::note()const { + return data->event.note(); +} +OEvent OEffectiveEvent::event()const { + return data->event; +} +QTime OEffectiveEvent::startTime()const { + return data->start; +} +QTime OEffectiveEvent::endTime()const { + return data->end; +} +QDate OEffectiveEvent::date()const { + return data->date; +} +int OEffectiveEvent::length()const { + return (data->end.hour() * 60 - data->start.hour() * 60) + + QABS(data->start.minute() - data->end.minute() ); +} +int OEffectiveEvent::size()const { + return ( data->end.hour() - data->start.hour() ) * 3600 + + (data->end.minute() - data->start.minute() * 60 + + data->end.second() - data->start.second() ); +} +QDate OEffectiveEvent::startDate()const { + if ( data->dates ) + return data->startDate; + else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer + return data->date; + else + return data->event.startDateTime().date(); +} +QDate OEffectiveEvent::endDate()const { + if ( data->dates ) + return data->endDate; + else if ( data->event.hasRecurrence() ) + return data->date; + else + return data->event.endDateTime().date(); +} +void OEffectiveEvent::deref() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +void OEffectiveEvent::changeOrModify() { + if ( data->count != 1 ) { + data->deref(); + Data* d2 = new Data; + d2->event = data->event; + d2->date = data->date; + d2->start = data->start; + d2->end = data->end; + d2->startDate = data->startDate; + d2->endDate = data->endDate; + d2->dates = data->dates; + data = d2; + } +} +bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ + if ( data->date < e.date() ) + return TRUE; + if ( data->date == e.date() ) + return ( startTime() < e.startTime() ); + else + return FALSE; +} +bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ + return (data->date <= e.date() ); +} +bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { + return ( date() == e.date() + && startTime() == e.startTime() + && endTime()== e.endTime() + && event() == e.event() ); +} +bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { + return !(*this == e ); +} +bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { + return !(*this <= e ); +} +bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { + return !(*this < e); +} diff --git a/libopie/pim/oevent.h b/libopie/pim/oevent.h new file mode 100644 index 0000000..4489be7 --- a/dev/null +++ b/libopie/pim/oevent.h @@ -0,0 +1,198 @@ +// CONTAINS GPLed code of TT + +#ifndef OPIE_PIM_EVENT_H +#define OPIE_PIM_EVENT_H + +#include <qstring.h> +#include <qdatetime.h> +#include <qvaluelist.h> + +#include <qpe/recordfields.h> +#include <qpe/palmtopuidgen.h> + +#include "otimezone.h" +#include "opimrecord.h" + +namespace OCalendarHelper { + /** calculate the week number of the date */ + static int week( const QDate& ); + /** calculate the occurence of week days since the start of the month */ + static int ocurrence( const QDate& ); + + // returns the dayOfWeek for the *first* day it finds (ignores + // any further days!). Returns 1 (Monday) if there isn't any day found + static int dayOfWeek( char day ); + + /** returns the diff of month */ + static int monthDiff( const QDate& first, const QDate& second ); + +} + +class OPimNotifyManager; +class ORecur; +class OEvent : public OPimRecord { +public: + typedef QValueList<OEvent> ValueList; + enum RecordFields { + Uid = Qtopia::UID_ID, + Category = Qtopia::CATEGORY_ID, + Description, + Location, + Alarm, + Reminder, + Recurrence, + Note, + Created, + StartDate, + EndDate, + AllDay, + TimeZone + }; + + OEvent(int uid = 0); + OEvent( const OEvent& ); + ~OEvent(); + OEvent &operator=( const OEvent& ); + + QString description()const; + void setDescription( const QString& description ); + + QString location()const; + void setLocation( const QString& loc ); + + bool hasNotifiers()const; + OPimNotifyManager ¬ifiers(); + + ORecur recurrence()const; + void setRecurrence( const ORecur& ); + bool hasRecurrence()const; + + QString note()const; + void setNote( const QString& note ); + + + QDateTime createdDateTime()const; + void setCreatedDateTime( const QDateTime& dt); + + /** set the date to dt. dt is the QDateTime in localtime */ + void setStartDateTime( const QDateTime& ); + /** returns the datetime in the local timeZone */ + QDateTime startDateTime()const; + + /** returns the start datetime in the current zone */ + QDateTime startDateTimeInZone()const; + + /** in current timezone */ + void setEndDateTime( const QDateTime& ); + /** in current timezone */ + QDateTime endDateTime()const; + QDateTime endDateTimeInZone()const; + + bool isMultipleDay()const; + bool isAllDay()const; + void setAllDay( bool isAllDay ); + + /* pin this event to a timezone! FIXME */ + void setTimeZone( const QString& timeZone ); + QString timeZone()const; + + + bool match( const QRegExp& )const; + + + + + /* needed reimp */ + QString toRichText()const; + QString toShortText()const; + QString type()const; + + QMap<int, QString> toMap()const; + QMap<QString, QString> toExtraMap()const; + QString recordField(int )const; + + static int rtti(); + + bool loadFromStream( QDataStream& ); + bool saveToStream( QDataStream& )const; + +/* bool operator==( const OEvent& ); + bool operator!=( const OEvent& ); + bool operator<( const OEvent& ); + bool operator<=( const OEvent& ); + bool operator>( const OEvent& ); + bool operator>=(const OEvent& ); +*/ +private: + inline void changeOrModify(); + void deref(); + struct Data; + Data* data; + class Private; + Private* priv; + +}; + +/** + * AN Event can span through multiple days. We split up a multiday eve + */ + +class OEffectiveEvent { +public: + QValueList<OEffectiveEvent> ValueList; + enum Position { MidWay, Start, End, StartEnd }; + // If we calculate the effective event of a multi-day event + // we have to figure out whether we are at the first day, + // at the end, or anywhere else ("middle"). This is important + // for the start/end times (00:00/23:59) + // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- + // day event + // Start: start time -> 23:59 + // End: 00:00 -> end time + // Start | End == StartEnd: for single-day events (default) + // here we draw start time -> end time + OEffectiveEvent(); + OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); + OEffectiveEvent( const OEffectiveEvent& ); + OEffectiveEvent &operator=(const OEffectiveEvent& ); + ~OEffectiveEvent(); + + void setStartTime( const QTime& ); + void setEndTime( const QTime& ); + void setEvent( const OEvent& ); + void setDate( const QDate& ); + + void setEffectiveDates( const QDate& from, const QDate& to ); + + QString description()const; + QString location()const; + QString note()const; + OEvent event()const; + QTime startTime()const; + QTime endTime()const; + QDate date()const; + + /* return the length in hours */ + int length()const; + int size()const; + + QDate startDate()const; + QDate endDate()const; + + bool operator<( const OEffectiveEvent &e ) const; + bool operator<=( const OEffectiveEvent &e ) const; + bool operator==( const OEffectiveEvent &e ) const; + bool operator!=( const OEffectiveEvent &e ) const; + bool operator>( const OEffectiveEvent &e ) const; + bool operator>= ( const OEffectiveEvent &e ) const; + +private: + void deref(); + inline void changeOrModify(); + class Private; + Private* priv; + struct Data; + Data* data; + +}; +#endif diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp index daf3506..e6a4787 100644 --- a/libopie/pim/orecur.cpp +++ b/libopie/pim/orecur.cpp @@ -1,451 +1,446 @@ #include <qshared.h> #include <qtopia/timeconversion.h> #include "orecur.h" struct ORecur::Data : public QShared { Data() : QShared() { type = ORecur::NoRepeat; freq = -1; days = 0; pos = 0; - create = -1; + create = QDateTime::currentDateTime(); hasEnd = FALSE; - end = 0; + end = QDate::currentDate(); } char days; // Q_UINT8 for 8 seven days;) ORecur::RepeatType type; int freq; int pos; bool hasEnd : 1; - time_t end; - time_t create; + QDate end; + QDateTime create; int rep; QString app; ExceptionList list; QDate start; }; ORecur::ORecur() { data = new Data; } ORecur::ORecur( const ORecur& rec) : data( rec.data ) { data->ref(); } ORecur::~ORecur() { if ( data->deref() ) { delete data; data = 0l; } } void ORecur::deref() { if ( data->deref() ) { delete data; data = 0l; } } bool ORecur::operator==( const ORecur& )const { return false; } ORecur &ORecur::operator=( const ORecur& re) { + if ( *this == re ) return *this; + re.data->ref(); deref(); data = re.data; return *this; } bool ORecur::doesRecur()const { return !( type() == NoRepeat ); } /* * we try to be smart here * */ bool ORecur::doesRecur( const QDate& date ) { /* the day before the recurrance */ QDate da = date.addDays(-1); QDate recur; if (!nextOcurrence( da, recur ) ) return false; return (recur == date); } // FIXME unuglify! // GPL from Datebookdb.cpp // FIXME exception list! bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { // easy checks, first are we too far in the future or too far in the past? QDate tmpDate; int freq = frequency(); int diff, diff2, a; int iday, imonth, iyear; int dayOfWeek = 0; int firstOfWeek = 0; int weekOfMonth; if (hasEndDate() && endDate() < from) return FALSE; if (start() >= from) { next = start(); return TRUE; } switch ( type() ) { case Weekly: /* weekly is just daily by 7 */ /* first convert the repeatPattern.Days() mask to the next day of week valid after from */ dayOfWeek = from.dayOfWeek(); dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ /* this is done in case freq > 1 and from in week not for this round */ // firstOfWeek = 0; this is already done at decl. while(!((1 << firstOfWeek) & days() )) firstOfWeek++; /* there is at least one 'day', or there would be no event */ while(!((1 << (dayOfWeek % 7)) & days() )) dayOfWeek++; dayOfWeek = dayOfWeek % 7; /* the actual day of week */ dayOfWeek -= start().dayOfWeek() -1; firstOfWeek = firstOfWeek % 7; /* the actual first of week */ firstOfWeek -= start().dayOfWeek() -1; // dayOfWeek may be negitive now // day of week is number of days to add to start day freq *= 7; // FALL-THROUGH !!!!! case Daily: // the add is for the possible fall through from weekly */ if(start().addDays(dayOfWeek) > from) { /* first week exception */ next = QDate(start().addDays(dayOfWeek) ); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* if from is middle of a non-week */ diff = start().addDays(dayOfWeek).daysTo(from) % freq; diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; if(diff != 0) diff = freq - diff; if(diff2 != 0) diff2 = freq - diff2; diff = QMIN(diff, diff2); next = QDate(from.addDays(diff)); if ( (next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case MonthlyDay: iday = from.day(); iyear = from.year(); imonth = from.month(); /* find equivelent day of month for this month */ dayOfWeek = start().dayOfWeek(); weekOfMonth = (start().day() - 1) / 7; /* work out when the next valid month is */ a = from.year() - start().year(); a *= 12; a = a + (imonth - start().month()); /* a is e.start()monthsFrom(from); */ if(a % freq) { a = freq - (a % freq); imonth = from.month() + a; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } } /* imonth is now the first month after or on from that matches the frequency given */ /* find for this month */ tmpDate = QDate( iyear, imonth, 1 ); iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; while (iday > tmpDate.daysInMonth()) { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } tmpDate = QDate( iyear, imonth, 1 ); /* these loops could go for a while, check end case now */ if ((tmpDate > endDate()) && hasEndDate() ) return FALSE; iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; } tmpDate = QDate(iyear, imonth, iday); if (tmpDate >= from) { next = tmpDate; if ((next > endDate() ) && hasEndDate() ) return FALSE; return TRUE; } /* need to find the next iteration */ do { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } tmpDate = QDate( iyear, imonth, 1 ); /* these loops could go for a while, check end case now */ if ((tmpDate > endDate()) && hasEndDate() ) return FALSE; iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; } while (iday > tmpDate.daysInMonth()); tmpDate = QDate(iyear, imonth, iday); next = tmpDate; if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case MonthlyDate: iday = start().day(); iyear = from.year(); imonth = from.month(); a = from.year() - start().year(); a *= 12; a = a + (imonth - start().month()); /* a is e.start()monthsFrom(from); */ if(a % freq) { a = freq - (a % freq); imonth = from.month() + a; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } } /* imonth is now the first month after or on from that matches the frequencey given */ /* this could go for a while, worse case, 4*12 iterations, probably */ while(!QDate::isValid(iyear, imonth, iday) ) { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } /* these loops could go for a while, check end case now */ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) return FALSE; } if(QDate(iyear, imonth, iday) >= from) { /* done */ next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* ok, need to cycle */ imonth += freq; imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; while(!QDate::isValid(iyear, imonth, iday) ) { imonth += freq; imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) return FALSE; } next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case Yearly: iday = start().day(); imonth = start().month(); iyear = from.year(); // after all, we want to start in this year diff = 1; if(imonth == 2 && iday > 28) { /* leap year, and it counts, calculate actual frequency */ if(freq % 4) if (freq % 2) freq = freq * 4; else freq = freq * 2; /* else divides by 4 already, leave freq alone */ diff = 4; } a = from.year() - start().year(); if(a % freq) { a = freq - (a % freq); iyear = iyear + a; } /* under the assumption we won't hit one of the special not-leap years twice */ if(!QDate::isValid(iyear, imonth, iday)) { /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ iyear += freq; } if(QDate(iyear, imonth, iday) >= from) { next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* iyear == from.year(), need to advance again */ iyear += freq; /* under the assumption we won't hit one of the special not-leap years twice */ if(!QDate::isValid(iyear, imonth, iday)) { /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ iyear += freq; } next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; default: return FALSE; } } ORecur::RepeatType ORecur::type()const{ return data->type; } int ORecur::frequency()const { return data->freq; } int ORecur::position()const { return data->pos; } char ORecur::days() const{ return data->days; } bool ORecur::hasEndDate()const { return data->hasEnd; } QDate ORecur::endDate()const { - return TimeConversion::fromUTC( data->end ).date(); + return data->end; } QDate ORecur::start()const{ return data->start; } -time_t ORecur::endDateUTC()const { - return data->end; -} -time_t ORecur::createTime()const { +QDateTime ORecur::createdDateTime()const { return data->create; } int ORecur::repetition()const { return data->rep; } QString ORecur::service()const { return data->app; } ORecur::ExceptionList& ORecur::exceptions() { return data->list; } void ORecur::setType( const RepeatType& z) { checkOrModify(); data->type = z; } void ORecur::setFrequency( int freq ) { checkOrModify(); data->freq = freq; } void ORecur::setPosition( int pos ) { checkOrModify(); data->pos = pos; } void ORecur::setDays( char c ) { checkOrModify(); data->days = c; } void ORecur::setEndDate( const QDate& dt) { checkOrModify(); - data->end = TimeConversion::toUTC( dt ); -} -void ORecur::setEndDateUTC( time_t t) { - checkOrModify(); - data->end = t; + data->end = dt; } -void ORecur::setCreateTime( time_t t) { +void ORecur::setCreatedDateTime( const QDateTime& t) { checkOrModify(); data->create = t; } void ORecur::setHasEndDate( bool b) { checkOrModify(); data->hasEnd = b; } void ORecur::setRepitition( int rep ) { checkOrModify(); data->rep = rep; } void ORecur::setService( const QString& app ) { checkOrModify(); data->app = app; } void ORecur::setStart( const QDate& dt ) { checkOrModify(); data->start = dt; } void ORecur::checkOrModify() { if ( data->count != 1 ) { data->deref(); Data* d2 = new Data; d2->days = data->days; d2->type = data->type; d2->freq = data->freq; d2->pos = data->pos; d2->hasEnd = data->hasEnd; d2->end = data->end; d2->create = data->create; d2->rep = data->rep; d2->app = data->app; d2->list = data->list; d2->start = data->start; data = d2; } } diff --git a/libopie/pim/orecur.h b/libopie/pim/orecur.h index 8713d97..1e0014b 100644 --- a/libopie/pim/orecur.h +++ b/libopie/pim/orecur.h @@ -1,83 +1,87 @@ /* * GPL from TT */ #ifndef OPIE_RECUR_H #define OPIE_RECUR_H #include <sys/types.h> #include <qdatetime.h> #include <qvaluelist.h> class ORecur { public: typedef QValueList<QDate> ExceptionList; enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, MonthlyDate, Yearly }; enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, FRI = 0x10, SAT = 0x20, SUN = 0x40 }; ORecur(); ORecur( const ORecur& ); ~ORecur(); ORecur &operator=( const ORecur& ); bool operator==(const ORecur& )const; bool doesRecur()const; /* if it recurrs on that day */ bool doesRecur( const QDate& ); RepeatType type()const; int frequency()const; int position()const; char days()const; bool hasEndDate()const; QDate start()const; QDate endDate()const; - time_t endDateUTC()const; - time_t createTime()const; + QDateTime createdDateTime()const; + /** + * starting on monday=0, sunday=6 + * for convience + */ + bool repeatOnWeekDay( int day )const; /** * FromWhereToStart is not included!!! */ bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); + /** * The module this ORecur belongs to */ QString service()const; /* * reference to the exception list */ ExceptionList &exceptions(); /** * the current repetition */ int repetition()const; void setType( const RepeatType& ); void setFrequency( int freq ); void setPosition( int pos ); void setDays( char c); void setEndDate( const QDate& dt ); void setStart( const QDate& dt ); - void setEndDateUTC( time_t ); - void setCreateTime( time_t ); + void setCreatedDateTime( const QDateTime& ); void setHasEndDate( bool b ); void setRepitition(int ); void setService( const QString& ser ); private: void deref(); inline void checkOrModify(); class Data; Data* data; class ORecurPrivate; ORecurPrivate *d; }; #endif diff --git a/libopie/pim/otimezone.cpp b/libopie/pim/otimezone.cpp new file mode 100644 index 0000000..b2bd3aa --- a/dev/null +++ b/libopie/pim/otimezone.cpp @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <sys/types.h> + +#include "otimezone.h" + +namespace { + + QDateTime utcTime( time_t t) { + tm* broken = ::gmtime( &t ); + QDateTime ret; + ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) ); + ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) ); + return ret; + } + QDateTime utcTime( time_t t, const QString& zone) { + QCString org = ::getenv( "TZ" ); + ::setenv( "TZ", zone.latin1(), true ); + ::tzset(); + + tm* broken = ::localtime( &t ); + ::setenv( "TZ", org, true ); + + QDateTime ret; + ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) ); + ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) ); + + return ret; + } + time_t to_Time_t( const QDateTime& utc, const QString& str ) { + QDate d = utc.date(); + QTime t = utc.time(); + + tm broken; + broken.tm_year = d.year() - 1900; + broken.tm_mon = d.month() - 1; + broken.tm_mday = d.day(); + broken.tm_hour = t.hour(); + broken.tm_min = t.minute(); + broken.tm_sec = t.second(); + + QCString org = ::getenv( "TZ" ); + ::setenv( "TZ", str.latin1(), true ); + ::tzset(); + + time_t ti = ::mktime( &broken ); + ::setenv( "TZ", org, true ); + + return ti; + } +} +OTimeZone::OTimeZone( const ZoneName& zone ) + : m_name(zone) { +} +OTimeZone::~OTimeZone() { +} + +bool OTimeZone::isValid()const { + return !m_name.isEmpty(); +} + +/* + * we will get the current timezone + * and ask it to convert to the timezone date + */ +QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) { + return OTimeZone::current().toDateTime( dt, *this ); +} +QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) { + return OTimeZone::utc().toDateTime( dt, *this ); +} +QDateTime OTimeZone::fromUTCDateTime( time_t t) { + return utcTime( t ); +} +QDateTime OTimeZone::toDateTime( time_t t) { + return utcTime( t, m_name ); +} +/* + * convert dt to utc using zone.m_name + * convert utc -> timeZoneDT using this->m_name + */ +QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) { + time_t utc = to_Time_t( dt, zone.m_name ); + qWarning("%d %s", utc, zone.m_name.latin1() ); + return utcTime( utc, m_name ); +} +time_t OTimeZone::fromDateTime( const QDateTime& time ) { + return to_Time_t( time, m_name ); +} +time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) { + return to_Time_t( time, "UTC" ); +} +OTimeZone OTimeZone::current() { + QCString str = ::getenv("TZ"); + OTimeZone zone( str ); + return zone; +} +OTimeZone OTimeZone::utc() { + return OTimeZone("UTC"); +} +QString OTimeZone::timeZone()const { + return m_name; +} diff --git a/libopie/pim/otimezone.h b/libopie/pim/otimezone.h new file mode 100644 index 0000000..bb08349 --- a/dev/null +++ b/libopie/pim/otimezone.h @@ -0,0 +1,71 @@ +#ifndef OPIE_TIME_ZONE_H +#define OPIE_TIME_ZONE_H + +#include <time.h> +#include <qdatetime.h> + +/** + * A very primitive class to convert time + * from one timezone to another + * and to localtime + * and time_t + */ +class OTimeZone { + public: + typedef QString ZoneName; + OTimeZone( const ZoneName& = ZoneName::null ); + virtual ~OTimeZone(); // just in case. + + bool isValid()const; + + /** + * converts the QDateTime to a DateTime + * in the local timezone + * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h + * and the current timezone is Europe/London the returned + * time will be 11h. + */ + QDateTime toLocalDateTime( const QDateTime& dt ); + + /** + * converts the QDateTime to UTC time + */ + QDateTime toUTCDateTime( const QDateTime& dt ); + + /** + * reads the time_t into a QDateTime using UTC as timezone! + */ + QDateTime fromUTCDateTime( time_t ); + + /** + * converts the time_t to the time in the timezone + */ + QDateTime toDateTime( time_t ); + + /** + * converts the QDateTime from one timezone to this timeZone + */ + QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone ); + + /** + * converts the date time into a time_t. It takes the timezone into account + */ + time_t fromDateTime( const QDateTime& ); + + /** + * converts the datetime with timezone UTC + */ + time_t fromUTCDateTime( const QDateTime& ); + + static OTimeZone current(); + static OTimeZone utc(); + + QString timeZone()const; + private: + ZoneName m_name; + class Private; + Private* d; +}; + + +#endif diff --git a/libopie/pim/otodo.cpp b/libopie/pim/otodo.cpp index b4d4aa9..049359e 100644 --- a/libopie/pim/otodo.cpp +++ b/libopie/pim/otodo.cpp @@ -1,422 +1,424 @@ #include <qobject.h> #include <qshared.h> #include <qpe/palmtopuidgen.h> #include <qpe/stringutil.h> #include <qpe/palmtoprecord.h> #include <qpe/stringutil.h> #include <qpe/categories.h> #include <qpe/categoryselect.h> #include "opimstate.h" #include "orecur.h" #include "opimmaintainer.h" #include "opimnotifymanager.h" #include "opimresolver.h" #include "otodo.h" struct OTodo::OTodoData : public QShared { OTodoData() : QShared() { }; QDate date; bool isCompleted:1; bool hasDate:1; int priority; QString desc; QString sum; QMap<QString, QString> extra; ushort prog; OPimState state; ORecur recur; OPimMaintainer maintainer; QDate start; QDate completed; OPimNotifyManager notifiers; }; OTodo::OTodo(const OTodo &event ) : OPimRecord( event ), data( event.data ) { data->ref(); // qWarning("ref up"); } OTodo::~OTodo() { // qWarning("~OTodo " ); if ( data->deref() ) { // qWarning("OTodo::dereffing"); delete data; data = 0l; } } OTodo::OTodo(bool completed, int priority, const QArray<int> &category, const QString& summary, const QString &description, ushort progress, bool hasDate, QDate date, int uid ) : OPimRecord( uid ) { // qWarning("OTodoData " + summary); setCategories( category ); data = new OTodoData; data->date = date; data->isCompleted = completed; data->hasDate = hasDate; data->priority = priority; data->sum = summary; data->prog = progress; data->desc = Qtopia::simplifyMultiLineSpace(description ); } OTodo::OTodo(bool completed, int priority, const QStringList &category, const QString& summary, const QString &description, ushort progress, bool hasDate, QDate date, int uid ) : OPimRecord( uid ) { // qWarning("OTodoData" + summary); setCategories( idsFromString( category.join(";") ) ); data = new OTodoData; data->date = date; data->isCompleted = completed; data->hasDate = hasDate; data->priority = priority; data->sum = summary; data->prog = progress; data->desc = Qtopia::simplifyMultiLineSpace(description ); } bool OTodo::match( const QRegExp ®Exp )const { if( QString::number( data->priority ).find( regExp ) != -1 ){ return true; }else if( data->hasDate && data->date.toString().find( regExp) != -1 ){ return true; }else if(data->desc.find( regExp ) != -1 ){ return true; }else if(data->sum.find( regExp ) != -1 ) { return true; } return false; } bool OTodo::isCompleted() const { return data->isCompleted; } bool OTodo::hasDueDate() const { return data->hasDate; } bool OTodo::hasStartDate()const { return data->start.isValid(); } bool OTodo::hasCompletedDate()const { return data->completed.isValid(); } int OTodo::priority()const { return data->priority; } QString OTodo::summary() const { return data->sum; } ushort OTodo::progress() const { return data->prog; } QDate OTodo::dueDate()const { return data->date; } QDate OTodo::startDate()const { return data->start; } QDate OTodo::completedDate()const { return data->completed; } QString OTodo::description()const { return data->desc; } OPimState OTodo::state()const { return data->state; } ORecur OTodo::recurrence()const { return data->recur; } OPimMaintainer OTodo::maintainer()const { return data->maintainer; } void OTodo::setCompleted( bool completed ) { changeOrModify(); data->isCompleted = completed; } void OTodo::setHasDueDate( bool hasDate ) { changeOrModify(); data->hasDate = hasDate; } void OTodo::setDescription(const QString &desc ) { // qWarning( "desc " + desc ); changeOrModify(); data->desc = Qtopia::simplifyMultiLineSpace(desc ); } void OTodo::setSummary( const QString& sum ) { changeOrModify(); data->sum = sum; } void OTodo::setPriority(int prio ) { changeOrModify(); data->priority = prio; } void OTodo::setDueDate( const QDate& date ) { changeOrModify(); data->date = date; } void OTodo::setStartDate( const QDate& date ) { changeOrModify(); data->start = date; } void OTodo::setCompletedDate( const QDate& date ) { changeOrModify(); data->completed = date; } void OTodo::setState( const OPimState& state ) { changeOrModify(); data->state = state; } void OTodo::setRecurrence( const ORecur& rec) { changeOrModify(); data->recur = rec; } void OTodo::setMaintainer( const OPimMaintainer& pim ) { changeOrModify(); data->maintainer = pim; } bool OTodo::isOverdue( ) { if( data->hasDate && !data->isCompleted) return QDate::currentDate() > data->date; return false; } void OTodo::setProgress(ushort progress ) { changeOrModify(); data->prog = progress; } QString OTodo::toShortText() const { return summary(); } /*! Returns a richt text string */ QString OTodo::toRichText() const { QString text; QStringList catlist; // Description of the todo if ( !summary().isEmpty() ) { text += "<b>" + QObject::tr( "Summary:") + "</b><br>"; text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; } if( !description().isEmpty() ){ text += "<b>" + QObject::tr( "Description:" ) + "</b><br>"; text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) ; } text += "<br><br><br>"; text += "<b>" + QObject::tr( "Priority:") +" </b>" + QString::number( priority() ) + " <br>"; text += "<b>" + QObject::tr( "Progress:") + " </b>" + QString::number( progress() ) + " %<br>"; if (hasDueDate() ){ text += "<b>" + QObject::tr( "Deadline:") + " </b>"; text += dueDate().toString(); text += "<br>"; } text += "<b>" + QObject::tr( "Category:") + "</b> "; text += categoryNames( "Todo List" ).join(", "); text += "<br>"; return text; } OPimNotifyManager& OTodo::notifiers() { return data->notifiers; } bool OTodo::operator<( const OTodo &toDoEvent )const{ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() < toDoEvent.priority(); }else{ return dueDate() < toDoEvent.dueDate(); } } return false; } bool OTodo::operator<=(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return true; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() <= toDoEvent.priority(); }else{ return dueDate() <= toDoEvent.dueDate(); } } return true; } bool OTodo::operator>(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() > toDoEvent.priority(); }else{ return dueDate() > toDoEvent.dueDate(); } } return false; } bool OTodo::operator>=(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() > toDoEvent.priority(); }else{ return dueDate() > toDoEvent.dueDate(); } } return true; } bool OTodo::operator==(const OTodo &toDoEvent )const { if ( data->priority != toDoEvent.data->priority ) return false; if ( data->priority != toDoEvent.data->prog ) return false; if ( data->isCompleted != toDoEvent.data->isCompleted ) return false; if ( data->hasDate != toDoEvent.data->hasDate ) return false; if ( data->date != toDoEvent.data->date ) return false; if ( data->sum != toDoEvent.data->sum ) return false; if ( data->desc != toDoEvent.data->desc ) return false; if ( data->maintainer != toDoEvent.data->maintainer ) return false; return OPimRecord::operator==( toDoEvent ); } void OTodo::deref() { // qWarning("deref in ToDoEvent"); if ( data->deref() ) { // qWarning("deleting"); delete data; data= 0; } } OTodo &OTodo::operator=(const OTodo &item ) { + if ( *this == item ) return *this; + OPimRecord::operator=( item ); //qWarning("operator= ref "); item.data->ref(); deref(); data = item.data; return *this; } QMap<int, QString> OTodo::toMap() const { QMap<int, QString> map; map.insert( Uid, QString::number( uid() ) ); map.insert( Category, idsToString( categories() ) ); map.insert( HasDate, QString::number( data->hasDate ) ); map.insert( Completed, QString::number( data->isCompleted ) ); map.insert( Description, data->desc ); map.insert( Summary, data->sum ); map.insert( Priority, QString::number( data->priority ) ); map.insert( DateDay, QString::number( data->date.day() ) ); map.insert( DateMonth, QString::number( data->date.month() ) ); map.insert( DateYear, QString::number( data->date.year() ) ); map.insert( Progress, QString::number( data->prog ) ); // map.insert( CrossReference, crossToString() ); /* FIXME!!! map.insert( State, ); map.insert( Recurrence, ); map.insert( Reminders, ); map. */ return map; } QMap<QString, QString> OTodo::toExtraMap()const { return data->extra; } /** * change or modify looks at the ref count and either * creates a new QShared Object or it can modify it * right in place */ void OTodo::changeOrModify() { if ( data->count != 1 ) { qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } // WATCHOUT /* * if you add something to the Data struct * be sure to copy it here */ void OTodo::copy( OTodoData* src, OTodoData* dest ) { dest->date = src->date; dest->isCompleted = src->isCompleted; dest->hasDate = src->hasDate; dest->priority = src->priority; dest->desc = src->desc; dest->sum = src->sum; dest->extra = src->extra; dest->prog = src->prog; dest->state = src->state; dest->recur = src->recur; dest->maintainer = src->maintainer; dest->start = src->start; dest->completed = src->completed; dest->notifiers = src->notifiers; } QString OTodo::type() const { return QString::fromLatin1("OTodo"); } QString OTodo::recordField(int /*id*/ )const { return QString::null; } int OTodo::rtti(){ return OPimResolver::TodoList; } diff --git a/libopie/pim/test/oevent_test.cpp b/libopie/pim/test/oevent_test.cpp new file mode 100644 index 0000000..50cc032 --- a/dev/null +++ b/libopie/pim/test/oevent_test.cpp @@ -0,0 +1,23 @@ +#include <qdatetime.h> + +#include "../oevent.h" + +int main(int argc, char* argv ) { + OEvent ev; + ev.setUid( 20 ); + + ev.setDescription( "Foo" ); + + OEvent ev2 = ev; + ev2.setDescription("Foo2"); + qWarning("%s", ev2.description().latin1() ); + qWarning("%s", ev.description().latin1() ); + + QDateTime time = QDateTime::currentDateTime(); + ev2.setStartDateTime( time ); + ev2.setTimeZone( "Europe/London" ); + + qWarning("%s", ev2.startDateTime().toString().latin1() ); + qWarning("%s", ev2.startDateTimeInZone().toString().latin1() ); + return 0; +} diff --git a/libopie/pim/test/oevent_test.pro b/libopie/pim/test/oevent_test.pro new file mode 100644 index 0000000..3365def --- a/dev/null +++ b/libopie/pim/test/oevent_test.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +#CONFIG = qt warn_on debug +CONFIG = qt warn_on release +#HEADERS = +SOURCES = oevent_test.cpp +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe -lopie +TARGET = oevent_test + +include ( $(OPIEDIR)/include.pro )
\ No newline at end of file diff --git a/libopie/pim/test/test_todo.cpp b/libopie/pim/test/test_todo.cpp new file mode 100644 index 0000000..7440503 --- a/dev/null +++ b/libopie/pim/test/test_todo.cpp @@ -0,0 +1,36 @@ +#include <qdatetime.h> +#include <qmap.h> + +#include <opie/otodo.h> +#include <opie/otodoaccess.h> +#include <opie/otodoaccessxml.h> + +int main(int argc, char* argv[] ) { + + OTodoAccessXML* xml = new OTodoAccessXML("demo"); + OTodoAccess ac(xml); + int elc; + QTime timer; + qWarning("start loading"); + timer.start(); + ac.load(); + elc = timer.elapsed(); + qWarning("Elapsed loading %d %d", elc, elc/1000); + + timer.start(); + OTodoAccess::List lis = ac.allRecords(); + elc = timer.elapsed(); + qWarning("Elapsed allRecords %d %d", elc, elc/1000 ); + OTodoAccess::List::Iterator it; + timer.start(); +ac.save(); +/* + for( it = lis.begin(); it != lis.end(); ++it ) { + qWarning("Desc: " + (*it).summary() ); + qWarning("UID %d", (*it).uid() ); + } + */ +elc = timer.elapsed(); + + qWarning("elapsed iterating %d %d", elc, elc/1000 ); +}; diff --git a/libopie/pim/test/todo_test.pro b/libopie/pim/test/todo_test.pro new file mode 100644 index 0000000..3d14dda --- a/dev/null +++ b/libopie/pim/test/todo_test.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +#CONFIG = qt warn_on debug +CONFIG = qt warn_on release +#HEADERS = +SOURCES = test_todo.cpp +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe -lopie -lopiesql +TARGET = todo_test + +include ( $(OPIEDIR)/ )
\ No newline at end of file diff --git a/libopie/tododb.cpp b/libopie/tododb.cpp deleted file mode 100644 index 17163a0..0000000 --- a/libopie/tododb.cpp +++ b/dev/null @@ -1,268 +0,0 @@ - -#include <qdir.h> -#include <opie/tododb.h> -#include <opie/xmltree.h> -#include <opie/todoresource.h> -#include <qpe/palmtoprecord.h> -#include <qpe/global.h> - -using namespace Opie; - -namespace { - -class FileToDoResource : public ToDoResource { -public: - FileToDoResource() {}; - // FIXME better parsing - bool save(const QString &name, const QValueList<ToDoEvent> &m_todos ){ - // prepare the XML - XMLElement *tasks = new XMLElement( ); - tasks->setTagName("Tasks" ); - for( QValueList<ToDoEvent>::ConstIterator it = m_todos.begin(); it != m_todos.end(); ++it ){ - XMLElement::AttributeMap map; - XMLElement *task = new XMLElement(); - map.insert( "Completed", QString::number((int)(*it).isCompleted() ) ); - map.insert( "HasDate", QString::number((int)(*it).hasDate() ) ); - map.insert( "Priority", QString::number( (*it).priority() ) ); - map.insert( "Progress", QString::number( (*it).progress() ) ); - map.insert( "Summary", (*it).summary() ); - QArray<int> arrat = (*it).categories(); - QString attr; - for(uint i=0; i < arrat.count(); i++ ){ - attr.append(QString::number(arrat[i])+";" ); - } - if(!attr.isEmpty() ) // remove the last ; - attr.remove(attr.length()-1, 1 ); - map.insert( "Categories", attr ); - //else - //map.insert( "Categories", QString::null ); - map.insert( "Description", (*it).description() ); - if( (*it).hasDate() ){ - map.insert("DateYear", QString::number( (*it).date().year() ) ); - map.insert("DateMonth", QString::number( (*it).date().month() ) ); - map.insert("DateDay", QString::number( (*it).date().day() ) ); - } - map.insert("Uid", QString::number( (*it).uid() ) ); - task->setTagName("Task" ); - task->setAttributes( map ); - tasks->appendChild(task); - } - QFile file( name); - if( file.open(IO_WriteOnly ) ){ - QTextStream stream(&file ); - stream.setEncoding( QTextStream::UnicodeUTF8 ); - stream << "<!DOCTYPE Tasks>" << endl; - tasks->save(stream ); - delete tasks; - stream << "</Tasks>" << endl; - file.close(); - return true; - } - return false; - } - QValueList<ToDoEvent> load( const QString &name ){ - qWarning("loading tododb" ); - QValueList<ToDoEvent> m_todos; - XMLElement *root = XMLElement::load( name ); - if(root != 0l ){ // start parsing - qWarning("ToDoDB::load tagName(): %s", root->tagName().latin1() ); - //if( root->tagName() == QString::fromLatin1("Tasks" ) ){// Start - XMLElement *element = root->firstChild(); - if (element == 0 ) - return m_todos; - element = element->firstChild(); - while( element ){ - if( element->tagName() != QString::fromLatin1("Task") ){ - element = element->nextChild(); - continue; - } - qWarning("ToDoDB::load element tagName() : %s", element->tagName().latin1() ); - QString dummy; - ToDoEvent event; - bool ok; - int dumInt; - // completed - dummy = element->attribute("Completed" ); - dumInt = dummy.toInt(&ok ); - if(ok ) event.setCompleted( dumInt == 0 ? false : true ); - // progress - dummy = element->attribute("Progress" ); - { - ushort dumShort = dummy.toUShort(&ok); - event.setProgress( dumShort ); - - } - // hasDate - dummy = element->attribute("HasDate" ); - dumInt = dummy.toInt(&ok ); - if(ok ) event.setHasDate( dumInt == 0 ? false: true ); - // set the date - bool hasDa = dumInt; - if ( hasDa ) { //parse the date - int year, day, month = 0; - year = day = month; - // year - dummy = element->attribute("DateYear" ); - dumInt = dummy.toInt(&ok ); - if( ok ) year = dumInt; - // month - dummy = element->attribute("DateMonth" ); - dumInt = dummy.toInt(&ok ); - if(ok ) month = dumInt; - dummy = element->attribute("DateDay" ); - dumInt = dummy.toInt(&ok ); - if(ok ) day = dumInt; - // set the date - QDate date( year, month, day ); - event.setDate( date); - } - dummy = element->attribute("Priority" ); - dumInt = dummy.toInt(&ok ); - if(!ok ) dumInt = ToDoEvent::NORMAL; - event.setPriority( dumInt ); - //description - dummy = element->attribute("Description" ); - event.setDescription( dummy ); - dummy = element->attribute("Summary" ); - event.setSummary( dummy ); - // category - dummy = element->attribute("Categories" ); - QStringList ids = QStringList::split(";", dummy ); - event.setCategories( ids ); - - //uid - dummy = element->attribute("Uid" ); - dumInt = dummy.toInt(&ok ); - if(ok ) event.setUid( dumInt ); - m_todos.append( event ); - element = element->nextChild(); // next element - } - //} - }else { - qWarning("could not load" ); - } - delete root; - qWarning("returning" ); - return m_todos; - } -}; - -} - -ToDoDB::ToDoDB(const QString &fileName, ToDoResource *res ){ - m_fileName = fileName; - if( fileName.isEmpty() && res == 0 ){ - m_fileName = Global::applicationFileName("todolist","todolist.xml"); - res = new FileToDoResource(); - //qWarning("%s", m_fileName.latin1() ); - }else if(res == 0 ){ // let's create a ToDoResource for xml - res = new FileToDoResource(); - } - m_res = res; - load(); -} -ToDoResource* ToDoDB::resource(){ - return m_res; -}; -void ToDoDB::setResource( ToDoResource *res ) -{ - delete m_res; - m_res = res; -} -ToDoDB::~ToDoDB() -{ - delete m_res; -} -QValueList<ToDoEvent> ToDoDB::effectiveToDos(const QDate &from, const QDate &to, - bool all ) -{ - QValueList<ToDoEvent> events; - for( QValueList<ToDoEvent>::Iterator it = m_todos.begin(); it!= m_todos.end(); ++it ){ - if( (*it).hasDate() ){ - if( (*it).date() >= from && (*it).date() <= to ) - events.append( (*it) ); - }else if( all ){ - events.append( (*it) ); - } - } - return events; -} -QValueList<ToDoEvent> ToDoDB::effectiveToDos(const QDate &from, - bool all) -{ - return effectiveToDos( from, QDate::currentDate(), all ); -} -QValueList<ToDoEvent> ToDoDB::overDue() -{ - QValueList<ToDoEvent> events; - for( QValueList<ToDoEvent>::Iterator it = m_todos.begin(); it!= m_todos.end(); ++it ){ - if( (*it).isOverdue() ) - events.append((*it) ); - } - return events; -} -QValueList<ToDoEvent> ToDoDB::rawToDos() -{ - return m_todos; -} -void ToDoDB::addEvent( const ToDoEvent &event ) -{ - m_todos.append( event ); -} -void ToDoDB::editEvent( const ToDoEvent &event ) -{ - m_todos.remove( event ); - m_todos.append( event ); -} -void ToDoDB::removeEvent( const ToDoEvent &event ) -{ - m_todos.remove( event ); -} -void ToDoDB::replaceEvent(const ToDoEvent &event ) -{ - QValueList<ToDoEvent>::Iterator it; - int uid = event.uid(); - // == is not overloaded as we would like :( so let's search for the uid - for(it = m_todos.begin(); it != m_todos.end(); ++it ){ - if( (*it).uid() == uid ){ - m_todos.remove( (*it) ); - break; // should save us the iterate is now borked - } - } - m_todos.append(event); -} -void ToDoDB::reload() -{ - load(); -} -void ToDoDB::mergeWith(const QValueList<ToDoEvent>& events ) -{ - QValueList<ToDoEvent>::ConstIterator it; - for( it = events.begin(); it != events.end(); ++it ){ - replaceEvent( (*it) ); - } -} -void ToDoDB::setFileName(const QString &file ) -{ - m_fileName =file; -} -QString ToDoDB::fileName()const -{ - return m_fileName; -} -void ToDoDB::load() -{ - m_todos = m_res->load( m_fileName ); -} -bool ToDoDB::save() -{ - return m_res->save( m_fileName, m_todos ); -} - - - - - - - - diff --git a/libopie/tododb.h b/libopie/tododb.h deleted file mode 100644 index 7fd9f96..0000000 --- a/libopie/tododb.h +++ b/dev/null @@ -1,46 +0,0 @@ - -#ifndef tododb_h -#define tododb_h - -#include <qvaluelist.h> - -#include <opie/todoevent.h> - -class ToDoResource; -class ToDoDB -{ - public: - // if no argument is supplied pick the default book - ToDoDB(const QString &fileName = QString::null, ToDoResource* resource= 0 ); - ~ToDoDB(); - QValueList<ToDoEvent> effectiveToDos(const QDate &from, - const QDate &to, - bool includeNoDates = true); - QValueList<ToDoEvent> effectiveToDos(const QDate &start, bool includeNoDates = true ); - QValueList<ToDoEvent> rawToDos(); // all events - QValueList<ToDoEvent> overDue(); - - void addEvent(const ToDoEvent &event ); - void editEvent(const ToDoEvent &editEvent ); - void removeEvent(const ToDoEvent &event); - void replaceEvent(const ToDoEvent &event ); - // QValueList<ToDoEvents will overwrite existing ones no smart code at all ;) - void mergeWith(const QValueList<ToDoEvent>& ); - void reload(); - void setFileName(const QString & ); - QString fileName()const; - bool save(); - ToDoResource *resource(); - void setResource(ToDoResource* res); - - private: - class ToDoDBPrivate; - ToDoDBPrivate *d; - QString m_fileName; - ToDoResource *m_res; - QValueList<ToDoEvent> m_todos; - void load(); -}; - - -#endif diff --git a/libopie/todoevent.cpp b/libopie/todoevent.cpp deleted file mode 100644 index f744550..0000000 --- a/libopie/todoevent.cpp +++ b/dev/null @@ -1,339 +0,0 @@ - -#include <opie/todoevent.h> - - -#include <qpe/palmtopuidgen.h> -#include <qpe/stringutil.h> -#include <qpe/palmtoprecord.h> - -#include <qpe/stringutil.h> -#include <qpe/categories.h> -#include <qpe/categoryselect.h> - -#include <qobject.h> - -ToDoEvent::ToDoEvent(const ToDoEvent &event ) -{ - *this = event; -} - -ToDoEvent::ToDoEvent(bool completed, int priority, - const QStringList &category, - const QString& summary, - const QString &description, - ushort progress, - bool hasDate, QDate date, int uid ) -{ - m_date = date; - m_isCompleted = completed; - m_hasDate = hasDate; - m_priority = priority; - m_category = category; - m_sum = summary; - m_prog = progress; - m_desc = Qtopia::simplifyMultiLineSpace(description ); - if (uid == -1 ) { - Qtopia::UidGen *uidgen = new Qtopia::UidGen(); - uid = uidgen->generate(); - delete uidgen; - }// generate the ids - m_uid = uid; -} -QArray<int> ToDoEvent::categories()const -{ - QArray<int> array(m_category.count() ); // currently the datebook can be only in one category - array = Qtopia::Record::idsFromString( m_category.join(";") ); - return array; -} -bool ToDoEvent::match( const QRegExp ®Exp )const -{ - if( QString::number( m_priority ).find( regExp ) != -1 ){ - return true; - }else if( m_hasDate && m_date.toString().find( regExp) != -1 ){ - return true; - }else if(m_desc.find( regExp ) != -1 ){ - return true; - } - return false; -} -bool ToDoEvent::isCompleted() const -{ - return m_isCompleted; -} -bool ToDoEvent::hasDate() const -{ - return m_hasDate; -} -int ToDoEvent::priority()const -{ - return m_priority; -} -QStringList ToDoEvent::allCategories()const -{ - return m_category; -} -QString ToDoEvent::extra(const QString& )const -{ - return QString::null; -} -QString ToDoEvent::summary() const -{ - return m_sum; -} -ushort ToDoEvent::progress() const -{ - return m_prog; -} -QStringList ToDoEvent::relatedApps() const -{ - QStringList list; - QMap<QString, QArray<int> >::ConstIterator it; - for ( it = m_relations.begin(); it != m_relations.end(); ++it ) { - list << it.key(); - } - return list; -} -QArray<int> ToDoEvent::relations( const QString& app)const -{ - QArray<int> tmp; - QMap<QString, QArray<int> >::ConstIterator it; - it = m_relations.find( app); - if ( it != m_relations.end() ) - tmp = it.data(); - return tmp; -} -void ToDoEvent::insertCategory(const QString &str ) -{ - m_category.append( str ); -} -void ToDoEvent::clearCategories() -{ - m_category.clear(); -} -void ToDoEvent::setCategories(const QStringList &list ) -{ - m_category = list; -} -QDate ToDoEvent::date()const -{ - return m_date; -} - -QString ToDoEvent::description()const -{ - return m_desc; -} -void ToDoEvent::setCompleted( bool completed ) -{ - m_isCompleted = completed; -} -void ToDoEvent::setHasDate( bool hasDate ) -{ - m_hasDate = hasDate; -} -void ToDoEvent::setDescription(const QString &desc ) -{ - m_desc = Qtopia::simplifyMultiLineSpace(desc ); -} -void ToDoEvent::setExtra( const QString&, const QString& ) -{ - -} -void ToDoEvent::setSummary( const QString& sum ) -{ - m_sum = sum; -} -void ToDoEvent::setCategory( const QString &cat ) -{ - qWarning("setCategory %s", cat.latin1() ); - m_category.clear(); - m_category << cat; -} -void ToDoEvent::setPriority(int prio ) -{ - m_priority = prio; -} -void ToDoEvent::setDate( QDate date ) -{ - m_date = date; -} -void ToDoEvent::addRelated( const QString &app, int id ) -{ - QMap<QString, QArray<int> >::Iterator it; - QArray<int> tmp; - it = m_relations.find( app ); - if ( it == m_relations.end() ) { - tmp.resize(1 ); - tmp[0] = id; - }else{ - tmp = it.data(); - tmp.resize( tmp.size() + 1 ); - tmp[tmp.size() - 1] = id; - } - m_relations.replace( app, tmp ); -} -void ToDoEvent::addRelated(const QString& app, QArray<int> ids ) -{ - QMap<QString, QArray<int> >::Iterator it; - QArray<int> tmp; - it = m_relations.find( app); - if ( it == m_relations.end() ) { // not there - /** tmp.resize( ids.size() ); stupid?? - */ - tmp = ids; - }else{ - tmp = it.data(); - int offset = tmp.size()-1; - tmp.resize( tmp.size() + ids.size() ); - for (uint i = 0; i < ids.size(); i++ ) { - tmp[offset+i] = ids[i]; - } - - } - m_relations.replace( app, tmp ); -} -void ToDoEvent::clearRelated( const QString& app ) -{ - m_relations.remove( app ); -} -bool ToDoEvent::isOverdue( ) -{ - if( m_hasDate ) - return QDate::currentDate() > m_date; - return false; -} -void ToDoEvent::setProgress(ushort progress ) -{ - m_prog = progress; -} -/*! - Returns a richt text string -*/ -QString ToDoEvent::richText() const -{ - QString text; - QStringList catlist; - - // Description of the todo - if ( !description().isEmpty() ){ - text += "<b>" + QObject::tr( "Summary:") + "</b><br>"; - text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; - text += "<b>" + QObject::tr( "Description:" ) + "</b><br>"; - text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br><br><br>"; - } - text += "<b>" + QObject::tr( "Priority:") +" </b>" - + QString::number( priority() ) + " <br>"; - text += "<b>" + QObject::tr( "Progress:") + " </b>" - + QString::number( progress() ) + " %<br>"; - if (hasDate() ){ - text += "<b>" + QObject::tr( "Deadline:") + " </b>"; - text += date().toString(); - text += "<br>"; - } - - // Open database of all categories and get the list of - // the categories this todoevent belongs to. - // Then print them... - // I am not sure whether there is no better way doing this !? - Categories catdb; - bool firstloop = true; - catdb.load( categoryFileName() ); - catlist = allCategories(); - - text += "<b>" + QObject::tr( "Category:") + "</b> "; - for ( QStringList::Iterator it = catlist.begin(); it != catlist.end(); ++it ) { - if (!firstloop){ - text += ", "; - } - firstloop = false; - text += catdb.label ("todo", (*it).toInt()); - } - text += "<br>"; - return text; -} - -bool ToDoEvent::operator<( const ToDoEvent &toDoEvent )const{ - if( !hasDate() && !toDoEvent.hasDate() ) return true; - if( !hasDate() && toDoEvent.hasDate() ) return false; - if( hasDate() && toDoEvent.hasDate() ){ - if( date() == toDoEvent.date() ){ // let's the priority decide - return priority() < toDoEvent.priority(); - }else{ - return date() < toDoEvent.date(); - } - } - return false; -} -bool ToDoEvent::operator<=(const ToDoEvent &toDoEvent )const -{ - if( !hasDate() && !toDoEvent.hasDate() ) return true; - if( !hasDate() && toDoEvent.hasDate() ) return true; - if( hasDate() && toDoEvent.hasDate() ){ - if( date() == toDoEvent.date() ){ // let's the priority decide - return priority() <= toDoEvent.priority(); - }else{ - return date() <= toDoEvent.date(); - } - } - return true; -} -bool ToDoEvent::operator>(const ToDoEvent &toDoEvent )const -{ - if( !hasDate() && !toDoEvent.hasDate() ) return false; - if( !hasDate() && toDoEvent.hasDate() ) return false; - if( hasDate() && toDoEvent.hasDate() ){ - if( date() == toDoEvent.date() ){ // let's the priority decide - return priority() > toDoEvent.priority(); - }else{ - return date() > toDoEvent.date(); - } - } - return false; -} -bool ToDoEvent::operator>=(const ToDoEvent &toDoEvent )const -{ - if( !hasDate() && !toDoEvent.hasDate() ) return true; - if( !hasDate() && toDoEvent.hasDate() ) return false; - if( hasDate() && toDoEvent.hasDate() ){ - if( date() == toDoEvent.date() ){ // let's the priority decide - return priority() > toDoEvent.priority(); - }else{ - return date() > toDoEvent.date(); - } - } - return true; -} -bool ToDoEvent::operator==(const ToDoEvent &toDoEvent )const -{ - if( m_priority == toDoEvent.m_priority && - m_priority == toDoEvent.m_prog && - m_isCompleted == toDoEvent.m_isCompleted && - m_hasDate == toDoEvent.m_hasDate && - m_date == toDoEvent.m_date && - m_category == toDoEvent.m_category && - m_sum == toDoEvent.m_sum && - m_desc == toDoEvent.m_desc ) - return true; - return false; -} -ToDoEvent &ToDoEvent::operator=(const ToDoEvent &item ) -{ - m_date = item.m_date; - m_isCompleted = item.m_isCompleted; - m_hasDate = item.m_hasDate; - m_priority = item.m_priority; - m_category = item.m_category; - m_desc = item.m_desc; - m_uid = item.m_uid; - m_sum = item.m_sum; - m_prog = item.m_prog; - return *this; -} - - - - - - - - diff --git a/libopie/todoevent.h b/libopie/todoevent.h deleted file mode 100644 index b55a39b..0000000 --- a/libopie/todoevent.h +++ b/dev/null @@ -1,191 +0,0 @@ - -#ifndef todoevent_h -#define todoevent_h - - -#include <qarray.h> -#include <qmap.h> -#include <qregexp.h> -#include <qstringlist.h> -#include <qdatetime.h> - - -class ToDoEvent { - friend class ToDoDB; - public: - // priorities from Very low to very high - enum Priority { VERYHIGH=1, HIGH, NORMAL, LOW, VERYLOW }; - /* Constructs a new ToDoEvent - @param completed Is the TodoEvent completed - @param priority What is the priority of this ToDoEvent - @param category Which category does it belong( uid ) - @param summary A small summary of the todo - @param description What is this ToDoEvent about - @param hasDate Does this Event got a deadline - @param date what is the deadline? - @param uid what is the UUID of this Event - **/ - ToDoEvent( bool completed = false, int priority = NORMAL, - const QStringList &category = QStringList(), - const QString &summary = QString::null , - const QString &description = QString::null, - ushort progress = 0, - bool hasDate = false, QDate date = QDate::currentDate(), int uid = -1 ); - /* Copy c'tor - - **/ - ToDoEvent(const ToDoEvent & ); - - /* - Is this event completed? - **/ - bool isCompleted() const; - - /* - Does this Event have a deadline - **/ - bool hasDate() const; - - /* - What is the priority? - **/ - int priority()const ; - - /** - * progress as ushort 0, 20, 40, 60, 80 or 100% - */ - ushort progress() const; - /* - All category numbers as QString in a List - **/ - QStringList allCategories()const; - - /* - * Same as above but with QArray<int> - */ - QArray<int> categories() const; - - /** - * The end Date - */ - QDate date()const; - - /** - * The description of the todo - */ - QString description()const; - - /** - * A small summary of the todo - */ - QString summary() const; - - /** - * Return this todoevent in a RichText formatted QString - */ - QString richText() const; - - /** - * Returns the UID of the Todo - */ - int uid()const { return m_uid;}; - - - QString extra(const QString& )const; - - /** - * returns a list of apps which have related items - */ - QStringList relatedApps()const; - - /** - * returns all relations for one app - */ - QArray<int> relations( const QString& app )const; - /** - * Set if this Todo is completed - */ - void setCompleted(bool completed ); - - /** - * set if this todo got an end data - */ - void setHasDate( bool hasDate ); - // if the category doesn't exist we will create it - // this sets the the Category after this call category will be the only category - void setCategory( const QString &category ); - // adds a category to the Categories of this event - void insertCategory(const QString &category ); - - /** - * Removes this event from all categories - */ - void clearCategories(); - - /** - * This todo belongs to xxx categories - */ - void setCategories(const QStringList& ); - - /** - * Set the priority of the Todo - */ - void setPriority(int priority ); - - /** - * Set the progress. - */ - void setProgress( ushort progress ); - - /** - * add related function it replaces too ;) - */ - void addRelated( const QString& app, int id ); - - /** - * add related - */ - void addRelated( const QString& app, QArray<int> ids ); - - /** - * clear relations for one app - */ - void clearRelated(const QString& app); - - /** - * set the end date - */ - void setDate( QDate date ); - void setDescription(const QString& ); - void setSummary(const QString& ); - void setExtra( const QString&, const QString& ); - bool isOverdue(); - - bool match( const QRegExp &r )const; - - void setUid(int id) {m_uid = id; }; - bool operator<(const ToDoEvent &toDoEvent )const; - bool operator<=(const ToDoEvent &toDoEvent )const; - bool operator!=(const ToDoEvent &toDoEvent )const { return !(*this == toDoEvent); }; - bool operator>(const ToDoEvent &toDoEvent )const; - bool operator>=(const ToDoEvent &toDoEvent)const; - bool operator==(const ToDoEvent &toDoEvent )const; - ToDoEvent &operator=(const ToDoEvent &toDoEvent ); - private: - class ToDoEventPrivate; - ToDoEventPrivate *d; - QDate m_date; - bool m_isCompleted:1; - bool m_hasDate:1; - int m_priority; - QStringList m_category; - QString m_desc; - QString m_sum; - QMap<QString, QString> m_extra; - QMap<QString, QArray<int> > m_relations; - int m_uid; - ushort m_prog; -}; - - -#endif diff --git a/libopie/todoresource.h b/libopie/todoresource.h deleted file mode 100644 index 34edb04..0000000 --- a/libopie/todoresource.h +++ b/dev/null @@ -1,14 +0,0 @@ - - -#ifndef opietodoresource_h -#define opietodoresource_h - -class ToDoEvent; -class ToDoResource { - public: - ToDoResource( ) {}; - virtual QValueList<ToDoEvent> load(const QString &file ) = 0; - virtual bool save( const QString &file, const QValueList<ToDoEvent> & ) = 0; -}; - -#endif diff --git a/libopie/todovcalresource.cpp b/libopie/todovcalresource.cpp deleted file mode 100644 index 1df5aff..0000000 --- a/libopie/todovcalresource.cpp +++ b/dev/null @@ -1,158 +0,0 @@ -/* - =. This file is part of the OPIE Project - .=l. Copyright (c) 2002 Holger Freyther <freyther@kde.org> - .>+-= the use of vobject was inspired by libkcal - _;:, .> :=|. This library is free software; you can -.> <`_, > . <= redistribute it and/or modify it under -:`=1 )Y*s>-.-- : the terms of the GNU Library General Public -.="- .-=="i, .._ License as published by the Free Software - - . .-<_> .<> Foundation; either version 2 of the License, - ._= =} : or (at your option) any later version. - .%`+i> _;_. - .i_,=:_. -<s. This library is distributed in the hope that - + . -:. = it will be useful, but WITHOUT ANY WARRANTY; - : .. .:, . . . without even the implied warranty of - =_ + =;=|` MERCHANTABILITY or FITNESS FOR A - _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU -..}^=.= = ; Library General Public License for more -++= -. .` .: details. - : = ...= . :.=- - -. .:....=;==+<; You should have received a copy of the GNU - -_. . . )=. = Library General Public License along with - -- :-=` this library; see the file COPYING.LIB. - If not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - -*/ - -#include <qfile.h> -#include <qvaluelist.h> -#include <opie/todoevent.h> -#include <opie/todovcalresource.h> - -#include "../library/backend/vobject_p.h" -#include "../library/timeconversion.h" -#include "../library/backend/qfiledirect_p.h" - -static VObject *vobjByEvent( const ToDoEvent &event ) -{ - VObject *task = newVObject( VCTodoProp ); - if( task == 0 ) - return 0l; - if( event.hasDate() ) - addPropValue( task, VCDueProp, TimeConversion::toISO8601( event.date() ) ); - - if( event.isCompleted() ) - addPropValue( task, VCStatusProp, "COMPLETED"); - - QString string = QString::number(event.priority() ); - addPropValue( task, VCPriorityProp, string.local8Bit() ); - addPropValue( task, VCCategoriesProp, event.allCategories().join(";").local8Bit() ); - addPropValue( task, VCDescriptionProp, event.description().local8Bit() ); - addPropValue( task, VCSummaryProp, event.summary().left(15).local8Bit() ); - return task; -}; - -static ToDoEvent eventByVObj( VObject *obj ){ - ToDoEvent event; - VObject *ob; - QCString name; - // no uid, attendees, ... and no fun - // description - if( ( ob = isAPropertyOf( obj, VCDescriptionProp )) != 0 ){ - name = vObjectStringZValue( ob ); - event.setDescription( name ); - } - // summary - if ( ( ob = isAPropertyOf( obj, VCSummaryProp ) ) != 0 ) { - name = vObjectStringZValue( ob ); - event.setSummary( name ); - } - // completed - if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){ - name = vObjectStringZValue( ob ); - if( name == "COMPLETED" ){ - event.setCompleted( true ); - }else{ - event.setCompleted( false ); - } - }else - event.setCompleted( false ); - // priority - if ((ob = isAPropertyOf(obj, VCPriorityProp))) { - name = vObjectStringZValue( ob ); - bool ok; - event.setPriority(name.toInt(&ok) ); - } - //due date - if((ob = isAPropertyOf(obj, VCDueProp)) ){ - event.setHasDate( true ); - name = vObjectStringZValue( ob ); - event.setDate( TimeConversion::fromISO8601( name).date() ); - } - // categories - if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){ - name = vObjectStringZValue( ob ); - qWarning("Categories:%s", name.data() ); - } - - return event; -}; - - -QValueList<ToDoEvent> ToDoVCalResource::load(const QString &file) -{ - QValueList<ToDoEvent> events; - VObject *vcal = 0l; - vcal = Parse_MIME_FromFileName( (char *)file.utf8().data() ); // from vobject - if(!vcal ) - return events; - // start parsing - - VObjectIterator it; - VObject *vobj; - initPropIterator(&it, vcal); - - while( moreIteration( &it ) ) { - vobj = ::nextVObject( &it ); - QCString name = ::vObjectName( vobj ); - //QCString objVal = ::vObjectStringZValue( vobj ); - // let's find out the type - if( name == VCTodoProp ){ - events.append( eventByVObj( vobj ) ); - - } // parse the value - } - return events; -} -bool ToDoVCalResource::save(const QString &fileName, const QValueList<ToDoEvent>&list ) -{ - QFileDirect file ( fileName ); - if(!file.open(IO_WriteOnly ) ) - return false; - // obj - VObject *obj; - obj = newVObject( VCCalProp ); - addPropValue( obj, VCVersionProp, "1.0" ); - VObject *vo; - for(QValueList<ToDoEvent>::ConstIterator it = list.begin(); it != list.end(); ++it ){ - vo = vobjByEvent( (*it) ); - addVObjectProp(obj, vo ); - } - writeVObject( file.directHandle(), obj ); - cleanVObject( obj ); - cleanStrTbl(); - - return true; -} - - - - - - - - - - diff --git a/libopie/todovcalresource.h b/libopie/todovcalresource.h deleted file mode 100644 index 0663bc2..0000000 --- a/libopie/todovcalresource.h +++ b/dev/null @@ -1,42 +0,0 @@ -/* - =. This file is part of the OPIE Project - .=l. Copyright (c) 2002 Holger Freyther <freyther@kde.org> - .>+-= - _;:, .> :=|. This library is free software; you can -.> <`_, > . <= redistribute it and/or modify it under -:`=1 )Y*s>-.-- : the terms of the GNU Library General Public -.="- .-=="i, .._ License as published by the Free Software - - . .-<_> .<> Foundation; either version 2 of the License, - ._= =} : or (at your option) any later version. - .%`+i> _;_. - .i_,=:_. -<s. This library is distributed in the hope that - + . -:. = it will be useful, but WITHOUT ANY WARRANTY; - : .. .:, . . . without even the implied warranty of - =_ + =;=|` MERCHANTABILITY or FITNESS FOR A - _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU -..}^=.= = ; Library General Public License for more -++= -. .` .: details. - : = ...= . :.=- - -. .:....=;==+<; You should have received a copy of the GNU - -_. . . )=. = Library General Public License along with - -- :-=` this library; see the file COPYING.LIB. - If not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - -*/ - -#ifndef opievcaltodoresource_h -#define opievcaltodoresource_h - -#include <opie/todoresource.h> - -class ToDoVCalResource : public ToDoResource { - public: - ToDoVCalResource() { }; - QValueList<ToDoEvent> load(const QString &file ); - bool save( const QString &filename, const QValueList<ToDoEvent> & ); - -}; - -#endif diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp index 622d40a..e537269 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp +++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp @@ -1,461 +1,470 @@ /* * VCard Backend for the OPIE-Contact Database. * * Copyright (C) 2000 Trolltech AS. All rights reserved. * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) * * ===================================================================== * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * ===================================================================== * ToDo: * * ===================================================================== * Version: $Id$ * ===================================================================== * History: * $Log$ + * Revision 1.8 2003/02/21 16:52:49 zecke + * -Remove old Todo classes they're deprecated and today I already using the + * new API + * -Guard against self assignment in OTodo + * -Add test apps for OPIM + * -Opiefied Event classes + * -Added TimeZone handling and pinning of TimeZones to OEvent + * -Adjust ORecur and the widget to better timezone behaviour + * * Revision 1.7 2003/02/16 22:25:46 zecke * 0000276 Fix for that bug.. or better temp workaround * A Preferred Number is HOME|VOICE * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test * triggers both * and the cell phone number overrides the other entries.. * * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the * number * * The right and final fix would be to reorder the if statement to make it * if else based and the less common thing put to the bottom * * OTodoAccessVcal fix the date for beaming * * Revision 1.6 2003/01/13 15:49:31 eilers * Fixing crash when businesscard.vcf is missing.. * * Revision 1.5 2002/12/07 13:26:22 eilers * Fixing bug in storing anniversary.. * * Revision 1.4 2002/11/13 14:14:51 eilers * Added sorted for Contacts.. * * Revision 1.3 2002/11/11 16:41:09 kergoth * no default arguments in implementation * * Revision 1.2 2002/11/10 15:41:53 eilers * Bugfixes.. * * Revision 1.1 2002/11/09 14:34:52 eilers * Added VCard Backend. * */ #include "ocontactaccessbackend_vcard.h" #include "../../library/backend/vobject_p.h" #include "../../library/backend/qfiledirect_p.h" #include <qpe/timeconversion.h> #include <qfile.h> OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename ): m_dirty( false ), m_file( filename ) { load(); } bool OContactAccessBackend_VCard::load () { m_map.clear(); m_dirty = false; VObject* obj = 0l; - if ( QFile( m_file ).exists() ){ + if ( QFile::exists(m_file) ){ obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); if ( !obj ) return false; }else{ qWarning("File \"%s\" not found !", m_file.latin1() ); return false; } while ( obj ) { OContact con = parseVObject( obj ); /* * if uid is 0 assign a new one * this at least happens on * Nokia6210 */ if ( con.uid() == 0 ){ con.setUid( 1 ); qWarning("assigned new uid %d",con.uid() ); } m_map.insert( con.uid(), con ); VObject *t = obj; obj = nextVObjectInList(obj); cleanVObject( t ); } return true; } bool OContactAccessBackend_VCard::reload() { return load(); } bool OContactAccessBackend_VCard::save() { if (!m_dirty ) return true; QFileDirect file( m_file ); if (!file.open(IO_WriteOnly ) ) return false; VObject *obj; obj = newVObject( VCCalProp ); addPropValue( obj, VCVersionProp, "1.0" ); VObject *vo; for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ vo = createVObject( *it ); writeVObject( file.directHandle() , vo ); cleanVObject( vo ); } cleanStrTbl(); m_dirty = false; return true; } void OContactAccessBackend_VCard::clear () { m_map.clear(); m_dirty = true; // ??? sure ? (se) } bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) { m_map.insert( newcontact.uid(), newcontact ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::remove ( int uid ) { m_map.remove( uid ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::replace ( const OContact &contact ) { m_map.replace( contact.uid(), contact ); m_dirty = true; return true; } OContact OContactAccessBackend_VCard::find ( int uid ) const { return m_map[uid]; } QArray<int> OContactAccessBackend_VCard::allRecords() const { QArray<int> ar( m_map.count() ); QMap<int, OContact>::ConstIterator it; int i = 0; for ( it = m_map.begin(); it != m_map.end(); ++it ) { ar[i] = it.key(); i++; } return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) { QArray<int> ar(0); return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const { QArray<int> ar(0); return ar; } const uint OContactAccessBackend_VCard::querySettings() { return 0; // No search possible } bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const { return false; // No search possible, therefore all settings invalid ;) } bool OContactAccessBackend_VCard::wasChangedExternally() { return false; // Don't expect concurrent access } // Not implemented QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int ) { QArray<int> ar(0); return ar; } // *** Private stuff *** OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) { OContact c; VObjectIterator it; initPropIterator( &it, obj ); while( moreIteration( &it ) ) { VObject *o = nextVObject( &it ); QCString name = vObjectName( o ); QCString value = vObjectStringZValue( o ); if ( name == VCNameProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); QString value = vObjectStringZValue( o ); if ( name == VCNamePrefixesProp ) c.setTitle( value ); else if ( name == VCNameSuffixesProp ) c.setSuffix( value ); else if ( name == VCFamilyNameProp ) c.setLastName( value ); else if ( name == VCGivenNameProp ) c.setFirstName( value ); else if ( name == VCAdditionalNamesProp ) c.setMiddleName( value ); } } else if ( name == VCAdrProp ) { bool work = TRUE; // default address is work address QString street; QString city; QString region; QString postal; QString country; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCHomeProp ) work = FALSE; else if ( name == VCWorkProp ) work = TRUE; else if ( name == VCStreetAddressProp ) street = value; else if ( name == VCCityProp ) city = value; else if ( name == VCRegionProp ) region = value; else if ( name == VCPostalCodeProp ) postal = value; else if ( name == VCCountryNameProp ) country = value; } if ( work ) { c.setBusinessStreet( street ); c.setBusinessCity( city ); c.setBusinessCountry( country ); c.setBusinessZip( postal ); c.setBusinessState( region ); } else { c.setHomeStreet( street ); c.setHomeCity( city ); c.setHomeCountry( country ); c.setHomeZip( postal ); c.setHomeState( region ); } } else if ( name == VCTelephoneProp ) { enum { HOME = 0x01, WORK = 0x02, VOICE = 0x04, CELL = 0x08, FAX = 0x10, PAGER = 0x20, UNKNOWN = 0x80 }; int type = 0; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) type |= HOME; else if ( name == VCWorkProp ) type |= WORK; else if ( name == VCVoiceProp ) type |= VOICE; else if ( name == VCCellularProp ) type |= CELL; else if ( name == VCFaxProp ) type |= FAX; else if ( name == VCPagerProp ) type |= PAGER; else if ( name == VCPreferredProp ) ; else type |= UNKNOWN; } if ( (type & UNKNOWN) != UNKNOWN ) { if ( ( type & (HOME|WORK) ) == 0 ) // default type |= HOME; if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default type |= VOICE; qWarning("value %s %d", value.data(), type ); if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) ) c.setHomePhone( value ); if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) c.setHomeFax( value ); if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) c.setHomeMobile( value ); if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) ) c.setBusinessPhone( value ); if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) c.setBusinessFax( value ); if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) c.setBusinessMobile( value ); if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) c.setBusinessPager( value ); } } else if ( name == VCEmailAddressProp ) { QString email = vObjectStringZValue( o ); bool valid = TRUE; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name != VCInternetProp && name != VCHomeProp && name != VCWorkProp && name != VCPreferredProp ) // ### preffered should map to default email valid = FALSE; } if ( valid ) { c.insertEmail( email ); } } else if ( name == VCURLProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) c.setHomeWebpage( value ); else if ( name == VCWorkProp ) c.setBusinessWebpage( value ); } } else if ( name == VCOrgProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCOrgNameProp ) c.setCompany( value ); else if ( name == VCOrgUnitProp ) c.setDepartment( value ); else if ( name == VCOrgUnit2Prop ) c.setOffice( value ); } } else if ( name == VCTitleProp ) { c.setJobTitle( value ); } else if ( name == "X-Qtopia-Profession" ) { c.setProfession( value ); } else if ( name == "X-Qtopia-Manager" ) { c.setManager( value ); } else if ( name == "X-Qtopia-Assistant" ) { c.setAssistant( value ); } else if ( name == "X-Qtopia-Spouse" ) { c.setSpouse( value ); } else if ( name == "X-Qtopia-Gender" ) { c.setGender( value ); } else if ( name == "X-Qtopia-Anniversary" ) { c.setAnniversary( convVCardDateToDate( value ) ); } else if ( name == "X-Qtopia-Nickname" ) { c.setNickname( value ); } else if ( name == "X-Qtopia-Children" ) { c.setChildren( value ); } else if ( name == VCBirthDateProp ) { // Reading Birthdate regarding RFC 2425 (5.8.4) c.setBirthday( convVCardDateToDate( value ) ); } #if 0 else { printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); printf(" subprop: %s = %s\n", name.data(), value.latin1() ); } } #endif } c.setFileAs(); return c; } VObject* OContactAccessBackend_VCard::createVObject( const OContact &c ) { VObject *vcard = newVObject( VCCardProp ); safeAddPropValue( vcard, VCVersionProp, "2.1" ); safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); // full name safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); // name properties VObject *name = safeAddProp( vcard, VCNameProp ); safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); safeAddPropValue( name, VCGivenNameProp, c.firstName() ); safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp index daf3506..e6a4787 100644 --- a/libopie2/opiepim/core/orecur.cpp +++ b/libopie2/opiepim/core/orecur.cpp @@ -1,451 +1,446 @@ #include <qshared.h> #include <qtopia/timeconversion.h> #include "orecur.h" struct ORecur::Data : public QShared { Data() : QShared() { type = ORecur::NoRepeat; freq = -1; days = 0; pos = 0; - create = -1; + create = QDateTime::currentDateTime(); hasEnd = FALSE; - end = 0; + end = QDate::currentDate(); } char days; // Q_UINT8 for 8 seven days;) ORecur::RepeatType type; int freq; int pos; bool hasEnd : 1; - time_t end; - time_t create; + QDate end; + QDateTime create; int rep; QString app; ExceptionList list; QDate start; }; ORecur::ORecur() { data = new Data; } ORecur::ORecur( const ORecur& rec) : data( rec.data ) { data->ref(); } ORecur::~ORecur() { if ( data->deref() ) { delete data; data = 0l; } } void ORecur::deref() { if ( data->deref() ) { delete data; data = 0l; } } bool ORecur::operator==( const ORecur& )const { return false; } ORecur &ORecur::operator=( const ORecur& re) { + if ( *this == re ) return *this; + re.data->ref(); deref(); data = re.data; return *this; } bool ORecur::doesRecur()const { return !( type() == NoRepeat ); } /* * we try to be smart here * */ bool ORecur::doesRecur( const QDate& date ) { /* the day before the recurrance */ QDate da = date.addDays(-1); QDate recur; if (!nextOcurrence( da, recur ) ) return false; return (recur == date); } // FIXME unuglify! // GPL from Datebookdb.cpp // FIXME exception list! bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { // easy checks, first are we too far in the future or too far in the past? QDate tmpDate; int freq = frequency(); int diff, diff2, a; int iday, imonth, iyear; int dayOfWeek = 0; int firstOfWeek = 0; int weekOfMonth; if (hasEndDate() && endDate() < from) return FALSE; if (start() >= from) { next = start(); return TRUE; } switch ( type() ) { case Weekly: /* weekly is just daily by 7 */ /* first convert the repeatPattern.Days() mask to the next day of week valid after from */ dayOfWeek = from.dayOfWeek(); dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ /* this is done in case freq > 1 and from in week not for this round */ // firstOfWeek = 0; this is already done at decl. while(!((1 << firstOfWeek) & days() )) firstOfWeek++; /* there is at least one 'day', or there would be no event */ while(!((1 << (dayOfWeek % 7)) & days() )) dayOfWeek++; dayOfWeek = dayOfWeek % 7; /* the actual day of week */ dayOfWeek -= start().dayOfWeek() -1; firstOfWeek = firstOfWeek % 7; /* the actual first of week */ firstOfWeek -= start().dayOfWeek() -1; // dayOfWeek may be negitive now // day of week is number of days to add to start day freq *= 7; // FALL-THROUGH !!!!! case Daily: // the add is for the possible fall through from weekly */ if(start().addDays(dayOfWeek) > from) { /* first week exception */ next = QDate(start().addDays(dayOfWeek) ); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* if from is middle of a non-week */ diff = start().addDays(dayOfWeek).daysTo(from) % freq; diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; if(diff != 0) diff = freq - diff; if(diff2 != 0) diff2 = freq - diff2; diff = QMIN(diff, diff2); next = QDate(from.addDays(diff)); if ( (next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case MonthlyDay: iday = from.day(); iyear = from.year(); imonth = from.month(); /* find equivelent day of month for this month */ dayOfWeek = start().dayOfWeek(); weekOfMonth = (start().day() - 1) / 7; /* work out when the next valid month is */ a = from.year() - start().year(); a *= 12; a = a + (imonth - start().month()); /* a is e.start()monthsFrom(from); */ if(a % freq) { a = freq - (a % freq); imonth = from.month() + a; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } } /* imonth is now the first month after or on from that matches the frequency given */ /* find for this month */ tmpDate = QDate( iyear, imonth, 1 ); iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; while (iday > tmpDate.daysInMonth()) { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } tmpDate = QDate( iyear, imonth, 1 ); /* these loops could go for a while, check end case now */ if ((tmpDate > endDate()) && hasEndDate() ) return FALSE; iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; } tmpDate = QDate(iyear, imonth, iday); if (tmpDate >= from) { next = tmpDate; if ((next > endDate() ) && hasEndDate() ) return FALSE; return TRUE; } /* need to find the next iteration */ do { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } tmpDate = QDate( iyear, imonth, 1 ); /* these loops could go for a while, check end case now */ if ((tmpDate > endDate()) && hasEndDate() ) return FALSE; iday = 1; iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; iday += 7 * weekOfMonth; } while (iday > tmpDate.daysInMonth()); tmpDate = QDate(iyear, imonth, iday); next = tmpDate; if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case MonthlyDate: iday = start().day(); iyear = from.year(); imonth = from.month(); a = from.year() - start().year(); a *= 12; a = a + (imonth - start().month()); /* a is e.start()monthsFrom(from); */ if(a % freq) { a = freq - (a % freq); imonth = from.month() + a; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } } /* imonth is now the first month after or on from that matches the frequencey given */ /* this could go for a while, worse case, 4*12 iterations, probably */ while(!QDate::isValid(iyear, imonth, iday) ) { imonth += freq; if (imonth > 12) { imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; } /* these loops could go for a while, check end case now */ if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) return FALSE; } if(QDate(iyear, imonth, iday) >= from) { /* done */ next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* ok, need to cycle */ imonth += freq; imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; while(!QDate::isValid(iyear, imonth, iday) ) { imonth += freq; imonth--; iyear += imonth / 12; imonth = imonth % 12; imonth++; if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) return FALSE; } next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; case Yearly: iday = start().day(); imonth = start().month(); iyear = from.year(); // after all, we want to start in this year diff = 1; if(imonth == 2 && iday > 28) { /* leap year, and it counts, calculate actual frequency */ if(freq % 4) if (freq % 2) freq = freq * 4; else freq = freq * 2; /* else divides by 4 already, leave freq alone */ diff = 4; } a = from.year() - start().year(); if(a % freq) { a = freq - (a % freq); iyear = iyear + a; } /* under the assumption we won't hit one of the special not-leap years twice */ if(!QDate::isValid(iyear, imonth, iday)) { /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ iyear += freq; } if(QDate(iyear, imonth, iday) >= from) { next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; } /* iyear == from.year(), need to advance again */ iyear += freq; /* under the assumption we won't hit one of the special not-leap years twice */ if(!QDate::isValid(iyear, imonth, iday)) { /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ iyear += freq; } next = QDate(iyear, imonth, iday); if ((next > endDate()) && hasEndDate() ) return FALSE; return TRUE; default: return FALSE; } } ORecur::RepeatType ORecur::type()const{ return data->type; } int ORecur::frequency()const { return data->freq; } int ORecur::position()const { return data->pos; } char ORecur::days() const{ return data->days; } bool ORecur::hasEndDate()const { return data->hasEnd; } QDate ORecur::endDate()const { - return TimeConversion::fromUTC( data->end ).date(); + return data->end; } QDate ORecur::start()const{ return data->start; } -time_t ORecur::endDateUTC()const { - return data->end; -} -time_t ORecur::createTime()const { +QDateTime ORecur::createdDateTime()const { return data->create; } int ORecur::repetition()const { return data->rep; } QString ORecur::service()const { return data->app; } ORecur::ExceptionList& ORecur::exceptions() { return data->list; } void ORecur::setType( const RepeatType& z) { checkOrModify(); data->type = z; } void ORecur::setFrequency( int freq ) { checkOrModify(); data->freq = freq; } void ORecur::setPosition( int pos ) { checkOrModify(); data->pos = pos; } void ORecur::setDays( char c ) { checkOrModify(); data->days = c; } void ORecur::setEndDate( const QDate& dt) { checkOrModify(); - data->end = TimeConversion::toUTC( dt ); -} -void ORecur::setEndDateUTC( time_t t) { - checkOrModify(); - data->end = t; + data->end = dt; } -void ORecur::setCreateTime( time_t t) { +void ORecur::setCreatedDateTime( const QDateTime& t) { checkOrModify(); data->create = t; } void ORecur::setHasEndDate( bool b) { checkOrModify(); data->hasEnd = b; } void ORecur::setRepitition( int rep ) { checkOrModify(); data->rep = rep; } void ORecur::setService( const QString& app ) { checkOrModify(); data->app = app; } void ORecur::setStart( const QDate& dt ) { checkOrModify(); data->start = dt; } void ORecur::checkOrModify() { if ( data->count != 1 ) { data->deref(); Data* d2 = new Data; d2->days = data->days; d2->type = data->type; d2->freq = data->freq; d2->pos = data->pos; d2->hasEnd = data->hasEnd; d2->end = data->end; d2->create = data->create; d2->rep = data->rep; d2->app = data->app; d2->list = data->list; d2->start = data->start; data = d2; } } diff --git a/libopie2/opiepim/core/orecur.h b/libopie2/opiepim/core/orecur.h index 8713d97..1e0014b 100644 --- a/libopie2/opiepim/core/orecur.h +++ b/libopie2/opiepim/core/orecur.h @@ -1,83 +1,87 @@ /* * GPL from TT */ #ifndef OPIE_RECUR_H #define OPIE_RECUR_H #include <sys/types.h> #include <qdatetime.h> #include <qvaluelist.h> class ORecur { public: typedef QValueList<QDate> ExceptionList; enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, MonthlyDate, Yearly }; enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, FRI = 0x10, SAT = 0x20, SUN = 0x40 }; ORecur(); ORecur( const ORecur& ); ~ORecur(); ORecur &operator=( const ORecur& ); bool operator==(const ORecur& )const; bool doesRecur()const; /* if it recurrs on that day */ bool doesRecur( const QDate& ); RepeatType type()const; int frequency()const; int position()const; char days()const; bool hasEndDate()const; QDate start()const; QDate endDate()const; - time_t endDateUTC()const; - time_t createTime()const; + QDateTime createdDateTime()const; + /** + * starting on monday=0, sunday=6 + * for convience + */ + bool repeatOnWeekDay( int day )const; /** * FromWhereToStart is not included!!! */ bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); + /** * The module this ORecur belongs to */ QString service()const; /* * reference to the exception list */ ExceptionList &exceptions(); /** * the current repetition */ int repetition()const; void setType( const RepeatType& ); void setFrequency( int freq ); void setPosition( int pos ); void setDays( char c); void setEndDate( const QDate& dt ); void setStart( const QDate& dt ); - void setEndDateUTC( time_t ); - void setCreateTime( time_t ); + void setCreatedDateTime( const QDateTime& ); void setHasEndDate( bool b ); void setRepitition(int ); void setService( const QString& ser ); private: void deref(); inline void checkOrModify(); class Data; Data* data; class ORecurPrivate; ORecurPrivate *d; }; #endif diff --git a/libopie2/opiepim/core/otimezone.cpp b/libopie2/opiepim/core/otimezone.cpp new file mode 100644 index 0000000..b2bd3aa --- a/dev/null +++ b/libopie2/opiepim/core/otimezone.cpp @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <sys/types.h> + +#include "otimezone.h" + +namespace { + + QDateTime utcTime( time_t t) { + tm* broken = ::gmtime( &t ); + QDateTime ret; + ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) ); + ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) ); + return ret; + } + QDateTime utcTime( time_t t, const QString& zone) { + QCString org = ::getenv( "TZ" ); + ::setenv( "TZ", zone.latin1(), true ); + ::tzset(); + + tm* broken = ::localtime( &t ); + ::setenv( "TZ", org, true ); + + QDateTime ret; + ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) ); + ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) ); + + return ret; + } + time_t to_Time_t( const QDateTime& utc, const QString& str ) { + QDate d = utc.date(); + QTime t = utc.time(); + + tm broken; + broken.tm_year = d.year() - 1900; + broken.tm_mon = d.month() - 1; + broken.tm_mday = d.day(); + broken.tm_hour = t.hour(); + broken.tm_min = t.minute(); + broken.tm_sec = t.second(); + + QCString org = ::getenv( "TZ" ); + ::setenv( "TZ", str.latin1(), true ); + ::tzset(); + + time_t ti = ::mktime( &broken ); + ::setenv( "TZ", org, true ); + + return ti; + } +} +OTimeZone::OTimeZone( const ZoneName& zone ) + : m_name(zone) { +} +OTimeZone::~OTimeZone() { +} + +bool OTimeZone::isValid()const { + return !m_name.isEmpty(); +} + +/* + * we will get the current timezone + * and ask it to convert to the timezone date + */ +QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) { + return OTimeZone::current().toDateTime( dt, *this ); +} +QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) { + return OTimeZone::utc().toDateTime( dt, *this ); +} +QDateTime OTimeZone::fromUTCDateTime( time_t t) { + return utcTime( t ); +} +QDateTime OTimeZone::toDateTime( time_t t) { + return utcTime( t, m_name ); +} +/* + * convert dt to utc using zone.m_name + * convert utc -> timeZoneDT using this->m_name + */ +QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) { + time_t utc = to_Time_t( dt, zone.m_name ); + qWarning("%d %s", utc, zone.m_name.latin1() ); + return utcTime( utc, m_name ); +} +time_t OTimeZone::fromDateTime( const QDateTime& time ) { + return to_Time_t( time, m_name ); +} +time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) { + return to_Time_t( time, "UTC" ); +} +OTimeZone OTimeZone::current() { + QCString str = ::getenv("TZ"); + OTimeZone zone( str ); + return zone; +} +OTimeZone OTimeZone::utc() { + return OTimeZone("UTC"); +} +QString OTimeZone::timeZone()const { + return m_name; +} diff --git a/libopie2/opiepim/core/otimezone.h b/libopie2/opiepim/core/otimezone.h new file mode 100644 index 0000000..bb08349 --- a/dev/null +++ b/libopie2/opiepim/core/otimezone.h @@ -0,0 +1,71 @@ +#ifndef OPIE_TIME_ZONE_H +#define OPIE_TIME_ZONE_H + +#include <time.h> +#include <qdatetime.h> + +/** + * A very primitive class to convert time + * from one timezone to another + * and to localtime + * and time_t + */ +class OTimeZone { + public: + typedef QString ZoneName; + OTimeZone( const ZoneName& = ZoneName::null ); + virtual ~OTimeZone(); // just in case. + + bool isValid()const; + + /** + * converts the QDateTime to a DateTime + * in the local timezone + * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h + * and the current timezone is Europe/London the returned + * time will be 11h. + */ + QDateTime toLocalDateTime( const QDateTime& dt ); + + /** + * converts the QDateTime to UTC time + */ + QDateTime toUTCDateTime( const QDateTime& dt ); + + /** + * reads the time_t into a QDateTime using UTC as timezone! + */ + QDateTime fromUTCDateTime( time_t ); + + /** + * converts the time_t to the time in the timezone + */ + QDateTime toDateTime( time_t ); + + /** + * converts the QDateTime from one timezone to this timeZone + */ + QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone ); + + /** + * converts the date time into a time_t. It takes the timezone into account + */ + time_t fromDateTime( const QDateTime& ); + + /** + * converts the datetime with timezone UTC + */ + time_t fromUTCDateTime( const QDateTime& ); + + static OTimeZone current(); + static OTimeZone utc(); + + QString timeZone()const; + private: + ZoneName m_name; + class Private; + Private* d; +}; + + +#endif diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp new file mode 100644 index 0000000..71b9441 --- a/dev/null +++ b/libopie2/opiepim/oevent.cpp @@ -0,0 +1,427 @@ +#include <qshared.h> + +#include <qpe/palmtopuidgen.h> +#include <qpe/categories.h> + +#include "orecur.h" +#include "opimresolver.h" +#include "opimnotifymanager.h" + +#include "oevent.h" + +namespace OCalendarHelper { + static int week( const QDate& date) { + // Calculates the week this date is in within that + // month. Equals the "row" is is in in the month view + int week = 1; + QDate tmp( date.year(), date.month(), 1 ); + if ( date.dayOfWeek() < tmp.dayOfWeek() ) + ++week; + + week += ( date.day() - 1 ) / 7; + + return week; + } + static int occurence( const QDate& date) { + // calculates the number of occurrances of this day of the + // week till the given date (e.g 3rd Wednesday of the month) + return ( date.day() - 1 ) / 7 + 1; + } + static int dayOfWeek( char day ) { + int dayOfWeek = 1; + char i = ORecur::MON; + while ( !( i & day ) && i <= ORecur::SUN ) { + i <<= 1; + ++dayOfWeek; + } + return dayOfWeek; + } + static int monthDiff( const QDate& first, const QDate& second ) { + return ( second.year() - first.year() ) * 12 + + second.month() - first.month(); + } +} + +struct OEvent::Data : public QShared { + Data() : QShared() { + recur = 0; + manager = 0; + isAllDay = false; + } + ~Data() { + delete manager; + delete recur; + } + QString description; + QString location; + OPimNotifyManager* manager; + ORecur* recur; + QString note; + QDateTime created; + QDateTime start; + QDateTime end; + bool isAllDay : 1; + QString timezone; +}; + +OEvent::OEvent( int uid ) + : OPimRecord( uid ) { + data = new Data; +} +OEvent::OEvent( const OEvent& ev) + : OPimRecord( ev ), data( ev.data ) +{ + data->ref(); +} +OEvent::~OEvent() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +OEvent& OEvent::operator=( const OEvent& ev) { + if ( *this == ev ) return *this; + + OPimRecord::operator=( ev ); + ev.data->ref(); + deref(); + data = ev.data; + + + return *this; +} +QString OEvent::description()const { + return data->description; +} +void OEvent::setDescription( const QString& description ) { + changeOrModify(); + data->description = description; +} +void OEvent::setLocation( const QString& loc ) { + changeOrModify(); + data->location = loc; +} +QString OEvent::location()const { + return data->location; +} +OPimNotifyManager &OEvent::notifiers() { + // I hope we can skip the changeOrModify here + // the notifier should take care of it + // and OPimNotify is shared too + if (!data->manager ) + data->manager = new OPimNotifyManager; + + return *data->manager; +} +bool OEvent::hasNotifiers()const { + return ( data->manager); +} +ORecur OEvent::recurrence()const { + if (!data->recur) + data->recur = new ORecur; + + return *data->recur; +} +void OEvent::setRecurrence( const ORecur& rec) { + changeOrModify(); + if (data->recur ) + (*data->recur) = rec; + else + data->recur = new ORecur( rec ); +} +bool OEvent::hasRecurrence()const { + return data->recur; +} +QString OEvent::note()const { + return data->note; +} +void OEvent::setNote( const QString& note ) { + changeOrModify(); + data->note = note; +} +QDateTime OEvent::createdDateTime()const { + return data->created; +} +void OEvent::setCreatedDateTime( const QDateTime& time ) { + changeOrModify(); + data->created = time; +} +QDateTime OEvent::startDateTime()const { + if ( data->isAllDay ) + return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); + return data->start; +} +QDateTime OEvent::startDateTimeInZone()const { + /* if no timezone, or all day event or if the current and this timeZone match... */ + if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); + + OTimeZone zone(data->timezone ); + return zone.toDateTime( data->start, OTimeZone::current() ); +} +void OEvent::setStartDateTime( const QDateTime& dt ) { + changeOrModify(); + data->start = dt; +} +QDateTime OEvent::endDateTime()const { + /* + * if all Day event the end time needs + * to be on the same day as the start + */ + if ( data->isAllDay ) + return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); + return data->end; +} +QDateTime OEvent::endDateTimeInZone()const { + /* if no timezone, or all day event or if the current and this timeZone match... */ + if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); + + OTimeZone zone(data->timezone ); + return zone.toDateTime( data->end, OTimeZone::current() ); +} +void OEvent::setEndDateTime( const QDateTime& dt ) { + changeOrModify(); + data->end = dt; +} +bool OEvent::isMultipleDay()const { + return data->end.date().day() - data->start.date().day(); +} +bool OEvent::isAllDay()const { + return data->isAllDay; +} +void OEvent::setTimeZone( const QString& tz ) { + changeOrModify(); + data->timezone = tz; +} +QString OEvent::timeZone()const { + return data->timezone; +} +bool OEvent::match( const QRegExp& )const { + // FIXME + return false; +} +QString OEvent::toRichText()const { + // FIXME + return "OEvent test"; +} +QString OEvent::toShortText()const { + return "OEvent shotText"; +} +QString OEvent::type()const { + return QString::fromLatin1("OEvent"); +} +QString OEvent::recordField( int /*id */ )const { + return QString::null; +} +int OEvent::rtti() { + return OPimResolver::DateBook; +} +bool OEvent::loadFromStream( QDataStream& ) { + return true; +} +bool OEvent::saveToStream( QDataStream& )const { + return true; +} +void OEvent::changeOrModify() { + if ( data->count != 1 ) { + data->deref(); + Data* d2 = new Data; + d2->description = data->description; + d2->location = data->location; + d2->manager = data->manager; + d2->recur = data->recur; + d2->note = data->note; + d2->created = data->created; + d2->start = data->start; + d2->end = data->end; + d2->isAllDay = data->isAllDay; + d2->timezone = data->timezone; + + data = d2; + } +} +void OEvent::deref() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +// FIXME +QMap<int, QString> OEvent::toMap()const { + return QMap<int, QString>(); +} +QMap<QString, QString> OEvent::toExtraMap()const { + return QMap<QString, QString>(); +} + + +struct OEffectiveEvent::Data : public QShared { + Data() : QShared() { + } + OEvent event; + QDate date; + QTime start, end; + QDate startDate, endDate; + bool dates : 1; +}; + +OEffectiveEvent::OEffectiveEvent() { + data = new Data; + data->date = QDate::currentDate(); + data->start = data->end = QTime::currentTime(); + data->dates = false; +} +OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, + Position pos ) { + data = new Data; + data->event = ev; + data->date = startDate; + if ( pos & Start ) + data->start = ev.startDateTime().time(); + else + data->start = QTime( 0, 0, 0 ); + + if ( pos & End ) + data->end = ev.endDateTime().time(); + else + data->end = QTime( 23, 59, 59 ); + + data->dates = false; +} +OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { + data = ev.data; + data->ref(); +} +OEffectiveEvent::~OEffectiveEvent() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { + if ( *this == ev ) return *this; + + ev.data->ref(); + deref(); + data = ev.data; + + return *this; +} + +void OEffectiveEvent::setStartTime( const QTime& ti) { + changeOrModify(); + data->start = ti; +} +void OEffectiveEvent::setEndTime( const QTime& en) { + changeOrModify(); + data->end = en; +} +void OEffectiveEvent::setEvent( const OEvent& ev) { + changeOrModify(); + data->event = ev; +} +void OEffectiveEvent::setDate( const QDate& da) { + changeOrModify(); + data->date = da; +} +void OEffectiveEvent::setEffectiveDates( const QDate& from, + const QDate& to ) { + if (!from.isValid() ) { + data->dates = false; + return; + } + + data->startDate = from; + data->endDate = to; +} +QString OEffectiveEvent::description()const { + return data->event.description(); +} +QString OEffectiveEvent::location()const { + return data->event.location(); +} +QString OEffectiveEvent::note()const { + return data->event.note(); +} +OEvent OEffectiveEvent::event()const { + return data->event; +} +QTime OEffectiveEvent::startTime()const { + return data->start; +} +QTime OEffectiveEvent::endTime()const { + return data->end; +} +QDate OEffectiveEvent::date()const { + return data->date; +} +int OEffectiveEvent::length()const { + return (data->end.hour() * 60 - data->start.hour() * 60) + + QABS(data->start.minute() - data->end.minute() ); +} +int OEffectiveEvent::size()const { + return ( data->end.hour() - data->start.hour() ) * 3600 + + (data->end.minute() - data->start.minute() * 60 + + data->end.second() - data->start.second() ); +} +QDate OEffectiveEvent::startDate()const { + if ( data->dates ) + return data->startDate; + else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer + return data->date; + else + return data->event.startDateTime().date(); +} +QDate OEffectiveEvent::endDate()const { + if ( data->dates ) + return data->endDate; + else if ( data->event.hasRecurrence() ) + return data->date; + else + return data->event.endDateTime().date(); +} +void OEffectiveEvent::deref() { + if ( data->deref() ) { + delete data; + data = 0; + } +} +void OEffectiveEvent::changeOrModify() { + if ( data->count != 1 ) { + data->deref(); + Data* d2 = new Data; + d2->event = data->event; + d2->date = data->date; + d2->start = data->start; + d2->end = data->end; + d2->startDate = data->startDate; + d2->endDate = data->endDate; + d2->dates = data->dates; + data = d2; + } +} +bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ + if ( data->date < e.date() ) + return TRUE; + if ( data->date == e.date() ) + return ( startTime() < e.startTime() ); + else + return FALSE; +} +bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ + return (data->date <= e.date() ); +} +bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { + return ( date() == e.date() + && startTime() == e.startTime() + && endTime()== e.endTime() + && event() == e.event() ); +} +bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { + return !(*this == e ); +} +bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { + return !(*this <= e ); +} +bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { + return !(*this < e); +} diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h new file mode 100644 index 0000000..4489be7 --- a/dev/null +++ b/libopie2/opiepim/oevent.h @@ -0,0 +1,198 @@ +// CONTAINS GPLed code of TT + +#ifndef OPIE_PIM_EVENT_H +#define OPIE_PIM_EVENT_H + +#include <qstring.h> +#include <qdatetime.h> +#include <qvaluelist.h> + +#include <qpe/recordfields.h> +#include <qpe/palmtopuidgen.h> + +#include "otimezone.h" +#include "opimrecord.h" + +namespace OCalendarHelper { + /** calculate the week number of the date */ + static int week( const QDate& ); + /** calculate the occurence of week days since the start of the month */ + static int ocurrence( const QDate& ); + + // returns the dayOfWeek for the *first* day it finds (ignores + // any further days!). Returns 1 (Monday) if there isn't any day found + static int dayOfWeek( char day ); + + /** returns the diff of month */ + static int monthDiff( const QDate& first, const QDate& second ); + +} + +class OPimNotifyManager; +class ORecur; +class OEvent : public OPimRecord { +public: + typedef QValueList<OEvent> ValueList; + enum RecordFields { + Uid = Qtopia::UID_ID, + Category = Qtopia::CATEGORY_ID, + Description, + Location, + Alarm, + Reminder, + Recurrence, + Note, + Created, + StartDate, + EndDate, + AllDay, + TimeZone + }; + + OEvent(int uid = 0); + OEvent( const OEvent& ); + ~OEvent(); + OEvent &operator=( const OEvent& ); + + QString description()const; + void setDescription( const QString& description ); + + QString location()const; + void setLocation( const QString& loc ); + + bool hasNotifiers()const; + OPimNotifyManager ¬ifiers(); + + ORecur recurrence()const; + void setRecurrence( const ORecur& ); + bool hasRecurrence()const; + + QString note()const; + void setNote( const QString& note ); + + + QDateTime createdDateTime()const; + void setCreatedDateTime( const QDateTime& dt); + + /** set the date to dt. dt is the QDateTime in localtime */ + void setStartDateTime( const QDateTime& ); + /** returns the datetime in the local timeZone */ + QDateTime startDateTime()const; + + /** returns the start datetime in the current zone */ + QDateTime startDateTimeInZone()const; + + /** in current timezone */ + void setEndDateTime( const QDateTime& ); + /** in current timezone */ + QDateTime endDateTime()const; + QDateTime endDateTimeInZone()const; + + bool isMultipleDay()const; + bool isAllDay()const; + void setAllDay( bool isAllDay ); + + /* pin this event to a timezone! FIXME */ + void setTimeZone( const QString& timeZone ); + QString timeZone()const; + + + bool match( const QRegExp& )const; + + + + + /* needed reimp */ + QString toRichText()const; + QString toShortText()const; + QString type()const; + + QMap<int, QString> toMap()const; + QMap<QString, QString> toExtraMap()const; + QString recordField(int )const; + + static int rtti(); + + bool loadFromStream( QDataStream& ); + bool saveToStream( QDataStream& )const; + +/* bool operator==( const OEvent& ); + bool operator!=( const OEvent& ); + bool operator<( const OEvent& ); + bool operator<=( const OEvent& ); + bool operator>( const OEvent& ); + bool operator>=(const OEvent& ); +*/ +private: + inline void changeOrModify(); + void deref(); + struct Data; + Data* data; + class Private; + Private* priv; + +}; + +/** + * AN Event can span through multiple days. We split up a multiday eve + */ + +class OEffectiveEvent { +public: + QValueList<OEffectiveEvent> ValueList; + enum Position { MidWay, Start, End, StartEnd }; + // If we calculate the effective event of a multi-day event + // we have to figure out whether we are at the first day, + // at the end, or anywhere else ("middle"). This is important + // for the start/end times (00:00/23:59) + // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- + // day event + // Start: start time -> 23:59 + // End: 00:00 -> end time + // Start | End == StartEnd: for single-day events (default) + // here we draw start time -> end time + OEffectiveEvent(); + OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); + OEffectiveEvent( const OEffectiveEvent& ); + OEffectiveEvent &operator=(const OEffectiveEvent& ); + ~OEffectiveEvent(); + + void setStartTime( const QTime& ); + void setEndTime( const QTime& ); + void setEvent( const OEvent& ); + void setDate( const QDate& ); + + void setEffectiveDates( const QDate& from, const QDate& to ); + + QString description()const; + QString location()const; + QString note()const; + OEvent event()const; + QTime startTime()const; + QTime endTime()const; + QDate date()const; + + /* return the length in hours */ + int length()const; + int size()const; + + QDate startDate()const; + QDate endDate()const; + + bool operator<( const OEffectiveEvent &e ) const; + bool operator<=( const OEffectiveEvent &e ) const; + bool operator==( const OEffectiveEvent &e ) const; + bool operator!=( const OEffectiveEvent &e ) const; + bool operator>( const OEffectiveEvent &e ) const; + bool operator>= ( const OEffectiveEvent &e ) const; + +private: + void deref(); + inline void changeOrModify(); + class Private; + Private* priv; + struct Data; + Data* data; + +}; +#endif diff --git a/libopie2/opiepim/otodo.cpp b/libopie2/opiepim/otodo.cpp index b4d4aa9..049359e 100644 --- a/libopie2/opiepim/otodo.cpp +++ b/libopie2/opiepim/otodo.cpp @@ -1,422 +1,424 @@ #include <qobject.h> #include <qshared.h> #include <qpe/palmtopuidgen.h> #include <qpe/stringutil.h> #include <qpe/palmtoprecord.h> #include <qpe/stringutil.h> #include <qpe/categories.h> #include <qpe/categoryselect.h> #include "opimstate.h" #include "orecur.h" #include "opimmaintainer.h" #include "opimnotifymanager.h" #include "opimresolver.h" #include "otodo.h" struct OTodo::OTodoData : public QShared { OTodoData() : QShared() { }; QDate date; bool isCompleted:1; bool hasDate:1; int priority; QString desc; QString sum; QMap<QString, QString> extra; ushort prog; OPimState state; ORecur recur; OPimMaintainer maintainer; QDate start; QDate completed; OPimNotifyManager notifiers; }; OTodo::OTodo(const OTodo &event ) : OPimRecord( event ), data( event.data ) { data->ref(); // qWarning("ref up"); } OTodo::~OTodo() { // qWarning("~OTodo " ); if ( data->deref() ) { // qWarning("OTodo::dereffing"); delete data; data = 0l; } } OTodo::OTodo(bool completed, int priority, const QArray<int> &category, const QString& summary, const QString &description, ushort progress, bool hasDate, QDate date, int uid ) : OPimRecord( uid ) { // qWarning("OTodoData " + summary); setCategories( category ); data = new OTodoData; data->date = date; data->isCompleted = completed; data->hasDate = hasDate; data->priority = priority; data->sum = summary; data->prog = progress; data->desc = Qtopia::simplifyMultiLineSpace(description ); } OTodo::OTodo(bool completed, int priority, const QStringList &category, const QString& summary, const QString &description, ushort progress, bool hasDate, QDate date, int uid ) : OPimRecord( uid ) { // qWarning("OTodoData" + summary); setCategories( idsFromString( category.join(";") ) ); data = new OTodoData; data->date = date; data->isCompleted = completed; data->hasDate = hasDate; data->priority = priority; data->sum = summary; data->prog = progress; data->desc = Qtopia::simplifyMultiLineSpace(description ); } bool OTodo::match( const QRegExp ®Exp )const { if( QString::number( data->priority ).find( regExp ) != -1 ){ return true; }else if( data->hasDate && data->date.toString().find( regExp) != -1 ){ return true; }else if(data->desc.find( regExp ) != -1 ){ return true; }else if(data->sum.find( regExp ) != -1 ) { return true; } return false; } bool OTodo::isCompleted() const { return data->isCompleted; } bool OTodo::hasDueDate() const { return data->hasDate; } bool OTodo::hasStartDate()const { return data->start.isValid(); } bool OTodo::hasCompletedDate()const { return data->completed.isValid(); } int OTodo::priority()const { return data->priority; } QString OTodo::summary() const { return data->sum; } ushort OTodo::progress() const { return data->prog; } QDate OTodo::dueDate()const { return data->date; } QDate OTodo::startDate()const { return data->start; } QDate OTodo::completedDate()const { return data->completed; } QString OTodo::description()const { return data->desc; } OPimState OTodo::state()const { return data->state; } ORecur OTodo::recurrence()const { return data->recur; } OPimMaintainer OTodo::maintainer()const { return data->maintainer; } void OTodo::setCompleted( bool completed ) { changeOrModify(); data->isCompleted = completed; } void OTodo::setHasDueDate( bool hasDate ) { changeOrModify(); data->hasDate = hasDate; } void OTodo::setDescription(const QString &desc ) { // qWarning( "desc " + desc ); changeOrModify(); data->desc = Qtopia::simplifyMultiLineSpace(desc ); } void OTodo::setSummary( const QString& sum ) { changeOrModify(); data->sum = sum; } void OTodo::setPriority(int prio ) { changeOrModify(); data->priority = prio; } void OTodo::setDueDate( const QDate& date ) { changeOrModify(); data->date = date; } void OTodo::setStartDate( const QDate& date ) { changeOrModify(); data->start = date; } void OTodo::setCompletedDate( const QDate& date ) { changeOrModify(); data->completed = date; } void OTodo::setState( const OPimState& state ) { changeOrModify(); data->state = state; } void OTodo::setRecurrence( const ORecur& rec) { changeOrModify(); data->recur = rec; } void OTodo::setMaintainer( const OPimMaintainer& pim ) { changeOrModify(); data->maintainer = pim; } bool OTodo::isOverdue( ) { if( data->hasDate && !data->isCompleted) return QDate::currentDate() > data->date; return false; } void OTodo::setProgress(ushort progress ) { changeOrModify(); data->prog = progress; } QString OTodo::toShortText() const { return summary(); } /*! Returns a richt text string */ QString OTodo::toRichText() const { QString text; QStringList catlist; // Description of the todo if ( !summary().isEmpty() ) { text += "<b>" + QObject::tr( "Summary:") + "</b><br>"; text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; } if( !description().isEmpty() ){ text += "<b>" + QObject::tr( "Description:" ) + "</b><br>"; text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) ; } text += "<br><br><br>"; text += "<b>" + QObject::tr( "Priority:") +" </b>" + QString::number( priority() ) + " <br>"; text += "<b>" + QObject::tr( "Progress:") + " </b>" + QString::number( progress() ) + " %<br>"; if (hasDueDate() ){ text += "<b>" + QObject::tr( "Deadline:") + " </b>"; text += dueDate().toString(); text += "<br>"; } text += "<b>" + QObject::tr( "Category:") + "</b> "; text += categoryNames( "Todo List" ).join(", "); text += "<br>"; return text; } OPimNotifyManager& OTodo::notifiers() { return data->notifiers; } bool OTodo::operator<( const OTodo &toDoEvent )const{ if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() < toDoEvent.priority(); }else{ return dueDate() < toDoEvent.dueDate(); } } return false; } bool OTodo::operator<=(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return true; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() <= toDoEvent.priority(); }else{ return dueDate() <= toDoEvent.dueDate(); } } return true; } bool OTodo::operator>(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() > toDoEvent.priority(); }else{ return dueDate() > toDoEvent.dueDate(); } } return false; } bool OTodo::operator>=(const OTodo &toDoEvent )const { if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; if( hasDueDate() && toDoEvent.hasDueDate() ){ if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide return priority() > toDoEvent.priority(); }else{ return dueDate() > toDoEvent.dueDate(); } } return true; } bool OTodo::operator==(const OTodo &toDoEvent )const { if ( data->priority != toDoEvent.data->priority ) return false; if ( data->priority != toDoEvent.data->prog ) return false; if ( data->isCompleted != toDoEvent.data->isCompleted ) return false; if ( data->hasDate != toDoEvent.data->hasDate ) return false; if ( data->date != toDoEvent.data->date ) return false; if ( data->sum != toDoEvent.data->sum ) return false; if ( data->desc != toDoEvent.data->desc ) return false; if ( data->maintainer != toDoEvent.data->maintainer ) return false; return OPimRecord::operator==( toDoEvent ); } void OTodo::deref() { // qWarning("deref in ToDoEvent"); if ( data->deref() ) { // qWarning("deleting"); delete data; data= 0; } } OTodo &OTodo::operator=(const OTodo &item ) { + if ( *this == item ) return *this; + OPimRecord::operator=( item ); //qWarning("operator= ref "); item.data->ref(); deref(); data = item.data; return *this; } QMap<int, QString> OTodo::toMap() const { QMap<int, QString> map; map.insert( Uid, QString::number( uid() ) ); map.insert( Category, idsToString( categories() ) ); map.insert( HasDate, QString::number( data->hasDate ) ); map.insert( Completed, QString::number( data->isCompleted ) ); map.insert( Description, data->desc ); map.insert( Summary, data->sum ); map.insert( Priority, QString::number( data->priority ) ); map.insert( DateDay, QString::number( data->date.day() ) ); map.insert( DateMonth, QString::number( data->date.month() ) ); map.insert( DateYear, QString::number( data->date.year() ) ); map.insert( Progress, QString::number( data->prog ) ); // map.insert( CrossReference, crossToString() ); /* FIXME!!! map.insert( State, ); map.insert( Recurrence, ); map.insert( Reminders, ); map. */ return map; } QMap<QString, QString> OTodo::toExtraMap()const { return data->extra; } /** * change or modify looks at the ref count and either * creates a new QShared Object or it can modify it * right in place */ void OTodo::changeOrModify() { if ( data->count != 1 ) { qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } // WATCHOUT /* * if you add something to the Data struct * be sure to copy it here */ void OTodo::copy( OTodoData* src, OTodoData* dest ) { dest->date = src->date; dest->isCompleted = src->isCompleted; dest->hasDate = src->hasDate; dest->priority = src->priority; dest->desc = src->desc; dest->sum = src->sum; dest->extra = src->extra; dest->prog = src->prog; dest->state = src->state; dest->recur = src->recur; dest->maintainer = src->maintainer; dest->start = src->start; dest->completed = src->completed; dest->notifiers = src->notifiers; } QString OTodo::type() const { return QString::fromLatin1("OTodo"); } QString OTodo::recordField(int /*id*/ )const { return QString::null; } int OTodo::rtti(){ return OPimResolver::TodoList; } |