31 files changed, 1207 insertions, 98 deletions
diff --git a/libopie2/opiepim/backend/otodoaccessbackend.h b/libopie2/opiepim/backend/otodoaccessbackend.h index 3bad6b7..7944a2c 100644 --- a/libopie2/opiepim/backend/otodoaccessbackend.h +++ b/libopie2/opiepim/backend/otodoaccessbackend.h @@ -1,20 +1,21 @@ #ifndef OPIE_TODO_ACCESS_BACKEND_H #define OPIE_TODO_ACCESS_BACKEND_H #include "otodo.h" #include "opimaccessbackend.h" class OTodoAccessBackend : public OPimAccessBackend<OTodo> { public: OTodoAccessBackend(); ~OTodoAccessBackend(); virtual QArray<int> effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ) = 0; virtual QArray<int> overDue() = 0; virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ) = 0; + virtual void removeAllCompleted() = 0; }; #endif diff --git a/libopie2/opiepim/backend/otodoaccessvcal.cpp b/libopie2/opiepim/backend/otodoaccessvcal.cpp index ac70ea0..e96cc3c 100644 --- a/libopie2/opiepim/backend/otodoaccessvcal.cpp +++ b/libopie2/opiepim/backend/otodoaccessvcal.cpp @@ -1,192 +1,198 @@ #include <qfile.h> #include <qtopia/private/vobject_p.h> #include <qtopia/timeconversion.h> #include <qtopia/private/qfiledirect_p.h> #include "otodoaccessvcal.h" namespace { static OTodo eventByVObj( VObject *obj ){ OTodo 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.setHasDueDate( true ); name = vObjectStringZValue( ob ); event.setDueDate( TimeConversion::fromISO8601( name).date() ); } // categories if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){ name = vObjectStringZValue( ob ); qWarning("Categories:%s", name.data() ); } event.setUid( 1 ); return event; }; static VObject *vobjByEvent( const OTodo &event ) { VObject *task = newVObject( VCTodoProp ); if( task == 0 ) return 0l; if( event.hasDueDate() ) addPropValue( task, VCDueProp, TimeConversion::toISO8601( event.dueDate() ) ); if( event.isCompleted() ) addPropValue( task, VCStatusProp, "COMPLETED"); QString string = QString::number(event.priority() ); addPropValue( task, VCPriorityProp, string.local8Bit() ); addPropValue( task, VCCategoriesProp, event.idsToString( event.categories() ).local8Bit() ); addPropValue( task, VCDescriptionProp, event.description().local8Bit() ); addPropValue( task, VCSummaryProp, event.summary().local8Bit() ); return task; }; } OTodoAccessVCal::OTodoAccessVCal( const QString& path ) : m_dirty(false), m_file( path ) { } OTodoAccessVCal::~OTodoAccessVCal() { } bool OTodoAccessVCal::load() { m_map.clear(); m_dirty = false; VObject* vcal = 0l; vcal = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); if (!vcal ) return false; // Iterate over the list VObjectIterator it; VObject* vobj; initPropIterator(&it, vcal); while( moreIteration( &it ) ) { vobj = ::nextVObject( &it ); QCString name = ::vObjectName( vobj ); if( name == VCTodoProp ){ OTodo to = eventByVObj( vobj ); m_map.insert( to.uid(), to ); } } // Should I do a delete vcal? return true; } bool OTodoAccessVCal::reload() { return load(); } bool OTodoAccessVCal::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, OTodo>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ vo = vobjByEvent( it.data() ); addVObjectProp(obj, vo ); } writeVObject( file.directHandle(), obj ); cleanVObject( obj ); cleanStrTbl(); m_dirty = false; return true; } void OTodoAccessVCal::clear() { m_map.clear(); m_dirty = true; } bool OTodoAccessVCal::add( const OTodo& to ) { m_map.insert( to.uid(), to ); m_dirty = true; return true; } bool OTodoAccessVCal::remove( int uid ) { m_map.remove( uid ); m_dirty = true; return true; } +void OTodoAccessVCal::removeAllCompleted() { + for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) { + if ( (*it).isCompleted() ) + m_map.remove( it ); + } +} bool OTodoAccessVCal::replace( const OTodo& to ) { m_map.replace( to.uid(), to ); m_dirty = true; return true; } OTodo OTodoAccessVCal::find(int uid )const { return m_map[uid]; } QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::allRecords()const { QArray<int> ar( m_map.count() ); QMap<int, OTodo>::ConstIterator it; int i = 0; for ( it = m_map.begin(); it != m_map.end(); ++it ) { ar[i] = it.key(); i++; } return ar; } QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& , const QDate& , bool ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::overDue() { QArray<int> ar(0); return ar; } diff --git a/libopie2/opiepim/backend/otodoaccessvcal.h b/libopie2/opiepim/backend/otodoaccessvcal.h index 4499a7e..452f602 100644 --- a/libopie2/opiepim/backend/otodoaccessvcal.h +++ b/libopie2/opiepim/backend/otodoaccessvcal.h @@ -1,35 +1,37 @@ #ifndef OPIE_OTODO_ACCESS_VCAL_H #define OPIE_OTODO_ACCESS_VCAL_H #include "otodoaccessbackend.h" class OTodoAccessVCal : public OTodoAccessBackend { public: OTodoAccessVCal(const QString& ); ~OTodoAccessVCal(); bool load(); bool reload(); bool save(); QArray<int> allRecords()const; QArray<int> queryByExample( const OTodo& t, int sort ); QArray<int> effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ); QArray<int> overDue(); QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ); OTodo find(int uid)const; void clear(); bool add( const OTodo& ); bool remove( int uid ); bool replace( const OTodo& ); + void removeAllCompleted(); + private: bool m_dirty : 1; QString m_file; QMap<int, OTodo> m_map; }; #endif diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index c1682c6..b2dfe80 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp @@ -1,618 +1,619 @@ #include <qfile.h> #include <qvector.h> #include <qpe/global.h> #include <qpe/stringutil.h> #include <qpe/timeconversion.h> #include <opie/xmltree.h> #include "otodoaccessxml.h" OTodoAccessXML::OTodoAccessXML( const QString& appName, const QString& fileName ) : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) { if (!fileName.isEmpty() ) m_file = fileName; else m_file = Global::applicationFileName( "todolist", "todolist.xml" ); } OTodoAccessXML::~OTodoAccessXML() { } bool OTodoAccessXML::load() { m_opened = true; m_changed = false; /* initialize dict */ /* * UPDATE dict if you change anything!!! */ - QAsciiDict<int> dict(15); + QAsciiDict<int> dict(21); dict.setAutoDelete( TRUE ); dict.insert("Categories" , new int(OTodo::Category) ); dict.insert("Uid" , new int(OTodo::Uid) ); dict.insert("HasDate" , new int(OTodo::HasDate) ); dict.insert("Completed" , new int(OTodo::Completed) ); dict.insert("Description" , new int(OTodo::Description) ); dict.insert("Summary" , new int(OTodo::Summary) ); dict.insert("Priority" , new int(OTodo::Priority) ); dict.insert("DateDay" , new int(OTodo::DateDay) ); dict.insert("DateMonth" , new int(OTodo::DateMonth) ); dict.insert("DateYear" , new int(OTodo::DateYear) ); dict.insert("Progress" , new int(OTodo::Progress) ); dict.insert("Completed", new int(OTodo::Completed) ); dict.insert("CrossReference", new int(OTodo::CrossReference) ); - dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); - dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); + dict.insert("State", new int(OTodo::State) ); + dict.insert("Recurrence", new int(OTodo::Recurrence) ); + dict.insert("Alarms", new int(OTodo::Alarms) ); + dict.insert("Reminders", new int(OTodo::Reminders) ); + dict.insert("Notifiers", new int(OTodo::Notifiers) ); + dict.insert("Maintainer", new int(OTodo::Maintainer) ); // here the custom XML parser from TT it's GPL - // but we want to push that to TT..... + // but we want to push OpiePIM... to TT..... QFile f(m_file ); if (!f.open(IO_ReadOnly) ) return false; QByteArray ba = f.readAll(); f.close(); char* dt = ba.data(); int len = ba.size(); int i = 0; char *point; const char* collectionString = "<Task "; while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { i = point -dt; i+= strlen(collectionString); OTodo ev; m_year = m_month = m_day = 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; // we have another attribute, read it. int j = i; while ( j < len && dt[j] != '=' ) ++j; QCString attr( dt+i, j-i+1); i = ++j; // skip = // find the start of quotes while ( i < len && dt[i] != '"' ) ++i; j = ++i; bool haveUtf = FALSE; bool haveEnt = FALSE; while ( j < len && dt[j] != '"' ) { if ( ((unsigned char)dt[j]) > 0x7f ) haveUtf = TRUE; if ( dt[j] == '&' ) haveEnt = TRUE; ++j; } if ( i == j ) { // empty value i = j + 1; 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 */ todo( &dict, ev, attr, str ); } /* * now add it */ if (m_events.contains( ev.uid() ) || ev.uid() == 0) { ev.setUid( 1 ); m_changed = true; } if ( ev.hasDueDate() ) { ev.setDueDate( QDate(m_year, m_month, m_day) ); } m_events.insert(ev.uid(), ev ); m_year = m_month = m_day = -1; } qWarning("counts %d records loaded!", m_events.count() ); return true; } bool OTodoAccessXML::reload() { return load(); } bool OTodoAccessXML::save() { // qWarning("saving"); if (!m_opened || !m_changed ) { // qWarning("not saving"); return true; } QString strNewFile = m_file + ".new"; QFile f( strNewFile ); if (!f.open( IO_WriteOnly|IO_Raw ) ) return false; int written; QString out; out = "<!DOCTYPE Tasks>\n<Tasks>\n"; // for all todos QMap<int, OTodo>::Iterator it; for (it = m_events.begin(); it != m_events.end(); ++it ) { out+= "<Task " + toString( (*it) ) + " />\n"; QCString cstr = out.utf8(); written = f.writeBlock( cstr.data(), cstr.length() ); /* less written then we wanted */ if ( written != (int)cstr.length() ) { f.close(); QFile::remove( strNewFile ); return false; } out = QString::null; } out += "</Tasks>"; QCString cstr = out.utf8(); written = f.writeBlock( cstr.data(), cstr.length() ); if ( written != (int)cstr.length() ) { f.close(); QFile::remove( strNewFile ); return false; } /* flush before renaming */ f.close(); if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { // qWarning("error renaming"); QFile::remove( strNewFile ); } m_changed = false; return true; } QArray<int> OTodoAccessXML::allRecords()const { QArray<int> ids( m_events.count() ); QMap<int, OTodo>::ConstIterator it; int i = 0; for ( it = m_events.begin(); it != m_events.end(); ++it ) { ids[i] = it.key(); i++; } return ids; } QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { QArray<int> ids(0); return ids; } OTodo OTodoAccessXML::find( int uid )const { OTodo todo; todo.setUid( 0 ); // isEmpty() QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); if ( it != m_events.end() ) todo = it.data(); return todo; } void OTodoAccessXML::clear() { if (m_opened ) m_changed = true; m_events.clear(); } bool OTodoAccessXML::add( const OTodo& todo ) { // qWarning("add"); m_changed = true; m_events.insert( todo.uid(), todo ); return true; } bool OTodoAccessXML::remove( int uid ) { m_changed = true; m_events.remove( uid ); return true; } bool OTodoAccessXML::replace( const OTodo& todo) { m_changed = true; m_events.replace( todo.uid(), todo ); return true; } QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ) { QArray<int> ids( m_events.count() ); QMap<int, OTodo>::Iterator it; int i = 0; for ( it = m_events.begin(); it != m_events.end(); ++it ) { if ( !it.data().hasDueDate() ) { if ( includeNoDates ) { ids[i] = it.key(); i++; } }else if ( it.data().dueDate() >= start && it.data().dueDate() <= end ) { ids[i] = it.key(); i++; } } ids.resize( i ); return ids; } QArray<int> OTodoAccessXML::overDue() { QArray<int> ids( m_events.count() ); int i = 0; QMap<int, OTodo>::Iterator it; for ( it = m_events.begin(); it != m_events.end(); ++it ) { if ( it.data().isOverdue() ) { ids[i] = it.key(); i++; } } ids.resize( i ); return ids; } /* private */ void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, const QCString& attr, const QString& val) { // qWarning("parse to do from XMLElement" ); int *find=0; find = (*dict)[ attr.data() ]; if (!find ) { // qWarning("Unknown option" + it.key() ); ev.setCustomField( attr, val ); return; } switch( *find ) { case OTodo::Uid: ev.setUid( val.toInt() ); break; case OTodo::Category: ev.setCategories( ev.idsFromString( val ) ); break; case OTodo::HasDate: ev.setHasDueDate( val.toInt() ); break; case OTodo::Completed: ev.setCompleted( val.toInt() ); break; case OTodo::Description: ev.setDescription( val ); break; case OTodo::Summary: ev.setSummary( val ); break; case OTodo::Priority: ev.setPriority( val.toInt() ); break; case OTodo::DateDay: m_day = val.toInt(); break; case OTodo::DateMonth: m_month = val.toInt(); break; case OTodo::DateYear: m_year = val.toInt(); break; case OTodo::Progress: ev.setProgress( val.toInt() ); break; case OTodo::CrossReference: { /* * A cross refernce looks like * appname,id;appname,id * we need to split it up */ QStringList refs = QStringList::split(';', val ); QStringList::Iterator strIt; for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { int pos = (*strIt).find(','); if ( pos > -1 ) ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); } break; } - case OTodo::HasAlarmDateTime: - ev.setHasAlarmDateTime( val.toInt() ); - break; - case OTodo::AlarmDateTime: { - /* this sounds better ;) zecke */ - ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); - break; - } default: break; } } QString OTodoAccessXML::toString( const OTodo& ev )const { QString str; str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; str += "Categories=\"" + toString( ev.categories() ) + "\" "; str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; if ( ev.hasDueDate() ) { str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; } // qWarning( "Uid %d", ev.uid() ); str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; // append the extra options /* FIXME Qtopia::Record this is currently not * possible you can set custom fields * but don' iterate over the list * I may do #define private protected * for this case - cough --zecke */ /* QMap<QString, QString> extras = ev.extras(); QMap<QString, QString>::Iterator extIt; for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) str += extIt.key() + "=\"" + extIt.data() + "\" "; */ // cross refernce - str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; return str; } QString OTodoAccessXML::toString( const QArray<int>& ints ) const { return Qtopia::Record::idsToString( ints ); } /* internal class for sorting * * Inspired by todoxmlio.cpp from TT */ struct OTodoXMLContainer { OTodo todo; }; namespace { inline QString string( const OTodo& todo) { return todo.summary().isEmpty() ? todo.description().left(20 ) : todo.summary(); } inline int completed( const OTodo& todo1, const OTodo& todo2) { int ret = 0; if ( todo1.isCompleted() ) ret++; if ( todo2.isCompleted() ) ret--; return ret; } inline int priority( const OTodo& t1, const OTodo& t2) { return ( t1.priority() - t2.priority() ); } inline int description( const OTodo& t1, const OTodo& t2) { return QString::compare( string(t1), string(t2) ); } inline int deadline( const OTodo& t1, const OTodo& t2) { int ret = 0; if ( t1.hasDueDate() && t2.hasDueDate() ) ret = t2.dueDate().daysTo( t1.dueDate() ); else if ( t1.hasDueDate() ) ret = -1; else if ( t2.hasDueDate() ) ret = 1; else ret = 0; return ret; } }; /* * Returns: * 0 if item1 == item2 * * non-zero if item1 != item2 * * This function returns int rather than bool so that reimplementations * can return one of three values and use it to sort by: * * 0 if item1 == item2 * * > 0 (positive integer) if item1 > item2 * * < 0 (negative integer) if item1 < item2 * */ class OTodoXMLVector : public QVector<OTodoXMLContainer> { public: OTodoXMLVector(int size, bool asc, int sort) : QVector<OTodoXMLContainer>( size ) { setAutoDelete( true ); m_asc = asc; m_sort = sort; } /* return the summary/description */ QString string( const OTodo& todo) { return todo.summary().isEmpty() ? todo.description().left(20 ) : todo.summary(); } /** * we take the sortorder( switch on it ) * */ int compareItems( Item d1, Item d2 ) { bool seComp, sePrio, seDesc, seDeadline; seComp = sePrio = seDeadline = seDesc = false; int ret =0; OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; /* same item */ if ( con1->todo.uid() == con2->todo.uid() ) return 0; switch ( m_sort ) { /* completed */ case 0: { ret = completed( con1->todo, con2->todo ); seComp = TRUE; break; } /* priority */ case 1: { ret = priority( con1->todo, con2->todo ); sePrio = TRUE; break; } /* description */ case 2: { ret = description( con1->todo, con2->todo ); seDesc = TRUE; break; } /* deadline */ case 3: { ret = deadline( con1->todo, con2->todo ); seDeadline = TRUE; break; } default: ret = 0; break; }; /* * FIXME do better sorting if the first sort criteria * ret equals 0 start with complete and so on... */ /* twist it we're not ascending*/ if (!m_asc) ret = ret * -1; if ( ret ) return ret; // default did not gave difference let's try it other way around /* * General try if already checked if not test * and return * 1.Completed * 2.Priority * 3.Description * 4.DueDate */ if (!seComp ) { if ( (ret = completed( con1->todo, con2->todo ) ) ) { if (!m_asc ) ret *= -1; return ret; } } if (!sePrio ) { if ( (ret = priority( con1->todo, con2->todo ) ) ) { if (!m_asc ) ret *= -1; return ret; } } if (!seDesc ) { if ( (ret = description(con1->todo, con2->todo ) ) ) { if (!m_asc) ret *= -1; return ret; } } if (!seDeadline) { if ( (ret = deadline( con1->todo, con2->todo ) ) ) { if (!m_asc) ret *= -1; return ret; } } return 0; } private: bool m_asc; int m_sort; }; QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, int sortFilter, int cat ) { qWarning("sorted! %d cat", cat); OTodoXMLVector vector(m_events.count(), asc,sortOrder ); QMap<int, OTodo>::Iterator it; int item = 0; bool bCat = sortFilter & 1 ? true : false; bool bOnly = sortFilter & 2 ? true : false; bool comp = sortFilter & 4 ? true : false; for ( it = m_events.begin(); it != m_events.end(); ++it ) { /* show category */ if ( bCat && cat != 0) if (!(*it).categories().contains( cat ) ) { qWarning("category mis match"); continue; } /* isOverdue but we should not show overdue - why?*/ /* if ( (*it).isOverdue() && !bOnly ) { qWarning("item is overdue but !bOnly"); continue; } */ if ( !(*it).isOverdue() && bOnly ) { qWarning("item is not overdue but bOnly checked"); continue; } if ((*it).isCompleted() && comp ) { qWarning("completed continue!"); continue; } OTodoXMLContainer* con = new OTodoXMLContainer(); con->todo = (*it); vector.insert(item, con ); item++; } qWarning("XXX %d Items added", item); vector.resize( item ); /* sort it now */ vector.sort(); /* now get the uids */ QArray<int> array( vector.count() ); for (uint i= 0; i < vector.count(); i++ ) { array[i] = ( vector.at(i) )->todo.uid(); } qWarning("array count = %d %d", array.count(), vector.count() ); return array; }; +void OTodoAccessXML::removeAllCompleted() { + for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { + if ( (*it).isCompleted() ) + m_events.remove( it ); + } +} diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h index dc41c32..93609fe 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.h +++ b/libopie2/opiepim/backend/otodoaccessxml.h @@ -1,56 +1,57 @@ #ifndef OPIE_TODO_ACCESS_XML_H #define OPIE_TODO_ACCESS_XML_H #include <qasciidict.h> #include <qmap.h> #include "otodoaccessbackend.h" namespace Opie { class XMLElement; }; class OTodoAccessXML : public OTodoAccessBackend { public: /** * fileName if Empty we will use the default path */ OTodoAccessXML( const QString& appName, const QString& fileName = QString::null ); ~OTodoAccessXML(); bool load(); bool reload(); bool save(); QArray<int> allRecords()const; QArray<int> queryByExample( const OTodo&, int querysettings ); OTodo find( int uid )const; void clear(); bool add( const OTodo& ); bool remove( int uid ); + void removeAllCompleted(); bool replace( const OTodo& ); /* our functions */ QArray<int> effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ); QArray<int> overDue(); QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ); private: void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); QString toString( const OTodo& )const; QString toString( const QArray<int>& ints ) const; QMap<int, OTodo> m_events; QString m_file; QString m_app; bool m_opened : 1; bool m_changed : 1; class OTodoAccessXMLPrivate; OTodoAccessXMLPrivate* d; int m_year, m_month, m_day; }; #endif diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h index 6de68b1..8cf81c8 100644 --- a/libopie2/opiepim/core/opimaccesstemplate.h +++ b/libopie2/opiepim/core/opimaccesstemplate.h @@ -1,259 +1,269 @@ #ifndef OPIE_PIM_ACCESS_TEMPLATE_H #define OPIE_PIM_ACCESS_TEMPLATE_H #include <qarray.h> #include <opie/opimrecord.h> #include <opie/opimaccessbackend.h> #include <opie/orecordlist.h> #include "opimcache.h" #include "otemplatebase.h" /** * Thats the frontend to our OPIE PIM * Library. Either you want to use it's * interface or you want to implement * your own Access lib * Just create a OPimRecord and inherit from * the plugins */ template <class T = OPimRecord > class OPimAccessTemplate : public OTemplateBase<T> { public: typedef ORecordList<T> List; typedef OPimAccessBackend<T> BackEnd; typedef OPimCache<T> Cache; /** * c'tor BackEnd */ OPimAccessTemplate( BackEnd* end); virtual ~OPimAccessTemplate(); /** * load from the backend */ virtual bool load(); /** Reload database. * You should execute this function if the external database * was changed. * This function will load the external database and afterwards * rejoin the local changes. Therefore the local database will be set consistent. */ virtual bool reload(); /** Save contacts database. * Save is more a "commit". After calling this function, all changes are public available. * @return true if successful */ virtual bool save(); /** * if the resource was changed externally * You should use the signal handling instead of polling possible changes ! * zecke: Do you implement a signal for otodoaccess ? */ bool wasChangedExternally()const; /** * return a List of records * you can iterate over them */ virtual List allRecords()const; /** * queryByExample. * @see otodoaccess, ocontactaccess */ virtual List queryByExample( const T& t, int querySettings ); /** * find the OPimRecord uid */ virtual T find( int uid )const; /** * read ahead cache find method ;) */ virtual T find( int uid, const QArray<int>&, uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const; /* invalidate cache here */ /** * clears the backend and invalidates the backend */ virtual void clear() ; /** * add T to the backend * @param t The item to add. * @return <i>true</i> if added successfully. */ virtual bool add( const T& t ) ; + bool add( const OPimRecord& ); /* only the uid matters */ /** * remove T from the backend * @param t The item to remove * @return <i>true</i> if successful. */ virtual bool remove( const T& t ); /** * remove the OPimRecord with uid * @param uid The ID of the item to remove * @return <i>true</i> if successful. */ virtual bool remove( int uid ); /** * replace T from backend * @param t The item to replace * @return <i>true</i> if successful. */ virtual bool replace( const T& t) ; void setReadAhead( uint count ); /** * @internal */ void cache( const T& )const; void setSaneCacheSize( int ); protected: /** * invalidate the cache */ void invalidateCache(); void setBackEnd( BackEnd* end ); /** * returns the backend */ BackEnd* backEnd(); BackEnd* m_backEnd; Cache m_cache; }; template <class T> OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) : OTemplateBase<T>(), m_backEnd( end ) { if (end ) end->setFrontend( this ); } template <class T> OPimAccessTemplate<T>::~OPimAccessTemplate() { qWarning("~OPimAccessTemplate<T>"); delete m_backEnd; } template <class T> bool OPimAccessTemplate<T>::load() { invalidateCache(); return m_backEnd->load(); } template <class T> bool OPimAccessTemplate<T>::reload() { invalidateCache(); // zecke: I think this should be added (se) return m_backEnd->reload(); } template <class T> bool OPimAccessTemplate<T>::save() { return m_backEnd->save(); } template <class T> typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { QArray<int> ints = m_backEnd->allRecords(); List lis(ints, this ); return lis; } template <class T> typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); List lis(ints, this ); return lis; } template <class T> T OPimAccessTemplate<T>::find( int uid ) const{ T t = m_backEnd->find( uid ); cache( t ); return t; } template <class T> T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar, uint current, typename OTemplateBase<T>::CacheDirection dir )const { /* * better do T.isEmpty() * after a find this way we would * avoid two finds in QCache... */ // qWarning("find it now %d", uid ); if (m_cache.contains( uid ) ) { return m_cache.find( uid ); } T t = m_backEnd->find( uid, ar, current, dir ); cache( t ); return t; } template <class T> void OPimAccessTemplate<T>::clear() { invalidateCache(); m_backEnd->clear(); } template <class T> bool OPimAccessTemplate<T>::add( const T& t ) { cache( t ); return m_backEnd->add( t ); } template <class T> +bool OPimAccessTemplate<T>::add( const OPimRecord& rec) { + /* same type */ + if ( rec.rtti() == T::rtti() ) { + const T &t = static_cast<const T&>(rec); + return add(t); + } + return false; +} +template <class T> bool OPimAccessTemplate<T>::remove( const T& t ) { return remove( t.uid() ); } template <class T> bool OPimAccessTemplate<T>::remove( int uid ) { m_cache.remove( uid ); return m_backEnd->remove( uid ); } template <class T> bool OPimAccessTemplate<T>::replace( const T& t ) { m_cache.replace( t ); return m_backEnd->replace( t ); } template <class T> void OPimAccessTemplate<T>::invalidateCache() { m_cache.invalidate(); } template <class T> typename OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() { return m_backEnd; } template <class T> bool OPimAccessTemplate<T>::wasChangedExternally()const { return false; } template <class T> void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) { m_backEnd = end; if (m_backEnd ) m_backEnd->setFrontend( this ); } template <class T> void OPimAccessTemplate<T>::cache( const T& t ) const{ /* hacky we need to work around the const*/ ((OPimAccessTemplate<T>*)this)->m_cache.add( t ); } template <class T> void OPimAccessTemplate<T>::setSaneCacheSize( int size ) { m_cache.setSize( size ); } template <class T> void OPimAccessTemplate<T>::setReadAhead( uint count ) { m_backEnd->setReadAhead( count ); } #endif diff --git a/libopie2/opiepim/core/opimmaintainer.cpp b/libopie2/opiepim/core/opimmaintainer.cpp index e34f035..92cb25a 100644 --- a/libopie2/opiepim/core/opimmaintainer.cpp +++ b/libopie2/opiepim/core/opimmaintainer.cpp @@ -1,37 +1,37 @@ #include "opimmaintainer.h" -OPimMaintainer::OPimMaintainer( enum Mode mode, int uid ) +OPimMaintainer::OPimMaintainer( int mode, int uid ) : m_mode(mode), m_uid(uid ) {} OPimMaintainer::~OPimMaintainer() { } OPimMaintainer::OPimMaintainer( const OPimMaintainer& main ) { *this = main; } OPimMaintainer &OPimMaintainer::operator=( const OPimMaintainer& main ) { m_mode = main.m_mode; m_uid = main.m_uid; return *this; } bool OPimMaintainer::operator==( const OPimMaintainer& main ) { if (m_mode != main.m_mode ) return false; if (m_uid != main.m_uid ) return false; return true; } bool OPimMaintainer::operator!=( const OPimMaintainer& main ) { return !(*this == main ); } -OPimMaintainer::Mode OPimMaintainer::mode()const { +int OPimMaintainer::mode()const { return m_mode; } int OPimMaintainer::uid()const { return m_uid; } -void OPimMaintainer::setMode( enum Mode mo) { +void OPimMaintainer::setMode( int mo) { m_mode = mo; } void OPimMaintainer::setUid( int uid ) { m_uid = uid; } diff --git a/libopie2/opiepim/core/opimmaintainer.h b/libopie2/opiepim/core/opimmaintainer.h index 310e15a..793d066 100644 --- a/libopie2/opiepim/core/opimmaintainer.h +++ b/libopie2/opiepim/core/opimmaintainer.h @@ -1,36 +1,40 @@ #ifndef OPIE_PIM_MAINTAINER_H #define OPIE_PIM_MAINTAINER_H #include <qstring.h> /** * Who maintains what? */ class OPimMaintainer { public: enum Mode { Undefined = -1, - Responsible = 0, + Nothing = 0, + Responsible, DoneBy, - Coordinating }; - OPimMaintainer( enum Mode mode = Undefined, int uid = 0); + Coordinating, + }; + OPimMaintainer( int mode = Undefined, int uid = 0); OPimMaintainer( const OPimMaintainer& ); ~OPimMaintainer(); OPimMaintainer &operator=( const OPimMaintainer& ); bool operator==( const OPimMaintainer& ); bool operator!=( const OPimMaintainer& ); - Mode mode()const; + int mode()const; int uid()const; - void setMode( enum Mode ); + void setMode( int mode ); void setUid( int uid ); private: - Mode m_mode; + int m_mode; int m_uid; + class Private; + Private *d; }; #endif diff --git a/libopie2/opiepim/core/opimnotify.cpp b/libopie2/opiepim/core/opimnotify.cpp new file mode 100644 index 0000000..af5514b --- a/dev/null +++ b/libopie2/opiepim/core/opimnotify.cpp @@ -0,0 +1,227 @@ +#include <qshared.h> + +#include "opimnotify.h" + +struct OPimNotify::Data : public QShared { + Data() : QShared(),dur(-1),parent(0) { + + } + QDateTime start; + int dur; + QString application; + int parent; +}; + +OPimNotify::OPimNotify( const QDateTime& start, int duration, int parent ) { + data = new Data; + data->start = start; + data->dur = duration; + data->parent = parent; +} +OPimNotify::OPimNotify( const OPimNotify& noti) + : data( noti.data ) +{ + data->ref(); +} +OPimNotify::~OPimNotify() { + if ( data->deref() ) { + delete data; + data = 0l; + } +} + +OPimNotify &OPimNotify::operator=( const OPimNotify& noti) { + noti.data->ref(); + deref(); + data = noti.data; + + return *this; +} +bool OPimNotify::operator==( const OPimNotify& noti ) { + if ( data == noti.data ) return true; + if ( data->dur != noti.data->dur ) return false; + if ( data->parent != noti.data->parent ) return false; + if ( data->application != noti.data->application ) return false; + if ( data->start != noti.data->start ) return false; + + return true; +} +QDateTime OPimNotify::dateTime()const { + return data->start; +} +QString OPimNotify::service()const { + return data->application; +} +int OPimNotify::parent()const { + return data->parent; +} +int OPimNotify::duration()const { + return data->dur; +} +QDateTime OPimNotify::endTime()const { + return QDateTime( data->start.date(), data->start.time().addSecs( data->dur) ); +} +void OPimNotify::setDateTime( const QDateTime& time ) { + copyIntern(); + data->start = time; +} +void OPimNotify::setDuration( int dur ) { + copyIntern(); + data->dur = dur; +} +void OPimNotify::setParent( int uid ) { + copyIntern(); + data->parent = uid; +} +void OPimNotify::setService( const QString& str ) { + copyIntern(); + data->application = str; +} +void OPimNotify::copyIntern() { + if ( data->count != 1 ) { + data->deref(); + Data* dat = new Data; + dat->start = data->start; + dat->dur = data->dur; + dat->application = data->application; + dat->parent = data->parent; + data = dat; + } +} +void OPimNotify::deref() { + if ( data->deref() ) { + delete data; + data = 0; + } +} + +/***********************************************************/ +struct OPimAlarm::Data : public QShared { + Data() : QShared() { + sound = 1; + } + int sound; + QString file; +}; +OPimAlarm::OPimAlarm( int sound, const QDateTime& start, int duration, int parent ) + : OPimNotify( start, duration, parent ) +{ + data = new Data; + data->sound = sound; +} +OPimAlarm::OPimAlarm( const OPimAlarm& al) + : OPimNotify(al), data( al.data ) +{ + data->ref(); +} +OPimAlarm::~OPimAlarm() { + if ( data->deref() ) { + delete data; + data = 0l; + } +} +OPimAlarm &OPimAlarm::operator=( const OPimAlarm& al) +{ + OPimNotify::operator=( al ); + deref(); + al.data->ref(); + + data = al.data; + + + return *this; +} +bool OPimAlarm::operator==( const OPimAlarm& al) { + if ( data->sound != al.data->sound ) return false; + else if ( data->sound == Custom && data->file != al.data->file ) + return false; + + return OPimNotify::operator==( al ); +} +QString OPimAlarm::type()const { + return QString::fromLatin1("OPimAlarm"); +} +int OPimAlarm::sound()const { + return data->sound; +} +QString OPimAlarm::file()const { + return data->file; +} +void OPimAlarm::setSound( int snd) { + copyIntern(); + data->sound = snd; +} +void OPimAlarm::setFile( const QString& sound ) { + copyIntern(); + data->file = sound; +} +void OPimAlarm::deref() { + if ( data->deref() ) { + delete data; + data = 0l; + } +} +void OPimAlarm::copyIntern() { + if ( data->count != 1 ) { + data->deref(); + Data *newDat = new Data; + newDat->sound = data->sound; + newDat->file = data->file; + data = newDat; + } +} +/************************/ +struct OPimReminder::Data : public QShared { + Data() : QShared(), record( 0) { + } + int record; + +}; +OPimReminder::OPimReminder( int uid, const QDateTime& start, int dur, int parent ) + : OPimNotify( start, dur, parent ) +{ + data = new Data; + data->record = uid; +} +OPimReminder::OPimReminder( const OPimReminder& rem ) + : OPimNotify( rem ), data( rem.data ) +{ + data->ref(); +} +OPimReminder& OPimReminder::operator=( const OPimReminder& rem) { + OPimNotify::operator=(rem ); + + deref(); + rem.data->ref(); + data = rem.data; + + return *this; +} +bool OPimReminder::operator==( const OPimReminder& rem) { + if ( data->record != rem.data->record ) return false; + + return OPimNotify::operator==( rem ); +} +QString OPimReminder::type()const { + return QString::fromLatin1("OPimReminder"); +} +int OPimReminder::recordUid()const { + return data->record; +} +void OPimReminder::setRecordUid( int uid ) { + copyIntern(); + data->record = uid; +} +void OPimReminder::deref() { + if ( data->deref() ) { + delete data; + data = 0l; + } +} +void OPimReminder::copyIntern() { + if ( data->count != 1 ) { + Data* da = new Data; + da->record = data->record; + data = da; + } +} diff --git a/libopie2/opiepim/core/opimnotify.h b/libopie2/opiepim/core/opimnotify.h new file mode 100644 index 0000000..3501948 --- a/dev/null +++ b/libopie2/opiepim/core/opimnotify.h @@ -0,0 +1,142 @@ +#ifndef OPIE_PIM_NOTIFY_H +#define OPIE_PIM_NOTIFY_H + +#include <qdatetime.h> +#include <qvaluelist.h> + +/** + * This is the base class of Notifiers. Possible + * notifiers would be Alarms, Reminders + * What they share is that they have + * A DateTime, Type, Duration + * This is what this base class takes care of + * on top of that it's shared + */ +/* + * TALK to eilers: have a class OPimDuration which sets the Duration + * given on the Due/Start Date? -zecke + * discuss: do we need a uid for the notify? -zecke + */ +class OPimNotify { +public: + typedef QValueList<OPimNotify> ValueList; + OPimNotify( const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 ); + OPimNotify( const OPimNotify& ); + virtual ~OPimNotify(); + + OPimNotify &operator=(const OPimNotify& ); + bool operator==( const OPimNotify& ); + + virtual QString type()const = 0; + + /** start date */ + QDateTime dateTime()const; + QString service()const; + + /** + * RETURN the parent uid + */ + int parent()const; + + /** + * in Seconds + */ + int duration()const; + + /** + * Start Time + Duration + */ + QDateTime endTime()const; + + void setDateTime( const QDateTime& ); + void setDuration( int dur ); + void setParent(int uid ); + void setService( const QString& ); + + +private: + inline void copyIntern(); + void deref(); + struct Data; + Data* data; + + /* d-pointer */ + class NotifyPrivate; + NotifyPrivate* d; + +}; +/** + * An alarm is a sound/mail/buzzer played/send + * at a given time to inform about + * an Event + */ +class OPimAlarm : public OPimNotify { +public: + enum Sound{Loud=0, Silent, Custom }; + OPimAlarm( int sound = Silent, const QDateTime& start = QDateTime(), int duration = 0, int parent = 0 ); + OPimAlarm( const OPimAlarm& ); + ~OPimAlarm(); + + OPimAlarm &operator=( const OPimAlarm& ); + bool operator==( const OPimAlarm& ); + QString type()const; + + int sound()const; + QString file()const; + + void setSound( int ); + /* only when sound is custom... */ + void setFile( const QString& sound ); + +private: + void deref(); + void copyIntern(); + struct Data; + Data * data; + + class Private; + Private* d; + +}; + +/** + * A Reminder will be put into the + * datebook + */ +class OPimReminder : public OPimNotify { +public: + + /** + * c'tor of a reminder + * @param uid The uid of the Record inside the Datebook + * @param start the StartDate invalid for all day... + * @param duration The duration of the event ( -1 for all day ) + * @param parent The 'parent' record of this reminder + */ + OPimReminder( int uid = 0, const QDateTime& start = QDateTime(), + int duration = 0, int parent = 0 ); + OPimReminder( const OPimReminder& ); + OPimReminder &operator=(const OPimReminder& ); + + QString type()const; + + bool operator==( const OPimReminder& ); + + /** + * the uid of the alarm + * inside the 'datebook' application + */ + int recordUid()const; + void setRecordUid( int uid ); + +private: + void deref(); + void copyIntern(); + + struct Data; + Data* data; + class Private; + Private *d; +}; + +#endif diff --git a/libopie2/opiepim/core/opimnotifymanager.cpp b/libopie2/opiepim/core/opimnotifymanager.cpp new file mode 100644 index 0000000..be4a1c2 --- a/dev/null +++ b/libopie2/opiepim/core/opimnotifymanager.cpp @@ -0,0 +1,69 @@ +#include "opimnotifymanager.h" + +OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al) + : m_rem( rem ), m_al( al ) +{} +OPimNotifyManager::~OPimNotifyManager() { +} +/* use static_cast and type instead of dynamic... */ +void OPimNotifyManager::add( const OPimNotify& noti) { + if ( noti.type() == QString::fromLatin1("OPimReminder") ) { + const OPimReminder& rem = static_cast<const OPimReminder&>(noti); + m_rem.append( rem ); + }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { + const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); + m_al.append( al ); + } +} +void OPimNotifyManager::remove( const OPimNotify& noti) { + if ( noti.type() == QString::fromLatin1("OPimReminder") ) { + const OPimReminder& rem = static_cast<const OPimReminder&>(noti); + m_rem.remove( rem ); + }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { + const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); + m_al.remove( al ); + } +} +void OPimNotifyManager::replace( const OPimNotify& noti) { + if ( noti.type() == QString::fromLatin1("OPimReminder") ) { + const OPimReminder& rem = static_cast<const OPimReminder&>(noti); + m_rem.remove( rem ); + m_rem.append( rem ); + }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { + const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); + m_al.remove( al ); + m_al.append( al ); + } +} +OPimNotifyManager::Reminders OPimNotifyManager::reminders()const { + return m_rem; +} +OPimNotifyManager::Alarms OPimNotifyManager::alarms()const { + return m_al; +} +void OPimNotifyManager::setAlarms( const Alarms& al) { + m_al = al; +} +void OPimNotifyManager::setReminders( const Reminders& rem) { + m_rem = rem; +} +/* FIXME!!! */ +/** + * The idea is to check if the provider for our service + * is online + * if it is we will use QCOP + * if not the Factory to get the backend... + * Qtopia1.6 services would be kewl to have here.... + */ +void OPimNotifyManager::registerNotify( const OPimNotify& ) { + +} +/* FIXME!!! */ +/** + * same as above... + * Also implement Url model + * have a MainWindow.... + */ +void OPimNotifyManager::deregister( const OPimNotify& ) { + +} diff --git a/libopie2/opiepim/core/opimnotifymanager.h b/libopie2/opiepim/core/opimnotifymanager.h new file mode 100644 index 0000000..0eebc9b --- a/dev/null +++ b/libopie2/opiepim/core/opimnotifymanager.h @@ -0,0 +1,51 @@ +#ifndef OPIE_PIM_NOTIFY_MANAGER_H +#define OPIE_PIM_NOTIFY_MANAGER_H + +#include <qvaluelist.h> + +#include <opie/opimnotify.h> + +/** + * The notify manager keeps track of the Notifiers.... + */ +class OPimNotifyManager { +public: + typedef QValueList<OPimReminder> Reminders; + typedef QValueList<OPimAlarm> Alarms; + OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() ); + ~OPimNotifyManager(); + + /* we will cast it for you ;) */ + void add( const OPimNotify& ); + void remove( const OPimNotify& ); + /* replaces all with this one! */ + void replace( const OPimNotify& ); + + Reminders reminders()const; + Alarms alarms()const; + + void setAlarms( const Alarms& ); + void setReminders( const Reminders& ); + + /* register is a Ansi C keyword... */ + /** + * This function will register the Notify to the Alarm Server + * or datebook depending on the type of the notify + */ + void registerNotify( const OPimNotify& ); + + /** + * this will do the opposite.. + */ + void deregister( const OPimNotify& ); + +private: + Reminders m_rem; + Alarms m_al; + + class Private; + Private *d; + +}; + +#endif diff --git a/libopie2/opiepim/core/opimrecord.cpp b/libopie2/opiepim/core/opimrecord.cpp index 0e3be9d..49b5bf9 100644 --- a/libopie2/opiepim/core/opimrecord.cpp +++ b/libopie2/opiepim/core/opimrecord.cpp @@ -1,81 +1,84 @@ #include <qpe/categories.h> #include <qpe/categoryselect.h> #include "opimrecord.h" Qtopia::UidGen OPimRecord::m_uidGen( Qtopia::UidGen::Qtopia ); OPimRecord::OPimRecord( int uid ) : Qtopia::Record() { setUid( uid ); } OPimRecord::~OPimRecord() { } OPimRecord::OPimRecord( const OPimRecord& rec ) : Qtopia::Record( rec ) { (*this) = rec; } OPimRecord &OPimRecord::operator=( const OPimRecord& rec) { Qtopia::Record::operator=( rec ); m_xrefman = rec.m_xrefman; return *this; } /* * category names */ QStringList OPimRecord::categoryNames()const { QStringList list; QArray<int> cats = categories(); Categories catDB; catDB.load( categoryFileName() ); for (uint i = 0; i < cats.count(); i++ ) { list << catDB.label("Todo List", cats[i] ); } return list; } void OPimRecord::setCategoryNames( const QStringList& ) { } void OPimRecord::addCategoryName( const QString& ) { Categories catDB; catDB.load( categoryFileName() ); } bool OPimRecord::isEmpty()const { return ( uid() == 0 ); } /*QString OPimRecord::crossToString()const { QString str; QMap<QString, QArray<int> >::ConstIterator it; for (it = m_relations.begin(); it != m_relations.end(); ++it ) { QArray<int> id = it.data(); for ( uint i = 0; i < id.size(); ++i ) { str += it.key() + "," + QString::number( i ) + ";"; } } str = str.remove( str.length()-1, 1); // strip the ; //qWarning("IDS " + str ); return str; }*/ /* if uid = 1 assign a new one */ void OPimRecord::setUid( int uid ) { if ( uid == 1) uid = uidGen().generate(); Qtopia::Record::setUid( uid ); }; Qtopia::UidGen &OPimRecord::uidGen() { return m_uidGen; } OPimXRefManager &OPimRecord::xrefmanager() { return m_xrefman; } +int OPimRecord::rtti(){ + return 0; +} diff --git a/libopie2/opiepim/core/opimrecord.h b/libopie2/opiepim/core/opimrecord.h index 1642a5e..ec99a13 100644 --- a/libopie2/opiepim/core/opimrecord.h +++ b/libopie2/opiepim/core/opimrecord.h @@ -1,116 +1,122 @@ #ifndef OPIE_PIM_RECORD_H #define OPIE_PIM_RECORD_H #include <qmap.h> #include <qstring.h> #include <qstringlist.h> #include <qpe/palmtoprecord.h> #include <opie/opimxrefmanager.h> /** * This is the base class for * all PIM Records * */ class OPimRecord : public Qtopia::Record { public: /** * c'tor * uid of 0 isEmpty * uid of 1 will be assigned a new one */ OPimRecord(int uid = 0); ~OPimRecord(); /** * copy c'tor */ OPimRecord( const OPimRecord& rec ); /** * copy operator */ OPimRecord &operator=( const OPimRecord& ); /** * category names resolved */ QStringList categoryNames()const; /** * set category names they will be resolved */ void setCategoryNames( const QStringList& ); /** * addCategoryName adds a name * to the internal category list */ void addCategoryName( const QString& ); /** * if a Record isEmpty * it's empty if it's 0 */ virtual bool isEmpty()const; /** * toRichText summary */ virtual QString toRichText()const = 0; /** * a small one line summary */ virtual QString toShortText()const = 0; /** * the name of the Record */ virtual QString type()const = 0; /** * converts the internal structure to a map */ virtual QMap<int, QString> toMap()const = 0; /** * key value representation of extra items */ virtual QMap<QString, QString> toExtraMap()const = 0; /** * the name for a recordField */ virtual QString recordField(int)const = 0; /** * returns a reference of the * Cross Reference Manager - * Partner One is THIS PIM RECORD! - * Two is the Partner where we link to + * Partner 'One' is THIS PIM RECORD! + * 'Two' is the Partner where we link to */ OPimXRefManager& xrefmanager(); /** * set the uid */ virtual void setUid( int uid ); + /* + * used inside the Templates for casting + * REIMPLEMENT in your .... + */ + static int rtti(); + protected: Qtopia::UidGen &uidGen(); // QString crossToString()const; private: class OPimRecordPrivate; OPimRecordPrivate *d; OPimXRefManager m_xrefman; static Qtopia::UidGen m_uidGen; }; #endif diff --git a/libopie2/opiepim/core/opimresolver.h b/libopie2/opiepim/core/opimresolver.h new file mode 100644 index 0000000..86ae3eb --- a/dev/null +++ b/libopie2/opiepim/core/opimresolver.h @@ -0,0 +1,56 @@ +#ifndef OPIE_PIM_RESOLVER +#define OPIE_PIM_RESOLVER + +#include <qstring.h> +#include <qvaluelist.h> + +/** + * OPimResolver is a MetaClass to access + * available backends read only. + * It will be used to resolve uids + app names + * to full informations + * to traverse through a list of alarms, reminders + * to get access to built in PIM functionality + * and to more stuff + * THE PERFORMANCE will depend on THE BACKEND + * USING XML is a waste of memory!!!!! + */ +class OPimResolver : public QObject { +public: + enum BuiltIn { TodoList = 0, + DateBook, + AddressBook + }; + static OPimResolver* self(); + + + /* + * return a record for a uid + * and an app + */ + OPimRecord &record( const QString& service, int uid ); + + /** + * return the QCopChannel for service + * When we will use Qtopia Services it will be used here + */ + QString qcopChannel( enum BuiltIn& )const; + QString qcopChannel( const QString& service ); + + /** + * return a list of available services + */ + QStringList services()const; + + /** + * add a record to a service... ;) + */ + bool add( const QString& service, const OPimRecord& ); + +private: + OPimResolver(); + OPimRecord *m_last; + +}: + +#endif diff --git a/libopie2/opiepim/core/opimxref.cpp b/libopie2/opiepim/core/opimxref.cpp index 5cae871..8eefbd8 100644 --- a/libopie2/opiepim/core/opimxref.cpp +++ b/libopie2/opiepim/core/opimxref.cpp @@ -1,47 +1,47 @@ #include "opimxref.h" OPimXRef::OPimXRef( const OPimXRefPartner& one, const OPimXRefPartner& two ) : m_partners(2) { m_partners[0] = one; m_partners[1] = two; } OPimXRef::OPimXRef() : m_partners(2) { } OPimXRef::OPimXRef( const OPimXRef& ref) { *this = ref; } OPimXRef::~OPimXRef() { } OPimXRef &OPimXRef::operator=( const OPimXRef& ref) { m_partners = ref.m_partners; m_partners.detach(); return* this; } bool OPimXRef::operator==( const OPimXRef& oper ) { if ( m_partners == oper.m_partners ) return true; return false; } OPimXRefPartner OPimXRef::partner( enum Partners par) const{ return m_partners[par]; } void OPimXRef::setPartner( enum Partners par, const OPimXRefPartner& part) { m_partners[par] = part; } bool OPimXRef::containsString( const QString& string ) const{ - if ( m_partners[One].appName() == string || - m_partners[Two].appName() == string ) return true; + if ( m_partners[One].service() == string || + m_partners[Two].service() == string ) return true; return false; } bool OPimXRef::containsUid( int uid ) const{ if ( m_partners[One].uid() == uid || m_partners[Two].uid() == uid ) return true; return false; } diff --git a/libopie2/opiepim/core/opimxref.h b/libopie2/opiepim/core/opimxref.h index 354739a..6852651 100644 --- a/libopie2/opiepim/core/opimxref.h +++ b/libopie2/opiepim/core/opimxref.h @@ -1,39 +1,39 @@ #ifndef OPIM_XREF_H #define OPIM_XREF_H #include <qarray.h> #include <qvaluelist.h> #include <opie/opimxrefpartner.h> /** * this is a Cross Referecne between * two Cross Reference Partners */ class OPimXRef { public: typedef QValueList<OPimXRef> ValueList; enum Partners { One, Two }; OPimXRef( const OPimXRefPartner& ONE, const OPimXRefPartner& ); OPimXRef(); OPimXRef( const OPimXRef& ); ~OPimXRef(); OPimXRef &operator=( const OPimXRef& ); bool operator==( const OPimXRef& ); OPimXRefPartner partner( enum Partners )const; void setPartner( enum Partners, const OPimXRefPartner& ); - bool containsString( const QString& appName)const; + bool containsString( const QString& service)const; bool containsUid( int uid )const; private: QArray<OPimXRefPartner> m_partners; class Private; Private *d; }; #endif diff --git a/libopie2/opiepim/core/opimxrefmanager.cpp b/libopie2/opiepim/core/opimxrefmanager.cpp index 965f542..58bfd24 100644 --- a/libopie2/opiepim/core/opimxrefmanager.cpp +++ b/libopie2/opiepim/core/opimxrefmanager.cpp @@ -1,71 +1,71 @@ #include "opimxrefmanager.h" OPimXRefManager::OPimXRefManager() { } OPimXRefManager::OPimXRefManager( const OPimXRefManager& ref) { m_list = ref.m_list; } OPimXRefManager::~OPimXRefManager() { } OPimXRefManager &OPimXRefManager::operator=( const OPimXRefManager& ref) { m_list = ref.m_list; return *this; } bool OPimXRefManager::operator==( const OPimXRefManager& /*ref*/) { // if ( m_list == ref.m_list ) return true; return false; } void OPimXRefManager::add( const OPimXRef& ref) { m_list.append( ref ); } void OPimXRefManager::remove( const OPimXRef& ref) { m_list.remove( ref ); } void OPimXRefManager::replace( const OPimXRef& ref) { m_list.remove( ref ); m_list.append( ref ); } void OPimXRefManager::clear() { m_list.clear(); } QStringList OPimXRefManager::apps()const { OPimXRef::ValueList::ConstIterator it; QStringList list; QString str; for ( it = m_list.begin(); it != m_list.end(); ++it ) { - str = (*it).partner( OPimXRef::One ).appName(); + str = (*it).partner( OPimXRef::One ).service(); if ( !list.contains( str ) ) list << str; - str = (*it).partner( OPimXRef::Two ).appName(); + str = (*it).partner( OPimXRef::Two ).service(); if ( !list.contains( str ) ) list << str; } return list; } OPimXRef::ValueList OPimXRefManager::list()const { return m_list; } OPimXRef::ValueList OPimXRefManager::list( const QString& appName )const{ OPimXRef::ValueList list; OPimXRef::ValueList::ConstIterator it; for ( it = m_list.begin(); it != m_list.end(); ++it ) { if ( (*it).containsString( appName ) ) list.append( (*it) ); } return list; } OPimXRef::ValueList OPimXRefManager::list( int uid )const { OPimXRef::ValueList list; OPimXRef::ValueList::ConstIterator it; for ( it = m_list.begin(); it != m_list.end(); ++it ) { if ( (*it).containsUid( uid ) ) list.append( (*it) ); } return list; } diff --git a/libopie2/opiepim/core/opimxrefmanager.h b/libopie2/opiepim/core/opimxrefmanager.h index 9b003a3..39e5eef 100644 --- a/libopie2/opiepim/core/opimxrefmanager.h +++ b/libopie2/opiepim/core/opimxrefmanager.h @@ -1,41 +1,41 @@ #ifndef OPIM_XREF_MANAGER_H #define OPIM_XREF_MANAGER_H #include <qstringlist.h> #include <opie/opimxref.h> /** * This is a simple manager for * OPimXRefs. * It allows addition, removing, replacing * clearing and 'querying' the XRef... */ class OPimXRefManager { public: OPimXRefManager(); OPimXRefManager( const OPimXRefManager& ); ~OPimXRefManager(); OPimXRefManager& operator=( const OPimXRefManager& ); bool operator==( const OPimXRefManager& ); void add( const OPimXRef& ); void remove( const OPimXRef& ); void replace( const OPimXRef& ); void clear(); /** * apps participating */ QStringList apps()const; OPimXRef::ValueList list()const; - OPimXRef::ValueList list( const QString& appName )const; + OPimXRef::ValueList list( const QString& service )const; OPimXRef::ValueList list( int uid )const; private: OPimXRef::ValueList m_list; }; #endif diff --git a/libopie2/opiepim/core/opimxrefpartner.cpp b/libopie2/opiepim/core/opimxrefpartner.cpp index 028f4e6..6ef3efb 100644 --- a/libopie2/opiepim/core/opimxrefpartner.cpp +++ b/libopie2/opiepim/core/opimxrefpartner.cpp @@ -1,43 +1,43 @@ #include "opimxrefpartner.h" OPimXRefPartner::OPimXRefPartner( const QString& appName, int uid, int field ) : m_app(appName), m_uid(uid), m_field( field ) { } OPimXRefPartner::OPimXRefPartner( const OPimXRefPartner& ref ) { *this = ref; } OPimXRefPartner::~OPimXRefPartner() { } OPimXRefPartner &OPimXRefPartner::operator=( const OPimXRefPartner& par ) { m_app = par.m_app; m_uid = par.m_uid; m_field = par.m_field; return *this; } bool OPimXRefPartner::operator==( const OPimXRefPartner& par ) { if ( m_app != par.m_app ) return false; if ( m_uid != par.m_uid ) return false; if ( m_field != par.m_field ) return false; return true; } -QString OPimXRefPartner::appName()const { +QString OPimXRefPartner::service()const { return m_app; } int OPimXRefPartner::uid()const { return m_uid; } int OPimXRefPartner::field()const { return m_field; } -void OPimXRefPartner::setAppName( const QString& appName ) { +void OPimXRefPartner::setService( const QString& appName ) { m_app = appName; } void OPimXRefPartner::setUid( int uid ) { m_uid = uid; } void OPimXRefPartner::setField( int field ) { m_field = field; } diff --git a/libopie2/opiepim/core/opimxrefpartner.h b/libopie2/opiepim/core/opimxrefpartner.h index 808b9ab..d76e384 100644 --- a/libopie2/opiepim/core/opimxrefpartner.h +++ b/libopie2/opiepim/core/opimxrefpartner.h @@ -1,40 +1,40 @@ #ifndef OPIM_XREF_PARTNER_H #define OPIM_XREF_PARTNER_H #include <qstring.h> /** * This class represents one partner * of a Cross Reference. * In Opie one application * can link one uid * with one tableId( fieldId ) to another. */ class OPimXRefPartner { public: - OPimXRefPartner( const QString& appName = QString::null, + OPimXRefPartner( const QString& service = QString::null, int uid = 0, int field = -1 ); OPimXRefPartner( const OPimXRefPartner& ); OPimXRefPartner& operator=( const OPimXRefPartner& ); ~OPimXRefPartner(); bool operator==(const OPimXRefPartner& ); - QString appName()const; + QString service()const; int uid()const; int field()const; - void setAppName( const QString& appName ); + void setService( const QString& service ); void setUid( int uid ); void setField( int field ); private: QString m_app; int m_uid; int m_field; class Private; Private* d; }; #endif diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp index 257d4fd..daf3506 100644 --- a/libopie2/opiepim/core/orecur.cpp +++ b/libopie2/opiepim/core/orecur.cpp @@ -1,136 +1,451 @@ #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; hasEnd = FALSE; end = 0; } char days; // Q_UINT8 for 8 seven days;) ORecur::RepeatType type; int freq; int pos; bool hasEnd : 1; time_t end; time_t 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) { 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(); } +QDate ORecur::start()const{ + return data->start; +} time_t ORecur::endDateUTC()const { return data->end; } time_t ORecur::createTime()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; } void ORecur::setCreateTime( time_t 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 d24d72d..8713d97 100644 --- a/libopie2/opiepim/core/orecur.h +++ b/libopie2/opiepim/core/orecur.h @@ -1,56 +1,83 @@ /* * 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; + + /** + * 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 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/otodoaccess.cpp b/libopie2/opiepim/core/otodoaccess.cpp index c258de6..d860411 100644 --- a/libopie2/opiepim/core/otodoaccess.cpp +++ b/libopie2/opiepim/core/otodoaccess.cpp @@ -1,81 +1,86 @@ #include <qdatetime.h> #include <qpe/alarmserver.h> // #include "otodoaccesssql.h" #include "otodoaccess.h" #include "obackendfactory.h" OTodoAccess::OTodoAccess( OTodoAccessBackend* end ) : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end ) { // if (end == 0l ) // m_todoBackEnd = new OTodoAccessBackendSQL( QString::null); // Zecke: Du musst hier noch für das XML-Backend einen Appnamen übergeben ! if (end == 0l ) m_todoBackEnd = OBackendFactory<OTodoAccessBackend>::Default ("todo", QString::null); setBackEnd( m_todoBackEnd ); } OTodoAccess::~OTodoAccess() { // qWarning("~OTodoAccess"); } void OTodoAccess::mergeWith( const QValueList<OTodo>& list ) { QValueList<OTodo>::ConstIterator it; for ( it = list.begin(); it != list.end(); ++it ) { replace( (*it) ); } } OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ) { QArray<int> ints = m_todoBackEnd->effectiveToDos( start, end, includeNoDates ); List lis( ints, this ); return lis; } OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start, bool includeNoDates ) { return effectiveToDos( start, QDate::currentDate(), includeNoDates ); } OTodoAccess::List OTodoAccess::overDue() { List lis( m_todoBackEnd->overDue(), this ); return lis; } void OTodoAccess::addAlarm( const OTodo& event) { - if (!event.hasAlarmDateTime() ) +/* FIXME use the new notifier architecture + if (!event.hasAlarmDateTime() ) return; QDateTime now = QDateTime::currentDateTime(); QDateTime schedule = event.alarmDateTime(); if ( schedule > now ){ AlarmServer::addAlarm( schedule, "QPE/Application/todolist", "alarm(QDateTime,int)", event.uid() ); } +*/ } void OTodoAccess::delAlarm( int uid) { QDateTime schedule; // Create null DateTime // I hope this will remove all scheduled alarms // with the given uid !? // If not: I have to rethink how to remove already // scheduled events... (se) // it should be fine -zecke // qWarning("Removing alarm for event with uid %d", uid ); AlarmServer::deleteAlarm( schedule , "QPE/Application/todolist", "alarm(QDateTime,int)", uid ); } /* sort order */ OTodoAccess::List OTodoAccess::sorted( bool ascending, int sort,int filter, int cat ) { QArray<int> ints = m_todoBackEnd->sorted( ascending, sort, filter, cat ); OTodoAccess::List list( ints, this ); return list; } +void OTodoAccess::removeAllCompleted() { + m_todoBackEnd->removeAllCompleted(); +} diff --git a/libopie2/opiepim/core/otodoaccess.h b/libopie2/opiepim/core/otodoaccess.h index 390ab0e..c079155 100644 --- a/libopie2/opiepim/core/otodoaccess.h +++ b/libopie2/opiepim/core/otodoaccess.h @@ -1,93 +1,98 @@ #ifndef OPIE_TODO_ACCESS_H #define OPIE_TODO_ACCESS_H #include <qobject.h> #include <qvaluelist.h> #include "otodo.h" #include "otodoaccessbackend.h" #include "opimaccesstemplate.h" /** * OTodoAccess * the class to get access to * the todolist */ class OTodoAccess : public QObject, public OPimAccessTemplate<OTodo> { Q_OBJECT public: enum SortOrder { Completed = 0, Priority, Description, Deadline }; enum SortFilter{ Category =1, OnlyOverDue= 2, DoNotShowCompleted =4 }; /** * if you use 0l * the default resource will be * picked up */ OTodoAccess( OTodoAccessBackend* = 0l); ~OTodoAccess(); /* our functions here */ /** * include todos from start to end * includeNoDates whether or not to include * events with no dates */ List effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates = true ); /** * start * end date taken from the currentDate() */ List effectiveToDos( const QDate& start, bool includeNoDates = true ); /** * return overdue OTodos */ List overDue(); /** * */ List sorted( bool ascending, int sortOrder, int sortFilter, int cat ); /** * merge a list of OTodos into * the resource */ void mergeWith( const QValueList<OTodo>& ); /** + * delete all already completed items + */ + void removeAllCompleted(); + +signals: + /** + * if the OTodoAccess was changed + */ + void signalChanged( const OTodoAccess* ); +private: + /** * add an Alarm to the AlarmServer */ void addAlarm( const OTodo& ); /** * delete an alarm with the uid from * the alarm server */ void delAlarm( int uid ); -signals: - /** - * if the OTodoAccess was changed - */ - void signalChanged( const OTodoAccess* ); -private: int m_cat; OTodoAccessBackend* m_todoBackEnd; class OTodoAccessPrivate; OTodoAccessPrivate* d; }; #endif diff --git a/libopie2/opiepim/ocontact.cpp b/libopie2/opiepim/ocontact.cpp index 917eb0a..efa2777 100644 --- a/libopie2/opiepim/ocontact.cpp +++ b/libopie2/opiepim/ocontact.cpp @@ -74,1030 +74,1032 @@ OContact::OContact( const QMap<int, QString> &fromMap ) : setUid( uidGen().generate() ); }else setUid( uidStr.toInt() ); // if ( !uidStr.isEmpty() ) // setUid( uidStr.toInt() ); } /*! Destroys a contact. */ OContact::~OContact() { } /*! \fn void OContact::setTitle( const QString &str ) Sets the title of the contact to \a str. */ /*! \fn void OContact::setFirstName( const QString &str ) Sets the first name of the contact to \a str. */ /*! \fn void OContact::setMiddleName( const QString &str ) Sets the middle name of the contact to \a str. */ /*! \fn void OContact::setLastName( const QString &str ) Sets the last name of the contact to \a str. */ /*! \fn void OContact::setSuffix( const QString &str ) Sets the suffix of the contact to \a str. */ /*! \fn void OContact::setFileAs( const QString &str ) Sets the contact to filed as \a str. */ /*! \fn void OContact::setDefaultEmail( const QString &str ) Sets the default email of the contact to \a str. */ /*! \fn void OContact::setHomeStreet( const QString &str ) Sets the home street address of the contact to \a str. */ /*! \fn void OContact::setHomeCity( const QString &str ) Sets the home city of the contact to \a str. */ /*! \fn void OContact::setHomeState( const QString &str ) Sets the home state of the contact to \a str. */ /*! \fn void OContact::setHomeZip( const QString &str ) Sets the home zip code of the contact to \a str. */ /*! \fn void OContact::setHomeCountry( const QString &str ) Sets the home country of the contact to \a str. */ /*! \fn void OContact::setHomePhone( const QString &str ) Sets the home phone number of the contact to \a str. */ /*! \fn void OContact::setHomeFax( const QString &str ) Sets the home fax number of the contact to \a str. */ /*! \fn void OContact::setHomeMobile( const QString &str ) Sets the home mobile phone number of the contact to \a str. */ /*! \fn void OContact::setHomeWebpage( const QString &str ) Sets the home webpage of the contact to \a str. */ /*! \fn void OContact::setCompany( const QString &str ) Sets the company for contact to \a str. */ /*! \fn void OContact::setJobTitle( const QString &str ) Sets the job title of the contact to \a str. */ /*! \fn void OContact::setDepartment( const QString &str ) Sets the department for contact to \a str. */ /*! \fn void OContact::setOffice( const QString &str ) Sets the office for contact to \a str. */ /*! \fn void OContact::setBusinessStreet( const QString &str ) Sets the business street address of the contact to \a str. */ /*! \fn void OContact::setBusinessCity( const QString &str ) Sets the business city of the contact to \a str. */ /*! \fn void OContact::setBusinessState( const QString &str ) Sets the business state of the contact to \a str. */ /*! \fn void OContact::setBusinessZip( const QString &str ) Sets the business zip code of the contact to \a str. */ /*! \fn void OContact::setBusinessCountry( const QString &str ) Sets the business country of the contact to \a str. */ /*! \fn void OContact::setBusinessPhone( const QString &str ) Sets the business phone number of the contact to \a str. */ /*! \fn void OContact::setBusinessFax( const QString &str ) Sets the business fax number of the contact to \a str. */ /*! \fn void OContact::setBusinessMobile( const QString &str ) Sets the business mobile phone number of the contact to \a str. */ /*! \fn void OContact::setBusinessPager( const QString &str ) Sets the business pager number of the contact to \a str. */ /*! \fn void OContact::setBusinessWebpage( const QString &str ) Sets the business webpage of the contact to \a str. */ /*! \fn void OContact::setProfession( const QString &str ) Sets the profession of the contact to \a str. */ /*! \fn void OContact::setAssistant( const QString &str ) Sets the assistant of the contact to \a str. */ /*! \fn void OContact::setManager( const QString &str ) Sets the manager of the contact to \a str. */ /*! \fn void OContact::setSpouse( const QString &str ) Sets the spouse of the contact to \a str. */ /*! \fn void OContact::setGender( const QString &str ) Sets the gender of the contact to \a str. */ /*! \fn void OContact::setNickname( const QString &str ) Sets the nickname of the contact to \a str. */ /*! \fn void OContact::setNotes( const QString &str ) Sets the notes about the contact to \a str. */ /*! \fn QString OContact::title() const Returns the title of the contact. */ /*! \fn QString OContact::firstName() const Returns the first name of the contact. */ /*! \fn QString OContact::middleName() const Returns the middle name of the contact. */ /*! \fn QString OContact::lastName() const Returns the last name of the contact. */ /*! \fn QString OContact::suffix() const Returns the suffix of the contact. */ /*! \fn QString OContact::fileAs() const Returns the string the contact is filed as. */ /*! \fn QString OContact::defaultEmail() const Returns the default email address of the contact. */ /*! \fn QString OContact::emails() const Returns the list of email address for a contact separated by ';'s in a single string. */ /*! \fn QString OContact::homeStreet() const Returns the home street address of the contact. */ /*! \fn QString OContact::homeCity() const Returns the home city of the contact. */ /*! \fn QString OContact::homeState() const Returns the home state of the contact. */ /*! \fn QString OContact::homeZip() const Returns the home zip of the contact. */ /*! \fn QString OContact::homeCountry() const Returns the home country of the contact. */ /*! \fn QString OContact::homePhone() const Returns the home phone number of the contact. */ /*! \fn QString OContact::homeFax() const Returns the home fax number of the contact. */ /*! \fn QString OContact::homeMobile() const Returns the home mobile number of the contact. */ /*! \fn QString OContact::homeWebpage() const Returns the home webpage of the contact. */ /*! \fn QString OContact::company() const Returns the company for the contact. */ /*! \fn QString OContact::department() const Returns the department for the contact. */ /*! \fn QString OContact::office() const Returns the office for the contact. */ /*! \fn QString OContact::jobTitle() const Returns the job title of the contact. */ /*! \fn QString OContact::profession() const Returns the profession of the contact. */ /*! \fn QString OContact::assistant() const Returns the assistant of the contact. */ /*! \fn QString OContact::manager() const Returns the manager of the contact. */ /*! \fn QString OContact::businessStreet() const Returns the business street address of the contact. */ /*! \fn QString OContact::businessCity() const Returns the business city of the contact. */ /*! \fn QString OContact::businessState() const Returns the business state of the contact. */ /*! \fn QString OContact::businessZip() const Returns the business zip of the contact. */ /*! \fn QString OContact::businessCountry() const Returns the business country of the contact. */ /*! \fn QString OContact::businessPhone() const Returns the business phone number of the contact. */ /*! \fn QString OContact::businessFax() const Returns the business fax number of the contact. */ /*! \fn QString OContact::businessMobile() const Returns the business mobile number of the contact. */ /*! \fn QString OContact::businessPager() const Returns the business pager number of the contact. */ /*! \fn QString OContact::businessWebpage() const Returns the business webpage of the contact. */ /*! \fn QString OContact::spouse() const Returns the spouse of the contact. */ /*! \fn QString OContact::gender() const Returns the gender of the contact. */ /*! \fn QString OContact::nickname() const Returns the nickname of the contact. */ /*! \fn QString OContact::children() const Returns the children of the contact. */ /*! \fn QString OContact::notes() const Returns the notes relating to the the contact. */ /*! \fn QString OContact::groups() const \internal Returns the groups for the contact. */ /*! \fn QStringList OContact::groupList() const \internal */ /*! \fn QString OContact::field(int) const \internal */ /*! \fn void OContact::saveJournal( journal_action, const QString & = QString::null ) \internal */ /*! \fn void OContact::setUid( int id ) \internal Sets the uid for this record to \a id. */ /*! \enum OContact::journal_action \internal */ /*! \internal */ QMap<int, QString> OContact::toMap() const { QMap<int, QString> map = mMap; QString cats = idsToString( categories() ); if ( !cats.isEmpty() ) map.insert( Qtopia::AddressCategory, cats ); return map; } /*! Returns a rich text formatted QString representing the contents the contact. */ QString OContact::toRichText() const { QString text; QString value, comp, state; // name, jobtitle and company if ( !(value = fullName()).isEmpty() ) text += "<b>" + Qtopia::escapeString(value) + "</b><br>"; if ( !(value = jobTitle()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; comp = company(); if ( !(value = department()).isEmpty() ) { text += Qtopia::escapeString(value); if ( comp ) text += ", "; else text += "<br>"; } if ( !comp.isEmpty() ) text += Qtopia::escapeString(comp) + "<br>"; // business address if ( !businessStreet().isEmpty() || !businessCity().isEmpty() || !businessZip().isEmpty() || !businessCountry().isEmpty() ) { text += "<br>"; text += QObject::tr( "<b>Work Address:</b>" ); text += "<br>"; } if ( !(value = businessStreet()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; state = businessState(); if ( !(value = businessCity()).isEmpty() ) { text += Qtopia::escapeString(value); if ( state ) text += ", " + Qtopia::escapeString(state); text += "<br>"; } else if ( !state.isEmpty() ) text += Qtopia::escapeString(state) + "<br>"; if ( !(value = businessZip()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; if ( !(value = businessCountry()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; // home address if ( !homeStreet().isEmpty() || !homeCity().isEmpty() || !homeZip().isEmpty() || !homeCountry().isEmpty() ) { text += "<br>"; text += QObject::tr( "<b>Home Address:</b>" ); text += "<br>"; } if ( !(value = homeStreet()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; state = homeState(); if ( !(value = homeCity()).isEmpty() ) { text += Qtopia::escapeString(value); if ( !state.isEmpty() ) text += ", " + Qtopia::escapeString(state); text += "<br>"; } else if (!state.isEmpty()) text += Qtopia::escapeString(state) + "<br>"; if ( !(value = homeZip()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; if ( !(value = homeCountry()).isEmpty() ) text += Qtopia::escapeString(value) + "<br>"; // the others... QString str; str = emails(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Email Addresses: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = homePhone(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Home Phone: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = homeFax(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Home Fax: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = homeMobile(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Home Mobile: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = homeWebpage(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Home Web Page: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = businessWebpage(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Business Web Page: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = office(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Office: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = businessPhone(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Business Phone: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = businessFax(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Business Fax: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = businessMobile(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Business Mobile: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = businessPager(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Business Pager: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = profession(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Profession: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = assistant(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Assistant: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = manager(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Manager: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; str = gender(); if ( !str.isEmpty() && str.toInt() != 0 ) { if ( str.toInt() == 1 ) str = QObject::tr( "Male" ); else if ( str.toInt() == 2 ) str = QObject::tr( "Female" ); text += "<b>" + QObject::tr("Gender: ") + "</b>" + str + "<br>"; } str = spouse(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Spouse: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; if ( birthday().isValid() ){ str = TimeString::numberDateString( birthday() ); text += "<b>" + QObject::tr("Birthday: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; } if ( anniversary().isValid() ){ str = TimeString::numberDateString( anniversary() ); text += "<b>" + QObject::tr("Anniversary: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; } str = nickname(); if ( !str.isEmpty() ) text += "<b>" + QObject::tr("Nickname: ") + "</b>" + Qtopia::escapeString(str) + "<br>"; if ( categoryNames().count() ){ text += "<b>" + QObject::tr( "Category:") + "</b> "; text += categoryNames().join(", "); text += "<br>"; } // notes last if ( (value = notes()) ) { QRegExp reg("\n"); //QString tmp = Qtopia::escapeString(value); QString tmp = QStyleSheet::convertFromPlainText(value); //tmp.replace( reg, "<br>" ); text += "<br>" + tmp + "<br>"; } return text; } /*! \internal */ void OContact::insert( int key, const QString &v ) { QString value = v.stripWhiteSpace(); if ( value.isEmpty() ) mMap.remove( key ); else mMap.insert( key, value ); } /*! \internal */ void OContact::replace( int key, const QString & v ) { QString value = v.stripWhiteSpace(); if ( value.isEmpty() ) mMap.remove( key ); else mMap.replace( key, value ); } /*! \internal */ QString OContact::find( int key ) const { return mMap[key]; } /*! \internal */ QString OContact::displayAddress( const QString &street, const QString &city, const QString &state, const QString &zip, const QString &country ) const { QString s = street; if ( !street.isEmpty() ) s+= "\n"; s += city; if ( !city.isEmpty() && !state.isEmpty() ) s += ", "; s += state; if ( !state.isEmpty() && !zip.isEmpty() ) s += " "; s += zip; if ( !country.isEmpty() && !s.isEmpty() ) s += "\n"; s += country; return s; } /*! \internal */ QString OContact::displayBusinessAddress() const { return displayAddress( businessStreet(), businessCity(), businessState(), businessZip(), businessCountry() ); } /*! \internal */ QString OContact::displayHomeAddress() const { return displayAddress( homeStreet(), homeCity(), homeState(), homeZip(), homeCountry() ); } /*! Returns the full name of the contact */ QString OContact::fullName() const { QString title = find( Qtopia::Title ); QString firstName = find( Qtopia::FirstName ); QString middleName = find( Qtopia::MiddleName ); QString lastName = find( Qtopia::LastName ); QString suffix = find( Qtopia::Suffix ); QString name = title; if ( !firstName.isEmpty() ) { if ( !name.isEmpty() ) name += " "; name += firstName; } if ( !middleName.isEmpty() ) { if ( !name.isEmpty() ) name += " "; name += middleName; } if ( !lastName.isEmpty() ) { if ( !name.isEmpty() ) name += " "; name += lastName; } if ( !suffix.isEmpty() ) { if ( !name.isEmpty() ) name += " "; name += suffix; } return name.simplifyWhiteSpace(); } /*! Returns a list of the names of the children of the contact. */ QStringList OContact::childrenList() const { return QStringList::split( " ", find( Qtopia::Children ) ); } /*! \fn void OContact::insertEmail( const QString &email ) Insert \a email into the email list. Ensures \a email can only be added once. If there is no default email address set, it sets it to the \a email. */ /*! \fn void OContact::removeEmail( const QString &email ) Removes the \a email from the email list. If the default email was \a email, then the default email address is assigned to the first email in the email list */ /*! \fn void OContact::clearEmails() Clears the email list. */ /*! \fn void OContact::insertEmails( const QStringList &emailList ) Appends the \a emailList to the exiting email list */ /*! Returns a list of email addresses belonging to the contact, including the default email address. */ QStringList OContact::emailList() const { QString emailStr = emails(); QStringList r; if ( !emailStr.isEmpty() ) { qDebug(" emailstr "); QStringList l = QStringList::split( emailSeparator(), emailStr ); for ( QStringList::ConstIterator it = l.begin();it != l.end();++it ) r += (*it).simplifyWhiteSpace(); } return r; } /*! \overload Generates the string for the contact to be filed as from the first, middle and last name of the contact. */ void OContact::setFileAs() { QString lastName, firstName, middleName, fileas; lastName = find( Qtopia::LastName ); firstName = find( Qtopia::FirstName ); middleName = find( Qtopia::MiddleName ); if ( !lastName.isEmpty() && !firstName.isEmpty() && !middleName.isEmpty() ) fileas = lastName + ", " + firstName + " " + middleName; else if ( !lastName.isEmpty() && !firstName.isEmpty() ) fileas = lastName + ", " + firstName; else if ( !lastName.isEmpty() || !firstName.isEmpty() || !middleName.isEmpty() ) fileas = firstName + ( firstName.isEmpty() ? "" : " " ) + middleName + ( middleName.isEmpty() ? "" : " " ) + lastName; replace( Qtopia::FileAs, fileas ); } /*! \internal Appends the contact information to \a buf. */ void OContact::save( QString &buf ) const { static const QStringList SLFIELDS = fields(); // I'm expecting "<Contact " in front of this... for ( QMap<int, QString>::ConstIterator it = mMap.begin(); it != mMap.end(); ++it ) { const QString &value = it.data(); int key = it.key(); if ( !value.isEmpty() ) { if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid) continue; key -= Qtopia::AddressCategory+1; buf += SLFIELDS[key]; buf += "=\"" + Qtopia::escapeString(value) + "\" "; } } buf += customToXml(); if ( categories().count() > 0 ) buf += "Categories=\"" + idsToString( categories() ) + "\" "; buf += "Uid=\"" + QString::number( uid() ) + "\" "; // You need to close this yourself } /*! \internal Returns the list of fields belonging to a contact Never change order of this list ! It has to be regarding enum AddressBookFields !! */ QStringList OContact::fields() { QStringList list; list.append( "Title" ); // Not Used! list.append( "FirstName" ); list.append( "MiddleName" ); list.append( "LastName" ); list.append( "Suffix" ); list.append( "FileAs" ); list.append( "JobTitle" ); list.append( "Department" ); list.append( "Company" ); list.append( "BusinessPhone" ); list.append( "BusinessFax" ); list.append( "BusinessMobile" ); list.append( "DefaultEmail" ); list.append( "Emails" ); list.append( "HomePhone" ); list.append( "HomeFax" ); list.append( "HomeMobile" ); list.append( "BusinessStreet" ); list.append( "BusinessCity" ); list.append( "BusinessState" ); list.append( "BusinessZip" ); list.append( "BusinessCountry" ); list.append( "BusinessPager" ); list.append( "BusinessWebPage" ); list.append( "Office" ); list.append( "Profession" ); list.append( "Assistant" ); list.append( "Manager" ); list.append( "HomeStreet" ); list.append( "HomeCity" ); list.append( "HomeState" ); list.append( "HomeZip" ); list.append( "HomeCountry" ); list.append( "HomeWebPage" ); list.append( "Spouse" ); list.append( "Gender" ); list.append( "Birthday" ); list.append( "Anniversary" ); list.append( "Nickname" ); list.append( "Children" ); list.append( "Notes" ); list.append( "Groups" ); return list; } /*! Sets the list of email address for contact to those contained in \a str. Email address should be separated by ';'s. */ void OContact::setEmails( const QString &str ) { replace( Qtopia::Emails, str ); if ( str.isEmpty() ) setDefaultEmail( QString::null ); } /*! Sets the list of children for the contact to those contained in \a str. */ void OContact::setChildren( const QString &str ) { replace( Qtopia::Children, str ); } /*! Returns TRUE if the contact matches the regular expression \a regexp. Otherwise returns FALSE. */ bool OContact::match( const QString ®exp ) const { return match(QRegExp(regexp)); } /*! \overload Returns TRUE if the contact matches the regular expression \a regexp. Otherwise returns FALSE. */ bool OContact::match( const QRegExp &r ) const { bool match; match = false; QMap<int, QString>::ConstIterator it; for ( it = mMap.begin(); it != mMap.end(); ++it ) { if ( (*it).find( r ) > -1 ) { match = true; break; } } return match; } QString OContact::toShortText() const { return ( fullName() ); } QString OContact::type() const { return QString::fromLatin1( "OContact" ); } // Definition is missing ! (se) QMap<QString,QString> OContact::toExtraMap() const { qWarning ("Function not implemented: OContact::toExtraMap()"); QMap <QString,QString> useless; return useless; } class QString OContact::recordField( int pos ) const { QStringList SLFIELDS = fields(); // ?? why this ? (se) return SLFIELDS[pos]; } // In future releases, we should store birthday and anniversary // internally as QDate instead of QString ! // QString is always too complicate to interprete (DD.MM.YY, DD/MM/YY, MM/DD/YY, etc..)(se) /*! \fn void OContact::setBirthday( const QDate& date ) Sets the birthday for the contact to \a date. If date is null the current stored date will be removed. */ void OContact::setBirthday( const QDate &v ) { if ( v.isNull() ){ qWarning( "Remove Birthday"); replace( Qtopia::Birthday, QString::null ); return; } if ( v.isValid() ) replace( Qtopia::Birthday, TimeConversion::toString( v ) ); } /*! \fn void OContact::setAnniversary( const QDate &date ) Sets the anniversary of the contact to \a date. If date is null, the current stored date will be removed. */ void OContact::setAnniversary( const QDate &v ) { if ( v.isNull() ){ qWarning( "Remove Anniversary"); replace( Qtopia::Anniversary, QString::null ); return; } if ( v.isValid() ) replace( Qtopia::Anniversary, TimeConversion::toString( v ) ); } /*! \fn QDate OContact::birthday() const Returns the birthday of the contact. */ QDate OContact::birthday() const { QString str = find( Qtopia::Birthday ); qWarning ("Birthday %s", str.latin1() ); if ( !str.isEmpty() ) return TimeConversion::fromString ( str ); else return QDate(); } /*! \fn QDate OContact::anniversary() const Returns the anniversary of the contact. */ QDate OContact::anniversary() const { QDate empty; QString str = find( Qtopia::Anniversary ); qWarning ("Anniversary %s", str.latin1() ); if ( !str.isEmpty() ) return TimeConversion::fromString ( str ); else return empty; } void OContact::insertEmail( const QString &v ) { //qDebug("insertEmail %s", v.latin1()); QString e = v.simplifyWhiteSpace(); QString def = defaultEmail(); // if no default, set it as the default email and don't insert if ( def.isEmpty() ) { setDefaultEmail( e ); // will insert into the list for us return; } // otherwise, insert assuming doesn't already exist QString emailsStr = find( Qtopia::Emails ); if ( emailsStr.contains( e )) return; if ( !emailsStr.isEmpty() ) emailsStr += emailSeparator(); emailsStr += e; replace( Qtopia::Emails, emailsStr ); } void OContact::removeEmail( const QString &v ) { QString e = v.simplifyWhiteSpace(); QString def = defaultEmail(); QString emailsStr = find( Qtopia::Emails ); QStringList emails = emailList(); // otherwise, must first contain it if ( !emailsStr.contains( e ) ) return; // remove it //qDebug(" removing email from list %s", e.latin1()); emails.remove( e ); // reset the string emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator replace( Qtopia::Emails, emailsStr ); // if default, then replace the default email with the first one if ( def == e ) { //qDebug("removeEmail is default; setting new default"); if ( !emails.count() ) clearEmails(); else // setDefaultEmail will remove e from the list setDefaultEmail( emails.first() ); } } void OContact::clearEmails() { mMap.remove( Qtopia::DefaultEmail ); mMap.remove( Qtopia::Emails ); } void OContact::setDefaultEmail( const QString &v ) { QString e = v.simplifyWhiteSpace(); //qDebug("OContact::setDefaultEmail %s", e.latin1()); replace( Qtopia::DefaultEmail, e ); if ( !e.isEmpty() ) insertEmail( e ); } void OContact::insertEmails( const QStringList &v ) { for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it ) insertEmail( *it ); } - +int OContact::rtti() { + return 2; +} void OContact::setUid( int i ) { OPimRecord::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); } diff --git a/libopie2/opiepim/ocontact.h b/libopie2/opiepim/ocontact.h index d97af1c..65ba43e 100644 --- a/libopie2/opiepim/ocontact.h +++ b/libopie2/opiepim/ocontact.h @@ -1,238 +1,239 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** Copyright (C) 2002 by Stefan Eilers (eilers.stefan@epost.de) ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __OCONTACT_H__ #define __OCONTACT_H__ #include <opie/opimrecord.h> #include <qpe/recordfields.h> #include <qdatetime.h> #include <qstringlist.h> #if defined(QPC_TEMPLATEDLL) // MOC_SKIP_BEGIN QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>; // MOC_SKIP_END #endif class ContactPrivate; class QPC_EXPORT OContact : public OPimRecord { friend class DataSet; public: OContact(); OContact( const QMap<int, QString> &fromMap ); virtual ~OContact(); enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; - /* + /* * do we need to inline them * if yes do we need to inline them this way? * -zecke */ void setTitle( const QString &v ) { replace( Qtopia::Title, v ); } void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); } void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); } void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); } void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); } void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); } void setFileAs(); // default email address void setDefaultEmail( const QString &v ); // inserts email to list and ensure's doesn't already exist void insertEmail( const QString &v ); void removeEmail( const QString &v ); void clearEmails(); void insertEmails( const QStringList &v ); // home void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); } void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); } void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); } void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); } void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); } void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); } void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); } void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); } void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); } // business void setCompany( const QString &v ) { replace( Qtopia::Company, v ); } void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); } void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); } void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); } void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); } void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); } void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); } void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); } void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); } void setOffice( const QString &v ) { replace( Qtopia::Office, v ); } void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); } void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); } void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); } void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); } void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); } void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); } void setManager( const QString &v ) { replace( Qtopia::Manager, v ); } // personal void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); } void setGender( const QString &v ) { replace( Qtopia::Gender, v ); } void setBirthday( const QDate &v ); void setAnniversary( const QDate &v ); void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); } void setChildren( const QString &v ); // other void setNotes( const QString &v ) { replace( Qtopia::Notes, v); } bool match( const QString ®exp ) const; bool match( const QRegExp ®exp ) const; // // custom // void setCustomField( const QString &key, const QString &v ) // { replace(Custom- + key, v ); } // name QString fullName() const; QString title() const { return find( Qtopia::Title ); } QString firstName() const { return find( Qtopia::FirstName ); } QString middleName() const { return find( Qtopia::MiddleName ); } QString lastName() const { return find( Qtopia::LastName ); } QString suffix() const { return find( Qtopia::Suffix ); } QString fileAs() const { return find( Qtopia::FileAs ); } // email QString defaultEmail() const { return find( Qtopia::DefaultEmail ); } QStringList emailList() const; // home /* * OPimAddress address(enum Location)const; * would be some how nicer... * -zecke */ QString homeStreet() const { return find( Qtopia::HomeStreet ); } QString homeCity() const { return find( Qtopia::HomeCity ); } QString homeState() const { return find( Qtopia::HomeState ); } QString homeZip() const { return find( Qtopia::HomeZip ); } QString homeCountry() const { return find( Qtopia::HomeCountry ); } QString homePhone() const { return find( Qtopia::HomePhone ); } QString homeFax() const { return find( Qtopia::HomeFax ); } QString homeMobile() const { return find( Qtopia::HomeMobile ); } QString homeWebpage() const { return find( Qtopia::HomeWebPage ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayHomeAddress() const; // business QString company() const { return find( Qtopia::Company ); } QString businessStreet() const { return find( Qtopia::BusinessStreet ); } QString businessCity() const { return find( Qtopia::BusinessCity ); } QString businessState() const { return find( Qtopia::BusinessState ); } QString businessZip() const { return find( Qtopia::BusinessZip ); } QString businessCountry() const { return find( Qtopia::BusinessCountry ); } QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); } QString jobTitle() const { return find( Qtopia::JobTitle ); } QString department() const { return find( Qtopia::Department ); } QString office() const { return find( Qtopia::Office ); } QString businessPhone() const { return find( Qtopia::BusinessPhone ); } QString businessFax() const { return find( Qtopia::BusinessFax ); } QString businessMobile() const { return find( Qtopia::BusinessMobile ); } QString businessPager() const { return find( Qtopia::BusinessPager ); } QString profession() const { return find( Qtopia::Profession ); } QString assistant() const { return find( Qtopia::Assistant ); } QString manager() const { return find( Qtopia::Manager ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayBusinessAddress() const; //personal QString spouse() const { return find( Qtopia::Spouse ); } QString gender() const { return find( Qtopia::Gender ); } QDate birthday() const; QDate anniversary() const; QString nickname() const { return find( Qtopia::Nickname ); } QString children() const { return find( Qtopia::Children ); } QStringList childrenList() const; // other QString notes() const { return find( Qtopia::Notes ); } QString groups() const { return find( Qtopia::Groups ); } QStringList groupList() const; // // custom // const QString &customField( const QString &key ) // { return find( Custom- + key ); } QString toRichText() const; QMap<int, QString> toMap() const; QString field( int key ) const { return find( key ); } void setUid( int i ); QString toShortText()const; QString OContact::type()const; QMap<QString,QString> OContact::toExtraMap() const; class QString OContact::recordField(int) const; // Why private ? (eilers,se) QString emailSeparator() const { return " "; } // the emails should be seperated by a comma void setEmails( const QString &v ); QString emails() const { return find( Qtopia::Emails ); } + static int rtti(); private: // The XML-Backend needs some access to the private functions friend class OContactAccessBackend_XML; void insert( int key, const QString &value ); void replace( int key, const QString &value ); QString find( int key ) const; static QStringList fields(); void save( QString &buf ) const; QString displayAddress( const QString &street, const QString &city, const QString &state, const QString &zip, const QString &country ) const; QMap<int, QString> mMap; ContactPrivate *d; }; #endif diff --git a/libopie2/opiepim/otodo.cpp b/libopie2/opiepim/otodo.cpp index 6fcf9f6..ece624a 100644 --- a/libopie2/opiepim/otodo.cpp +++ b/libopie2/opiepim/otodo.cpp @@ -1,423 +1,421 @@ #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 "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; - bool hasAlarmDateTime :1; - QDateTime alarmDateTime; 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 ); - data->hasAlarmDateTime = false; - } 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 ); - data->hasAlarmDateTime = false; - } 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::hasAlarmDateTime() const -{ - return data->hasAlarmDateTime; +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; } - -QDateTime OTodo::alarmDateTime() const -{ - return data->alarmDateTime; +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::setHasAlarmDateTime( bool hasAlarmDateTime ) -{ - changeOrModify(); - data->hasAlarmDateTime = hasAlarmDateTime; -} 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( QDate date ) +void OTodo::setDueDate( const QDate& date ) { changeOrModify(); data->date = date; } -void OTodo::setAlarmDateTime( const QDateTime& alarm ) -{ +void OTodo::setStartDate( const QDate& date ) { changeOrModify(); - data->alarmDateTime = alarm; + 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>"; } - if (hasAlarmDateTime() ){ - text += "<b>" + QObject::tr( "Alarmed Notification:") + " </b>"; - text += alarmDateTime().toString(); - text += "<br>"; - } text += "<b>" + QObject::tr( "Category:") + "</b> "; text += categoryNames().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->hasAlarmDateTime != toDoEvent.data->hasAlarmDateTime ) - return false; - if ( data->alarmDateTime != toDoEvent.data->alarmDateTime ) - 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 ) { 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() ); - map.insert( HasAlarmDateTime, QString::number( data->hasAlarmDateTime ) ); - map.insert( AlarmDateTime, data->alarmDateTime.toString() ); - + /* 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->hasAlarmDateTime = src->hasAlarmDateTime; - dest->alarmDateTime = src->alarmDateTime; 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 1; +} diff --git a/libopie2/opiepim/otodo.h b/libopie2/opiepim/otodo.h index 70b0253..2f66f55 100644 --- a/libopie2/opiepim/otodo.h +++ b/libopie2/opiepim/otodo.h @@ -1,246 +1,273 @@ #ifndef OPIE_TODO_EVENT_H #define OPIE_TODO_EVENT_H #include <qarray.h> #include <qmap.h> #include <qregexp.h> #include <qstringlist.h> #include <qdatetime.h> #include <qvaluelist.h> #include <qpe/recordfields.h> #include <qpe/palmtopuidgen.h> #include <opie/opimrecord.h> class OPimState; class ORecur; class OPimMaintainer; +class OPimNotifyManager; class OTodo : public OPimRecord { public: typedef QValueList<OTodo> ValueList; enum RecordFields { Uid = Qtopia::UID_ID, Category = Qtopia::CATEGORY_ID, HasDate, Completed, Description, Summary, Priority, DateDay, DateMonth, DateYear, Progress, CrossReference, - HasAlarmDateTime, - AlarmDateTime, State, - Recurrance, + Recurrence, Alarms, Reminders, - Notifiers + Notifiers, + Maintainer, + StartDate, + CompletedDate }; public: // priorities from Very low to very high enum TaskPriority { 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 **/ OTodo( 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 = 0 /*empty*/ ); OTodo( bool completed, int priority, const QArray<int>& category, const QString& summary = QString::null, const QString& description = QString::null, ushort progress = 0, bool hasDate = false, QDate date = QDate::currentDate(), int uid = 0 /* empty */ ); - /* Copy c'tor - - **/ + /** Copy c'tor + * + */ OTodo(const OTodo & ); /** *destructor */ ~OTodo(); /** * Is this event completed? */ bool isCompleted() const; /** * Does this Event have a deadline */ bool hasDueDate() const; + bool hasStartDate()const; + bool hasCompletedDate()const; /** * Does this Event has an alarm time ? */ bool hasAlarmDateTime() const; /** * What is the priority? */ int priority()const ; /** * progress as ushort 0, 20, 40, 60, 80 or 100% */ ushort progress() const; /** * The due Date */ QDate dueDate()const; /** - * Alarm Date and Time + * When did it start? + */ + QDate startDate()const; + + /** + * When was it completed? */ - QDateTime alarmDateTime()const; + QDate completedDate()const; /** * What is the state of this OTodo? */ OPimState state()const; /** * the recurrance of this */ ORecur recurrence()const; /** * the Maintainer of this OTodo */ OPimMaintainer maintainer()const; /** * The description of the todo */ QString description()const; /** * A small summary of the todo */ QString summary() const; /** * @reimplemented * Return this todoevent in a RichText formatted QString */ QString toRichText() const; + /* + * check if the sharing is still fine!! -zecke + */ + /** + * return a reference to our notifiers... + */ + OPimNotifyManager ¬ifiers(); + /** - * reimplementation + * reimplementations */ QString type()const; QString toShortText()const; QMap<QString, QString> toExtraMap()const; QString recordField(int id )const; /** * toMap puts all data into the map. int relates * to ToDoEvent RecordFields enum */ QMap<int, QString> toMap()const; /** * Set if this Todo is completed */ void setCompleted(bool completed ); /** * set if this todo got an end data */ void setHasDueDate( bool hasDate ); - - /** - * set if this todo has an alarm time and date - */ - void setHasAlarmDateTime ( bool hasAlarm ); + // FIXME we do not have these for start, completed + // cause we'll use the isNull() of QDate for figuring + // out if it's has a date... + // decide what to do here? -zecke /** * Set the priority of the Todo */ void setPriority(int priority ); /** * Set the progress. */ void setProgress( ushort progress ); /** * set the end date */ - void setDueDate( QDate date ); + void setDueDate( const QDate& date ); + /** + * set the start date + */ + void setStartDate( const QDate& date ); + + /** + * set the completed date + */ + void setCompletedDate( const QDate& date ); void setRecurrence( const ORecur& ); /** * set the alarm time */ void setAlarmDateTime ( const QDateTime& alarm ); void setDescription(const QString& ); void setSummary(const QString& ); /** * set the state of a Todo * @param state State what the todo should take */ void setState( const OPimState& state); /** * set the Maintainer Mode */ void setMaintainer( const OPimMaintainer& ); bool isOverdue(); bool match( const QRegExp &r )const; bool operator<(const OTodo &toDoEvent )const; bool operator<=(const OTodo &toDoEvent )const; bool operator!=(const OTodo &toDoEvent )const; bool operator>(const OTodo &toDoEvent )const; bool operator>=(const OTodo &toDoEvent)const; bool operator==(const OTodo &toDoEvent )const; OTodo &operator=(const OTodo &toDoEvent ); + static int rtti(); + private: class OTodoPrivate; struct OTodoData; void deref(); inline void changeOrModify(); void copy( OTodoData* src, OTodoData* dest ); OTodoPrivate *d; OTodoData *data; }; inline bool OTodo::operator!=(const OTodo &toDoEvent )const { return !(*this == toDoEvent); } #endif diff --git a/libopie2/opiepim/ui/opimmainwindow.cpp b/libopie2/opiepim/ui/opimmainwindow.cpp new file mode 100644 index 0000000..92be2fd --- a/dev/null +++ b/libopie2/opiepim/ui/opimmainwindow.cpp @@ -0,0 +1,71 @@ +#include <qapplication.h> +#include <qcopchannel_qws.h> + +#include <qpe/qcopenvelope_qws.h> + +#include "opimmainwindow.h" + +OPimMainWindow::OPimMainWindow( const QString& service, QWidget* parent, + const char* name, WFlags flag ) + : QMainWindow( parent, name, flag ), m_service( service ), m_fallBack(0l) { + + /* + * let's generate our QCopChannel + */ + m_str = QString("QPE/"+m_service).local8Bit(); + m_channel= new QCopChannel(m_str, this ); + connect(m_channel, SIGNAL(received(const QCString&, const QByteArray& ) ), + this, SLOT( appMessage( const QCString&, const QByteArray& ) ) ); + + /* connect flush and reload */ + connect(qApp, SIGNAL(flush() ), + this, SLOT(flush() ) ); + connect(qApp, SIGNAL(reload() ), + this, SLOT(reload() ) ); +} +OPimMainWindow::~OPimMainWindow() { + delete m_channel; +} +QCopChannel* OPimMainWindow::channel() { + return m_channel; +} +void OPimMainWindow::appMessage( const QCString& cmd, const QByteArray& array ) { + /* + * create demands to create + * a new record... + */ + QDataStream stream(array, IO_ReadOnly); + if ( cmd == "create()" ) { + int uid = create(); + QCopEnvelope e(m_str, "created(int)" ); + e << uid; + }else if ( cmd == "remove(int)" ) { + int uid; + stream >> uid; + bool rem = remove( uid ); + QCopEnvelope e(m_str, "removed(bool)" ); + e << rem; + }else if ( cmd == "beam(int,int)" ) { + int uid, trans; + stream >> uid; + stream >> trans; + beam( uid, trans ); + }else if ( cmd == "show(int)" ) { + int uid; + stream >> uid; + show( uid ); + }else if ( cmd == "edit(int)" ) { + int uid; + stream >> uid; + edit( uid ); + }else if ( cmd == "add(int,QByteArray)" ) { + int rtti; + QByteArray array; + stream >> rtti; + stream >> array; + m_fallBack = record(rtti, array ); + if (!m_fallBack) return; + add( *m_fallBack ); + delete m_fallBack; + } +} diff --git a/libopie2/opiepim/ui/opimmainwindow.h b/libopie2/opiepim/ui/opimmainwindow.h new file mode 100644 index 0000000..94100bd --- a/dev/null +++ b/libopie2/opiepim/ui/opimmainwindow.h @@ -0,0 +1,79 @@ +#ifndef OPIE_PIM_MAINWINDOW_H +#define OPIE_PIM_MAINWINDOW_H + +#include <qmainwindow.h> + +#include <opie/opimrecord.h> + +/** + * This is a common Opie PIM MainWindow + * it takes care of the QCOP internals + * and implements some functions + * for the URL scripting schema + */ +/* + * due Qt and Templates with signal and slots + * do not work that good :( + * (Ok how to moc a template ;) ) + * We will have the mainwindow which calls a struct which + * is normally reimplemented as a template ;) + */ + +class QCopChannel; +class OPimMainWindow : public QMainWindow { + Q_OBJECT +public: + enum TransPort { BlueTooth=0, + IrDa }; + + OPimMainWindow( const QString& service, QWidget *parent = 0, const char* name = 0, + WFlags f = WType_TopLevel); + virtual ~OPimMainWindow(); + + +protected slots: + /* for syncing */ + virtual void flush() = 0; + virtual void reload() = 0; + + /** create a new Records and return the uid */ + virtual int create() = 0; + /** remove a record with UID == uid */ + virtual bool remove( int uid ) = 0; + /** beam the record with UID = uid */ + virtual void beam( int uid , int transport = IrDa) = 0; + + /** show the record with UID == uid */ + virtual void show( int uid ) = 0; + /** edit the record */ + virtual void edit( int uid ) = 0; + + /** make a copy of it! */ + virtual void add( const OPimRecord& ) = 0; + + /* I would love to do this as a template + * but can't think of a right way + * because I need signal and slots -zecke + */ + /* + * the only pointer in the whole PIM API :( + */ + virtual OPimRecord* record( int rtti, const QByteArray& ) = 0; + QCopChannel* channel(); + +private slots: + void appMessage( const QCString&, const QByteArray& ); + + +private: + class Private; + Private* d; + + QCopChannel* m_channel; + QString m_service; + QCString m_str; + OPimRecord* m_fallBack; +}; + + +#endif |