author | eilers <eilers> | 2003-11-10 08:28:38 (UTC) |
---|---|---|
committer | eilers <eilers> | 2003-11-10 08:28:38 (UTC) |
commit | f3326a60ba002b420f33b6132dc1740c0fc4ffef (patch) (side-by-side diff) | |
tree | 6809f30857a241cf3334f7d25f60edc6fbb83901 /libopie | |
parent | efa3f9a756fb5a9afd0d35bc783e1331bf40bc6a (diff) | |
download | opie-f3326a60ba002b420f33b6132dc1740c0fc4ffef.zip opie-f3326a60ba002b420f33b6132dc1740c0fc4ffef.tar.gz opie-f3326a60ba002b420f33b6132dc1740c0fc4ffef.tar.bz2 |
Platform MacOS-X: Disable backtrce in odebug..
Libopie PIM: Finishing SQL-Backend for Todo. Recurrance events are supported now.
What is still missing: Custom entries currently not stored. It isn't easy to
implement them with enabled prefetch-cache.
LibopieDB2: Adding -lsqlite here instead linking it to libopie
-rw-r--r-- | libopie/libopie.pro | 2 | ||||
-rw-r--r-- | libopie/pim/orecur.cpp | 147 | ||||
-rw-r--r-- | libopie/pim/orecur.h | 12 | ||||
-rw-r--r-- | libopie/pim/otodoaccesssql.cpp | 31 |
4 files changed, 150 insertions, 42 deletions
diff --git a/libopie/libopie.pro b/libopie/libopie.pro index bf6b78f..94434ae 100644 --- a/libopie/libopie.pro +++ b/libopie/libopie.pro @@ -1,132 +1,132 @@ TEMPLATE = lib CONFIG += qte warn_on release HEADERS = ofontmenu.h \ ocolorbutton.h \ ofiledialog.h ofileselector.h \ ofileselector_p.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/oconversion.h \ pim/ocontact.h \ pim/ocontactfields.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 \ pim/odatebookaccess.h \ pim/odatebookaccessbackend.h \ pim/odatebookaccessbackend_xml.h \ orecurrancewidget.h \ oticker.h owait.h SOURCES = ofontmenu.cc \ ocolorbutton.cpp \ sharp_compat.cpp \ xmltree.cc \ ofiledialog.cc ofileselector.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/oconversion.cpp \ pim/ocontact.cpp \ pim/ocontactfields.cpp \ pim/ocontactaccess.cpp \ pim/ocontactaccessbackend_vcard.cpp \ pim/ocontactaccessbackend_xml.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 \ pim/odatebookaccess.cpp \ pim/odatebookaccessbackend.cpp \ pim/odatebookaccessbackend_xml.cpp \ orecurrancewidget.cpp \ oticker.cpp owait.cpp TARGET = opie INCLUDEPATH += $(OPIEDIR)/include DESTDIR = $(OPIEDIR)/lib$(PROJMAK) LIBS += -lqpe # Add SQL-Support if selected by config (eilers) CONFTEST = $$system( echo $CONFIG_SQL_PIM_BACKEND ) contains( CONFTEST, y ){ DEFINES += __USE_SQL -LIBS += -lopiedb2 -lsqlite +LIBS += -lopiedb2 HEADERS += pim/otodoaccesssql.h pim/ocontactaccessbackend_sql.h SOURCES += pim/otodoaccesssql.cpp pim/ocontactaccessbackend_sql.cpp } INTERFACES = otimepickerbase.ui orecurrancebase.ui TARGET = opie TRANSLATIONS = ../i18n/de/libopie.ts \ ../i18n/nl/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 ( big-screen/big-screen.pro ) include ( $(OPIEDIR)/include.pro ) diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp index eae1fdc..8c9ad46 100644 --- a/libopie/pim/orecur.cpp +++ b/libopie/pim/orecur.cpp @@ -1,510 +1,585 @@ #include <time.h> #include <qshared.h> #include <qtopia/timeconversion.h> #include "otimezone.h" #include "orecur.h" struct ORecur::Data : public QShared { Data() : QShared() { type = ORecur::NoRepeat; freq = -1; days = 0; pos = 0; create = QDateTime::currentDateTime(); hasEnd = FALSE; end = QDate::currentDate(); } char days; // Q_UINT8 for 8 seven days;) ORecur::RepeatType type; int freq; int pos; bool hasEnd : 1; 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 ) { bool stillLooking; stillLooking = p_nextOccurrence( from, next ); while ( stillLooking && data->list.contains(next) ) stillLooking = p_nextOccurrence( next.addDays(1), next ); return stillLooking; } bool ORecur::p_nextOccurrence( 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 data->end; } QDate ORecur::start()const{ return data->start; } 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 = dt; } 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; } } QString ORecur::toString()const { QString buf; + QMap<int, QString> recMap = toMap(); buf += " rtype=\""; - switch ( data->type ) { - case ORecur::Daily: - buf += "Daily"; - break; - case ORecur::Weekly: - buf += "Weekly"; - break; - case ORecur::MonthlyDay: - buf += "MonthlyDay"; - break; - case ORecur::MonthlyDate: - buf += "MonthlyDate"; - break; - case ORecur::Yearly: - buf += "Yearly"; - break; - default: - buf += "NoRepeat"; - break; - } + buf += recMap[ORecur::RType]; buf += "\""; if (data->days > 0 ) - buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\""; + buf += " rweekdays=\"" + recMap[ORecur::RWeekdays] + "\""; if ( data->pos != 0 ) - buf += " rposition=\"" + QString::number(data->pos ) + "\""; + buf += " rposition=\"" + recMap[ORecur::RPosition] + "\""; - buf += " rfreq=\"" + QString::number( data->freq ) + "\""; - buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\""; + buf += " rfreq=\"" + recMap[ORecur::RFreq] + "\""; + buf += " rhasenddate=\"" + recMap[ORecur::RHasEndDate]+ "\""; if ( data->hasEnd ) buf += " enddt=\"" - + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) + + recMap[ORecur::EndDate] + "\""; - buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\""; + buf += " created=\"" + recMap[ORecur::Created] + "\""; if ( data->list.isEmpty() ) return buf; - // save exceptions list here!! - ExceptionList::ConstIterator it; - ExceptionList list = data->list; buf += " exceptions=\""; - QDate date; - for ( it = list.begin(); it != list.end(); ++it ) { - date = (*it); - if ( it != list.begin() ) buf += " "; - - buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() ); - } + buf += recMap[ORecur::Exceptions]; buf += "\" "; return buf; } + +QString ORecur::rTypeString() const +{ + QString retString; + switch ( data->type ) { + case ORecur::Daily: + retString = "Daily"; + break; + case ORecur::Weekly: + retString = "Weekly"; + break; + case ORecur::MonthlyDay: + retString = "MonthlyDay"; + break; + case ORecur::MonthlyDate: + retString = "MonthlyDate"; + break; + case ORecur::Yearly: + retString = "Yearly"; + break; + default: + retString = "NoRepeat"; + break; + + } + + return retString; +} + +QMap<QString, ORecur::RepeatType> ORecur::rTypeValueConvertMap() const +{ + QMap<QString, RepeatType> convertMap; + + convertMap.insert( QString( "Daily" ), ORecur::Daily ); + convertMap.insert( QString( "Weekly" ), ORecur::Weekly ); + convertMap.insert( QString( "MonthlyDay" ), ORecur::MonthlyDay ); + convertMap.insert( QString( "MonthlyDate" ), ORecur::MonthlyDate ); + convertMap.insert( QString( "Yearly" ), ORecur::Yearly ); + convertMap.insert( QString( "NoRepeat" ), ORecur::NoRepeat ); + + return convertMap; +} + + +QMap<int, QString> ORecur::toMap() const +{ + QMap<int, QString> retMap; + + retMap.insert( ORecur::RType, rTypeString() ); + retMap.insert( ORecur::RWeekdays, QString::number( static_cast<int>( data->days ) ) ); + retMap.insert( ORecur::RPosition, QString::number(data->pos ) ); + retMap.insert( ORecur::RFreq, QString::number( data->freq ) ); + retMap.insert( ORecur::RHasEndDate, QString::number( static_cast<int>( data->hasEnd ) ) ); + if( data -> hasEnd ) + retMap.insert( ORecur::EndDate, QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) ); + retMap.insert( ORecur::Created, QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) ); + + if ( data->list.isEmpty() ) return retMap; + + // save exceptions list here!! + ExceptionList::ConstIterator it; + ExceptionList list = data->list; + QString exceptBuf; + QDate date; + for ( it = list.begin(); it != list.end(); ++it ) { + date = (*it); + if ( it != list.begin() ) exceptBuf += " "; + + exceptBuf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() ); + } + + retMap.insert( ORecur::Exceptions, exceptBuf ); + + return retMap; +} + +void ORecur::fromMap( const QMap<int, QString>& map ) +{ + QMap<QString, RepeatType> repTypeMap = rTypeValueConvertMap(); + + data -> type = repTypeMap[ map [ORecur::RType] ]; + data -> days = (char) map[ ORecur::RWeekdays ].toInt(); + data -> pos = map[ ORecur::RPosition ].toInt(); + data -> freq = map[ ORecur::RFreq ].toInt(); + data -> hasEnd= map[ ORecur::RHasEndDate ].toInt() ? true : false; + OTimeZone utc = OTimeZone::utc(); + if ( data -> hasEnd ){ + data -> end = utc.fromUTCDateTime( (time_t) map[ ORecur::EndDate ].toLong() ).date(); + } + data -> create = utc.fromUTCDateTime( (time_t) map[ ORecur::Created ].toLong() ).date(); + +#if 0 + // FIXME: Exceptions currently not supported... + // Convert the list of exceptions from QString into ExceptionList + data -> list.clear(); + QString exceptStr = map[ ORecur::Exceptions ]; + QStringList exceptList = QStringList::split( " ", exceptStr ); + ... +#endif + + +} diff --git a/libopie/pim/orecur.h b/libopie/pim/orecur.h index b214b3f..47901b0 100644 --- a/libopie/pim/orecur.h +++ b/libopie/pim/orecur.h @@ -1,91 +1,101 @@ /* * GPL from TT */ #ifndef OPIE_RECUR_H #define OPIE_RECUR_H #include <sys/types.h> #include <qdatetime.h> #include <qvaluelist.h> - +#include <qmap.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 }; + enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate, + EndDate, Created, Exceptions }; + 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; 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 setCreatedDateTime( const QDateTime& ); void setHasEndDate( bool b ); void setRepitition(int ); void setService( const QString& ser ); + + QMap<int, QString> toMap() const; + void fromMap( const QMap<int, QString>& map ); /* almost internal */ QString toString()const; private: bool p_nextOccurrence( const QDate& from, QDate& next ); void deref(); inline void checkOrModify(); + /* Converts rType to String */ + QString rTypeString() const; + /* Returns a map to convert Stringname for RType to RepeatType */ + QMap<QString, RepeatType> rTypeValueConvertMap() const; class Data; Data* data; class ORecurPrivate; ORecurPrivate *d; }; #endif diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp index ebd03bb..3913661 100644 --- a/libopie/pim/otodoaccesssql.cpp +++ b/libopie/pim/otodoaccesssql.cpp @@ -1,667 +1,690 @@ #include <qdatetime.h> #include <qpe/global.h> #include <opie2/osqldriver.h> #include <opie2/osqlresult.h> #include <opie2/osqlmanager.h> #include <opie2/osqlquery.h> #include "otodoaccesssql.h" #include "opimstate.h" #include "opimnotifymanager.h" #include "orecur.h" /* * first some query * CREATE query * LOAD query * INSERT * REMOVE * CLEAR */ namespace { /** * CreateQuery for the Todolist Table */ class CreateQuery : public OSQLQuery { public: CreateQuery(); ~CreateQuery(); QString query()const; }; /** * LoadQuery * this one queries for all uids */ class LoadQuery : public OSQLQuery { public: LoadQuery(); ~LoadQuery(); QString query()const; }; /** * inserts/adds a OTodo to the table */ class InsertQuery : public OSQLQuery { public: InsertQuery(const OTodo& ); ~InsertQuery(); QString query()const; private: OTodo m_todo; }; /** * removes one from the table */ class RemoveQuery : public OSQLQuery { public: RemoveQuery(int uid ); ~RemoveQuery(); QString query()const; private: int m_uid; }; /** * Clears (delete) a Table */ class ClearQuery : public OSQLQuery { public: ClearQuery(); ~ClearQuery(); QString query()const; }; /** * a find query */ class FindQuery : public OSQLQuery { public: FindQuery(int uid); FindQuery(const QArray<int>& ); ~FindQuery(); QString query()const; private: QString single()const; QString multi()const; QArray<int> m_uids; int m_uid; }; /** * overdue query */ class OverDueQuery : public OSQLQuery { public: OverDueQuery(); ~OverDueQuery(); QString query()const; }; class EffQuery : public OSQLQuery { public: EffQuery( const QDate&, const QDate&, bool inc ); ~EffQuery(); QString query()const; private: QString with()const; QString out()const; QDate m_start; QDate m_end; bool m_inc :1; }; CreateQuery::CreateQuery() : OSQLQuery() {} CreateQuery::~CreateQuery() {} QString CreateQuery::query()const { QString qu; qu += "create table todolist( uid PRIMARY KEY, categories, completed, "; qu += "description, summary, priority, DueDate, progress , state, "; - qu += "Recurrence, reminders, alarms, maintainer, startdate, completeddate);"; + // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers) + qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, "; + qu += "reminders, alarms, maintainer, startdate, completeddate);"; qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );"; return qu; } LoadQuery::LoadQuery() : OSQLQuery() {} LoadQuery::~LoadQuery() {} QString LoadQuery::query()const { QString qu; // We do not need "distinct" here. The primary key is always unique.. //qu += "select distinct uid from todolist"; qu += "select uid from todolist"; return qu; } InsertQuery::InsertQuery( const OTodo& todo ) : OSQLQuery(), m_todo( todo ) { } InsertQuery::~InsertQuery() { } /* * converts from a OTodo to a query * we leave out X-Ref + Alarms */ QString InsertQuery::query()const{ int year, month, day; year = month = day = 0; if (m_todo.hasDueDate() ) { QDate date = m_todo.dueDate(); year = date.year(); month = date.month(); day = date.day(); } int sYear = 0, sMonth = 0, sDay = 0; if( m_todo.hasStartDate() ){ QDate sDate = m_todo.startDate(); sYear = sDate.year(); sMonth= sDate.month(); sDay = sDate.day(); } int eYear = 0, eMonth = 0, eDay = 0; if( m_todo.hasCompletedDate() ){ QDate eDate = m_todo.completedDate(); eYear = eDate.year(); eMonth= eDate.month(); eDay = eDate.day(); } QString qu; + QMap<int, QString> recMap = m_todo.recurrence().toMap(); qu = "insert into todolist VALUES(" + QString::number( m_todo.uid() ) + "," + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + "," + QString::number( m_todo.isCompleted() ) + "," + "'" + m_todo.description() + "'" + "," + "'" + m_todo.summary() + "'" + "," + QString::number(m_todo.priority() ) + "," + "'" + QString::number(year) + "-" + QString::number(month) + "-" + QString::number( day ) + "'" + "," + QString::number( m_todo.progress() ) + "," + QString::number( m_todo.state().state() ) + "," - + "'" + m_todo.recurrence().toString() + "'"+ ","; + + "'" + recMap[ ORecur::RType ] + "'" + "," + + "'" + recMap[ ORecur::RWeekdays ] + "'" + "," + + "'" + recMap[ ORecur::RPosition ] + "'" + "," + + "'" + recMap[ ORecur::RFreq ] + "'" + "," + + "'" + recMap[ ORecur::RHasEndDate ] + "'" + "," + + "'" + recMap[ ORecur::EndDate ] + "'" + "," + + "'" + recMap[ ORecur::Created ] + "'" + "," + + "'" + recMap[ ORecur::Exceptions ] + "'" + ","; if ( m_todo.hasNotifiers() ) { OPimNotifyManager manager = m_todo.notifiers(); qu += "'" + manager.remindersToString() + "'" + "," + "'" + manager.alarmsToString() + "'" + ","; } else{ qu += QString( "''" ) + "," + "''" + ","; } qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !) + "'" + QString::number(sYear) + "-" + QString::number(sMonth) + "-" + QString::number(sDay) + "'" + "," + "'" + QString::number(eYear) + "-" + QString::number(eMonth) + "-"+QString::number(eDay) + "'" + ")"; qWarning("add %s", qu.latin1() ); return qu; } RemoveQuery::RemoveQuery(int uid ) : OSQLQuery(), m_uid( uid ) {} RemoveQuery::~RemoveQuery() {} QString RemoveQuery::query()const { QString qu = "DELETE from todolist where uid = " + QString::number(m_uid); return qu; } ClearQuery::ClearQuery() : OSQLQuery() {} ClearQuery::~ClearQuery() {} QString ClearQuery::query()const { QString qu = "drop table todolist"; return qu; } FindQuery::FindQuery(int uid) : OSQLQuery(), m_uid(uid ) { } FindQuery::FindQuery(const QArray<int>& ints) : OSQLQuery(), m_uids(ints){ } FindQuery::~FindQuery() { } QString FindQuery::query()const{ if (m_uids.count() == 0 ) return single(); else return multi(); } QString FindQuery::single()const{ QString qu = "select * from todolist where uid = " + QString::number(m_uid); return qu; } QString FindQuery::multi()const { QString qu = "select * from todolist where "; for (uint i = 0; i < m_uids.count(); i++ ) { qu += " UID = " + QString::number( m_uids[i] ) + " OR"; } qu.remove( qu.length()-2, 2 ); return qu; } OverDueQuery::OverDueQuery(): OSQLQuery() {} OverDueQuery::~OverDueQuery() {} QString OverDueQuery::query()const { QDate date = QDate::currentDate(); QString str; str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() ); return str; } EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc ) : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {} EffQuery::~EffQuery() {} QString EffQuery::query()const { return m_inc ? with() : out(); } QString EffQuery::with()const { QString str; str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ") .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() ) .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() ); return str; } QString EffQuery::out()const { QString str; str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); return str; } }; OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) : OTodoAccessBackend(), m_dict(15), m_dirty(true) { QString fi = file; if ( fi.isEmpty() ) fi = Global::applicationFileName( "todolist", "todolist.db" ); OSQLManager man; m_driver = man.standard(); m_driver->setUrl(fi); // fillDict(); } OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ } bool OTodoAccessBackendSQL::load(){ if (!m_driver->open() ) return false; CreateQuery creat; OSQLResult res = m_driver->query(&creat ); m_dirty = true; return true; } bool OTodoAccessBackendSQL::reload(){ return load(); } bool OTodoAccessBackendSQL::save(){ return m_driver->close(); } QArray<int> OTodoAccessBackendSQL::allRecords()const { if (m_dirty ) update(); return m_uids; } QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){ QArray<int> ints(0); return ints; } OTodo OTodoAccessBackendSQL::find(int uid ) const{ FindQuery query( uid ); return todo( m_driver->query(&query) ); } OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, uint cur, Frontend::CacheDirection dir ) const{ uint CACHE = readAhead(); qWarning("searching for %d", uid ); QArray<int> search( CACHE ); uint size =0; OTodo to; // we try to cache CACHE items switch( dir ) { /* forward */ case 0: // FIXME: Not a good style to use magic numbers here (eilers) for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { qWarning("size %d %d", size, ints[i] ); search[size] = ints[i]; size++; } break; /* reverse */ case 1: // FIXME: Not a good style to use magic numbers here (eilers) for (uint i = cur; i != 0 && size < CACHE; i-- ) { search[size] = ints[i]; size++; } break; } search.resize( size ); FindQuery query( search ); OSQLResult res = m_driver->query( &query ); if ( res.state() != OSQLResult::Success ) return to; return todo( res ); } void OTodoAccessBackendSQL::clear() { ClearQuery cle; OSQLResult res = m_driver->query( &cle ); CreateQuery qu; res = m_driver->query(&qu); } bool OTodoAccessBackendSQL::add( const OTodo& t) { InsertQuery ins( t ); OSQLResult res = m_driver->query( &ins ); if ( res.state() == OSQLResult::Failure ) return false; int c = m_uids.count(); m_uids.resize( c+1 ); m_uids[c] = t.uid(); return true; } bool OTodoAccessBackendSQL::remove( int uid ) { RemoveQuery rem( uid ); OSQLResult res = m_driver->query(&rem ); if ( res.state() == OSQLResult::Failure ) return false; m_dirty = true; return true; } /* * FIXME better set query * but we need the cache for that * now we remove */ bool OTodoAccessBackendSQL::replace( const OTodo& t) { remove( t.uid() ); bool b= add(t); m_dirty = false; // we changed some stuff but the UID stayed the same return b; } QArray<int> OTodoAccessBackendSQL::overDue() { OverDueQuery qu; return uids( m_driver->query(&qu ) ); } QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s, const QDate& t, bool u) { EffQuery ef(s, t, u ); return uids (m_driver->query(&ef) ); } /* * */ QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder, int sortFilter, int cat ) { qWarning("sorted %d, %d", asc, sortOrder ); QString query; query = "select uid from todolist WHERE "; /* * Sort Filter stuff * not that straight forward * FIXME: Replace magic numbers * */ /* Category */ if ( sortFilter & 1 ) { QString str; if (cat != 0 ) str = QString::number( cat ); query += " categories like '%" +str+"%' AND"; } /* Show only overdue */ if ( sortFilter & 2 ) { QDate date = QDate::currentDate(); QString due; QString base; base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() ); query += " " + base + " AND"; } /* not show completed */ if ( sortFilter & 4 ) { query += " completed = 0 AND"; }else{ query += " ( completed = 1 OR completed = 0) AND"; } /* srtip the end */ query = query.remove( query.length()-3, 3 ); /* * sort order stuff * quite straight forward */ query += "ORDER BY "; switch( sortOrder ) { /* completed */ case 0: query += "completed"; break; case 1: query += "priority"; break; case 2: query += "summary"; break; case 3: query += "DueDate"; break; } if ( !asc ) { qWarning("not ascending!"); query += " DESC"; } qWarning( query ); OSQLRawQuery raw(query ); return uids( m_driver->query(&raw) ); } bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{ if ( str == "0-0-0" ) return false; else{ int day, year, month; QStringList list = QStringList::split("-", str ); year = list[0].toInt(); month = list[1].toInt(); day = list[2].toInt(); da.setYMD( year, month, day ); return true; } } OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{ if ( res.state() == OSQLResult::Failure ) { OTodo to; return to; } OSQLResultItem::ValueList list = res.results(); OSQLResultItem::ValueList::Iterator it = list.begin(); qWarning("todo1"); OTodo to = todo( (*it) ); cache( to ); ++it; for ( ; it != list.end(); ++it ) { qWarning("caching"); cache( todo( (*it) ) ); } return to; } OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const { qWarning("todo"); bool hasDueDate = false; QDate dueDate = QDate::currentDate(); hasDueDate = date( dueDate, item.data("DueDate") ); QStringList cats = QStringList::split(";", item.data("categories") ); + qWarning("Item is completed: %d", item.data("completed").toInt() ); + OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(), cats, item.data("summary"), item.data("description"), item.data("progress").toUShort(), hasDueDate, dueDate, item.data("uid").toInt() ); bool isOk; int prioInt = QString( item.data("priority") ).toInt( &isOk ); if ( isOk ) to.setPriority( prioInt ); bool hasStartDate = false; QDate startDate = QDate::currentDate(); hasStartDate = date( startDate, item.data("startdate") ); bool hasCompletedDate = false; QDate completedDate = QDate::currentDate(); hasCompletedDate = date( completedDate, item.data("completeddate") ); if ( hasStartDate ) to.setStartDate( startDate ); if ( hasCompletedDate ) to.setCompletedDate( completedDate ); OPimNotifyManager& manager = to.notifiers(); manager.alarmsFromString( item.data("alarms") ); manager.remindersFromString( item.data("reminders") ); OPimState pimState; pimState.setState( QString( item.data("state") ).toInt() ); to.setState( pimState ); - // Recurrence not supported yet - // to.setRecurrence( + QMap<int, QString> recMap; + recMap.insert( ORecur::RType , item.data("RType") ); + recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") ); + recMap.insert( ORecur::RPosition , item.data("RPosition") ); + recMap.insert( ORecur::RFreq , item.data("RFreq") ); + recMap.insert( ORecur::RHasEndDate, item.data("RHasEndDate") ); + recMap.insert( ORecur::EndDate , item.data("EndDate") ); + recMap.insert( ORecur::Created , item.data("Created") ); + recMap.insert( ORecur::Exceptions , item.data("Exceptions") ); + + ORecur recur; + recur.fromMap( recMap ); + to.setRecurrence( recur ); return to; } OTodo OTodoAccessBackendSQL::todo( int uid )const { FindQuery find( uid ); return todo( m_driver->query(&find) ); } /* * update the dict */ void OTodoAccessBackendSQL::fillDict() { /* initialize dict */ /* * UPDATE dict if you change anything!!! * FIXME: Isn't this dict obsolete ? (eilers) */ m_dict.setAutoDelete( TRUE ); m_dict.insert("Categories" , new int(OTodo::Category) ); m_dict.insert("Uid" , new int(OTodo::Uid) ); m_dict.insert("HasDate" , new int(OTodo::HasDate) ); m_dict.insert("Completed" , new int(OTodo::Completed) ); m_dict.insert("Description" , new int(OTodo::Description) ); m_dict.insert("Summary" , new int(OTodo::Summary) ); m_dict.insert("Priority" , new int(OTodo::Priority) ); m_dict.insert("DateDay" , new int(OTodo::DateDay) ); m_dict.insert("DateMonth" , new int(OTodo::DateMonth) ); m_dict.insert("DateYear" , new int(OTodo::DateYear) ); m_dict.insert("Progress" , new int(OTodo::Progress) ); m_dict.insert("Completed", new int(OTodo::Completed) ); // Why twice ? (eilers) m_dict.insert("CrossReference", new int(OTodo::CrossReference) ); // m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); // old stuff (eilers) // m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); // old stuff (eilers) } /* * need to be const so let's fool the * compiler :( */ void OTodoAccessBackendSQL::update()const { ((OTodoAccessBackendSQL*)this)->m_dirty = false; LoadQuery lo; OSQLResult res = m_driver->query(&lo); if ( res.state() != OSQLResult::Success ) return; ((OTodoAccessBackendSQL*)this)->m_uids = uids( res ); } QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{ OSQLResultItem::ValueList list = res.results(); OSQLResultItem::ValueList::Iterator it; QArray<int> ints(list.count() ); qWarning(" count = %d", list.count() ); int i = 0; for (it = list.begin(); it != list.end(); ++it ) { ints[i] = (*it).data("uid").toInt(); i++; } return ints; } QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const { #warning OTodoAccessBackendSQL::matchRegexp() not implemented !! #if 0 Copied from xml-backend by not adapted to sql (eilers) QArray<int> m_currentQuery( m_events.count() ); uint arraycounter = 0; QMap<int, OTodo>::ConstIterator it; for (it = m_events.begin(); it != m_events.end(); ++it ) { if ( it.data().match( r ) ) m_currentQuery[arraycounter++] = it.data().uid(); } // Shrink to fit.. m_currentQuery.resize(arraycounter); return m_currentQuery; #endif QArray<int> empty; return empty; } QBitArray OTodoAccessBackendSQL::supports()const { return sup(); } QBitArray OTodoAccessBackendSQL::sup() const{ QBitArray ar( OTodo::CompletedDate + 1 ); ar.fill( true ); ar[OTodo::CrossReference] = false; ar[OTodo::State ] = false; ar[OTodo::Reminders] = false; ar[OTodo::Notifiers] = false; ar[OTodo::Maintainer] = false; return ar; } void OTodoAccessBackendSQL::removeAllCompleted(){ #warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !! } |