summaryrefslogtreecommitdiff
path: root/libopie2/opiepim/backend
Side-by-side diff
Diffstat (limited to 'libopie2/opiepim/backend') (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp63
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.h2
2 files changed, 43 insertions, 22 deletions
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index 107c178..0f99d50 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -67,144 +67,153 @@ char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
if (!needle || !haystack || !hLen || !nLen)
return 0;
const char* hsearch = haystack;
if ((needleChar = *needle++) != 0) {
nLen--; //(to make up for needle++)
do {
do {
if ((haystackChar = *hsearch++) == 0)
return (0);
if (hsearch >= haystack + hLen)
return (0);
} while (haystackChar != needleChar);
} while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
hsearch--;
}
return ((char *)hsearch);
}
}
namespace {
time_t start, end, created, rp_end;
OPimRecurrence* rec;
- OPimRecurrence* recur() {
+ static OPimRecurrence* recur() {
if (!rec)
rec = new OPimRecurrence;
return rec;
}
int alarmTime;
int snd;
enum Attribute{
FDescription = 0,
FLocation,
FCategories,
FUid,
FType,
FAlarm,
FSound,
FRType,
FRWeekdays,
FRPosition,
FRFreq,
FRHasEndDate,
FREndDate,
FRStart,
FREnd,
FNote,
FCreated, // Should't this be called FRCreated ?
FTimeZone,
FRecParent,
FRecChildren,
FExceptions
};
// FIXME: Use OPimEvent::toMap() here !! (eilers)
- inline void save( const OPimEvent& ev, QString& buf ) {
+ static void save( const OPimEvent& ev, QString& buf ) {
owarn << "Saving " << ev.uid() << " " << ev.description() << "" << oendl;
buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
if (!ev.location().isEmpty() )
buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
+ if (!ev.categories().isEmpty() )
buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
+
buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
if (ev.isAllDay() )
buf += " type=\"AllDay\""; // is that all ?? (eilers)
if (ev.hasNotifiers() ) {
OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
if ( alarm.sound() == OPimAlarm::Loud )
buf += "loud";
else
buf += "silent";
buf += "\"";
}
if ( ev.hasRecurrence() ) {
buf += ev.recurrence().toString();
}
/*
* fscking timezones :) well, we'll first convert
* the QDateTime to a QDateTime in UTC time
* and then we'll create a nice time_t
*/
- OPimTimeZone zone( ev.timeZone().isEmpty() ? OPimTimeZone::current() : ev.timeZone() );
- buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OPimTimeZone::utc() ) ) ) + "\"";
- buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OPimTimeZone::utc() ) ) ) + "\"";
+ OPimTimeZone zone( (ev.timeZone().isEmpty()||ev.isAllDay()) ? OPimTimeZone::utc() : OPimTimeZone::current() );
+ buf += " start=\"" + QString::number( zone.fromDateTime( ev.startDateTime())) + "\"";
+ buf += " end=\"" + QString::number( zone.fromDateTime( ev.endDateTime() )) + "\"";
if (!ev.note().isEmpty() ) {
buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
}
+ /*
+ * Don't save a timezone if AllDay Events
+ * as they're UTC only anyway
+ */
+ if (!ev.isAllDay() ) {
+
buf += " timezone=\"";
if ( ev.timeZone().isEmpty() )
buf += "None";
else
buf += ev.timeZone();
buf += "\"";
+ }
if (ev.parent() != 0 ) {
buf += " recparent=\""+QString::number(ev.parent() )+"\"";
}
if (ev.children().count() != 0 ) {
QArray<int> children = ev.children();
buf += " recchildren=\"";
for ( uint i = 0; i < children.count(); i++ ) {
if ( i != 0 ) buf += " ";
buf += QString::number( children[i] );
}
buf+= "\"";
}
// skip custom writing
}
- inline bool forAll( const QMap<int, OPimEvent>& list, QFile& file ) {
+ static bool saveEachEvent( const QMap<int, OPimEvent>& list, QFile& file ) {
QMap<int, OPimEvent>::ConstIterator it;
QString buf;
QCString str;
int total_written;
for ( it = list.begin(); it != list.end(); ++it ) {
buf = "<event";
save( it.data(), buf );
buf += " />\n";
str = buf.utf8();
total_written = file.writeBlock(str.data(), str.length() );
if ( total_written != int(str.length() ) )
return false;
}
return true;
}
}
namespace Opie {
ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
const QString& fileName )
: ODateBookAccessBackend() {
m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
m_changed = false;
@@ -217,54 +226,54 @@ bool ODateBookAccessBackend_XML::load() {
bool ODateBookAccessBackend_XML::reload() {
clear();
return load();
}
bool ODateBookAccessBackend_XML::save() {
if (!m_changed) return true;
int total_written;
QString strFileNew = m_name + ".new";
QFile f( strFileNew );
if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
buf += "<events>\n";
QCString str = buf.utf8();
total_written = f.writeBlock( str.data(), str.length() );
if ( total_written != int(str.length() ) ) {
f.close();
QFile::remove( strFileNew );
return false;
}
- if (!forAll( m_raw, f ) ) {
+ if (!saveEachEvent( m_raw, f ) ) {
f.close();
QFile::remove( strFileNew );
return false;
}
- if (!forAll( m_rep, f ) ) {
+ if (!saveEachEvent( m_rep, f ) ) {
f.close();
QFile::remove( strFileNew );
return false;
}
buf = "</events>\n</DATEBOOK>\n";
str = buf.utf8();
total_written = f.writeBlock( str.data(), str.length() );
if ( total_written != int(str.length() ) ) {
f.close();
QFile::remove( strFileNew );
return false;
}
f.close();
if ( ::rename( strFileNew, m_name ) < 0 ) {
QFile::remove( strFileNew );
return false;
}
m_changed = false;
return true;
}
QArray<int> ODateBookAccessBackend_XML::allRecords()const {
@@ -385,48 +394,52 @@ bool ODateBookAccessBackend_XML::loadFile() {
QAsciiDict<int> dict(FExceptions+1);
dict.setAutoDelete( true );
dict.insert( "description", new int(FDescription) );
dict.insert( "location", new int(FLocation) );
dict.insert( "categories", new int(FCategories) );
dict.insert( "uid", new int(FUid) );
dict.insert( "type", new int(FType) );
dict.insert( "alarm", new int(FAlarm) );
dict.insert( "sound", new int(FSound) );
dict.insert( "rtype", new int(FRType) );
dict.insert( "rweekdays", new int(FRWeekdays) );
dict.insert( "rposition", new int(FRPosition) );
dict.insert( "rfreq", new int(FRFreq) );
dict.insert( "rhasenddate", new int(FRHasEndDate) );
dict.insert( "enddt", new int(FREndDate) );
dict.insert( "start", new int(FRStart) );
dict.insert( "end", new int(FREnd) );
dict.insert( "note", new int(FNote) );
dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
dict.insert( "recparent", new int(FRecParent) );
dict.insert( "recchildren", new int(FRecChildren) );
dict.insert( "exceptions", new int(FExceptions) );
dict.insert( "timezone", new int(FTimeZone) );
+
+ // initialiaze db hack
+ m_noTimeZone = true;
+
char* dt = (char*)map_addr;
int len = attribute.st_size;
int i = 0;
char* point;
const char* collectionString = "<event ";
int strLen = ::strlen(collectionString);
int *find;
while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
i = point -dt;
i+= strLen;
alarmTime = -1;
snd = 0; // silent
OPimEvent ev;
rec = 0;
while ( TRUE ) {
while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
++i;
if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
break;
@@ -458,118 +471,123 @@ bool ODateBookAccessBackend_XML::loadFile() {
continue;
}
QCString value( dt+i, j-i+1 );
i = j + 1;
QString str = (haveUtf ? QString::fromUtf8( value )
: QString::fromLatin1( value ) );
if ( haveEnt )
str = Qtopia::plainString( str );
/*
* add key + value
*/
find = dict[attr.data()];
if (!find)
ev.setCustomField( attr, str );
else {
setField( ev, *find, str );
}
}
/* time to finalize */
finalizeRecord( ev );
delete rec;
+ m_noTimeZone = true;
}
::munmap(map_addr, attribute.st_size );
m_changed = false; // changed during add
return true;
}
// FIXME: Use OPimEvent::fromMap() which makes this obsolete.. (eilers)
void ODateBookAccessBackend_XML::finalizeRecord( OPimEvent& ev ) {
+
+ /*
+ * quirk to import datebook files. They normally don't have a
+ * timeZone attribute and we treat this as to use OPimTimeZone::current()
+ */
+ if (m_noTimeZone )
+ ev.setTimeZone( OPimTimeZone::current().timeZone() );
+
+
+
/* AllDay is alway in UTC */
if ( ev.isAllDay() ) {
OPimTimeZone utc = OPimTimeZone::utc();
- ev.setStartDateTime( utc.fromUTCDateTime( start ) );
- ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
- ev.setTimeZone( "UTC"); // make sure it is really utc
+ ev.setStartDateTime( utc.toDateTime( start ) );
+ ev.setEndDateTime ( utc.toDateTime( end ) );
}else {
/* to current date time */
- // owarn << " Start is " << start << "" << oendl;
- OPimTimeZone zone( ev.timeZone().isEmpty() ? OPimTimeZone::current() : ev.timeZone() );
- QDateTime date = zone.toDateTime( start );
- owarn << " Start is " << date.toString() << "" << oendl;
- ev.setStartDateTime( zone.toDateTime( date, OPimTimeZone::current() ) );
+ OPimTimeZone to_zone( ev.timeZone().isEmpty() ? OPimTimeZone::utc() : OPimTimeZone::current() );
- date = zone.toDateTime( end );
- ev.setEndDateTime ( zone.toDateTime( date, OPimTimeZone::current() ) );
+ ev.setStartDateTime(to_zone.toDateTime( start));
+ ev.setEndDateTime (to_zone.toDateTime( end));
}
if ( rec && rec->doesRecur() ) {
OPimTimeZone utc = OPimTimeZone::utc();
OPimRecurrence recu( *rec ); // call copy c'tor;
- recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
- recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
+ recu.setEndDate ( utc.toDateTime( rp_end ).date() );
+ recu.setCreatedDateTime( utc.toDateTime( created ) );
recu.setStart( ev.startDateTime().date() );
ev.setRecurrence( recu );
}
if (alarmTime != -1 ) {
QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
OPimAlarm al( snd , dt );
ev.notifiers().add( al );
}
if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
owarn << "already contains assign uid" << oendl;
ev.setUid( 1 );
}
- owarn << "addind " << ev.uid() << " " << ev.description() << "" << oendl;
+
if ( ev.hasRecurrence() )
m_rep.insert( ev.uid(), ev );
else
m_raw.insert( ev.uid(), ev );
}
void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString& value) {
// owarn << " setting " << value << "" << oendl;
switch( id ) {
case FDescription:
e.setDescription( value );
break;
case FLocation:
e.setLocation( value );
break;
case FCategories:
e.setCategories( e.idsFromString( value ) );
break;
case FUid:
e.setUid( value.toInt() );
break;
case FType:
if ( value == "AllDay" ) {
e.setAllDay( true );
- e.setTimeZone( "UTC" );
}
break;
case FAlarm:
alarmTime = value.toInt();
break;
case FSound:
snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
break;
// recurrence stuff
case FRType:
if ( value == "Daily" )
recur()->setType( OPimRecurrence::Daily );
else if ( value == "Weekly" )
recur()->setType( OPimRecurrence::Weekly);
else if ( value == "MonthlyDay" )
recur()->setType( OPimRecurrence::MonthlyDay );
else if ( value == "MonthlyDate" )
recur()->setType( OPimRecurrence::MonthlyDate );
else if ( value == "Yearly" )
recur()->setType( OPimRecurrence::Yearly );
else
recur()->setType( OPimRecurrence::NoRepeat );
break;
case FRWeekdays:
@@ -601,48 +619,49 @@ void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString&
break;
case FCreated:
created = value.toInt();
break;
case FRecParent:
e.setParent( value.toInt() );
break;
case FRecChildren:{
QStringList list = QStringList::split(' ', value );
for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
e.addChild( (*it).toInt() );
}
}
break;
case FExceptions:{
QStringList list = QStringList::split(' ', value );
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
owarn << "adding exception " << date.toString() << "" << oendl;
recur()->exceptions().append( date );
}
}
break;
case FTimeZone:
+ m_noTimeZone = false;
if ( value != "None" )
e.setTimeZone( value );
break;
default:
break;
}
}
QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
{
QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
uint arraycounter = 0;
QMap<int, OPimEvent>::ConstIterator it;
for ( it = m_raw.begin(); it != m_raw.end(); ++it )
if ( it.data().match( r ) )
m_currentQuery[arraycounter++] = it.data().uid();
for ( it = m_rep.begin(); it != m_rep.end(); ++it )
if ( it.data().match( r ) )
m_currentQuery[arraycounter++] = it.data().uid();
// Shrink to fit..
m_currentQuery.resize(arraycounter);
return m_currentQuery;
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
index 6823ce6..af5b114 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
@@ -47,40 +47,42 @@ public:
~ODateBookAccessBackend_XML();
bool load();
bool reload();
bool save();
QArray<int> allRecords()const;
QArray<int> matchRegexp(const QRegExp &r) const;
QArray<int> queryByExample( const OPimEvent&, int, const QDateTime& d = QDateTime() );
OPimEvent find( int uid )const;
void clear();
bool add( const OPimEvent& ev );
bool remove( int uid );
bool replace( const OPimEvent& ev );
QArray<UID> rawEvents()const;
QArray<UID> rawRepeats()const;
QArray<UID> nonRepeats()const;
OPimEvent::ValueList directNonRepeats();
OPimEvent::ValueList directRawRepeats();
private:
bool m_changed :1 ;
+ bool m_noTimeZone : 1;
+
bool loadFile();
inline void finalizeRecord( OPimEvent& ev );
inline void setField( OPimEvent&, int field, const QString& val );
QString m_name;
QMap<int, OPimEvent> m_raw;
QMap<int, OPimEvent> m_rep;
struct Data;
Data* data;
class Private;
Private *d;
};
}
#endif