24 files changed, 1330 insertions, 130 deletions
diff --git a/libopie/pim/opimaccessbackend.h b/libopie/pim/opimaccessbackend.h index 5707b58..c27acbb 100644 --- a/libopie/pim/opimaccessbackend.h +++ b/libopie/pim/opimaccessbackend.h @@ -14,66 +14,66 @@ * the resource the implementation takes care * of */ template <class T = OPimRecord> class OPimAccessBackend { public: OPimAccessBackend(); virtual ~OPimAccessBackend(); - + /** * load the resource */ - virtual void load() = 0; - + virtual bool load() = 0; + /** * reload the resource */ - virtual void reload() = 0; - + virtual bool reload() = 0; + /** * save the resource and * all it's changes */ - virtual void save() = 0; - + virtual bool save() = 0; + /** * return an array of * all available uids */ virtual QArray<int> allRecords()const = 0; - + /** * queryByExample for T with the SortOrder * sort */ virtual QArray<int> queryByExample( const T& t, int sort ) = 0; - + /** * find the OPimRecord with uid @param uid * returns T and T.isEmpty() if nothing was found */ - virtual T find(int uid ) = 0; - + virtual T find(int uid )const = 0; + /** * clear the back end */ virtual void clear() = 0; - + /** * add T */ virtual bool add( const T& t ) = 0; - + /** * remove */ virtual bool remove( int uid ) = 0; - + /** * replace a record with T.uid() */ virtual bool replace( const T& t ) = 0; }; diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h index 36f5a99..31ab516 100644 --- a/libopie/pim/opimaccesstemplate.h +++ b/libopie/pim/opimaccesstemplate.h @@ -9,17 +9,17 @@ #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 + * 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; @@ -31,85 +31,86 @@ public: enum SortOrder { WildCards = 0, IgnoreCase = 1, RegExp = 2, ExactMatch = 4 }; /** * c'tor BackEnd */ OPimAccessTemplate( BackEnd* end); virtual ~OPimAccessTemplate(); - + /** * load from the backend */ - virtual void load(); - + virtual bool load(); + /** * reload from the backend */ - virtual void reload(); - + virtual bool reload(); + /** - * save to the backend + * save to the backend */ - virtual void save(); + virtual bool save(); /** * if the resource was changed externally */ bool wasChangedExternally()const; - + /** * return a List of records * you can iterate over them */ virtual List allRecords()const; - + /** - * queryByExample + * queryByExample */ virtual List queryByExample( const T& t, int sortOrder ); - + /** * find the OPimRecord uid */ - virtual T find( int uid ); + virtual T find( int uid )const; /* invalidate cache here */ /** * clears the backend and invalidates the backend */ virtual void clear() ; - + /** * add T to the backend */ virtual bool add( const T& t ) ; /* only the uid matters */ /** * remove T from the backend */ virtual bool remove( const T& t ); - + /** * remove the OPimRecord with uid */ virtual bool remove( int uid ); - + /** * replace T from backend */ virtual bool replace( const T& t) ; protected: /** * invalidate the cache */ void invalidateCache(); - + + void setBackEnd( BackEnd* end ); /** * returns the backend */ BackEnd* backEnd(); BackEnd* m_backEnd; }; @@ -120,43 +121,43 @@ OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) } template <class T> OPimAccessTemplate<T>::~OPimAccessTemplate() { qWarning("~OPimAccessTemplate<T>"); delete m_backEnd; } template <class T> -void OPimAccessTemplate<T>::load() { - m_backEnd->load(); +bool OPimAccessTemplate<T>::load() { + return m_backEnd->load(); } template <class T> -void OPimAccessTemplate<T>::reload() { - m_backEnd->reload(); +bool OPimAccessTemplate<T>::reload() { + return m_backEnd->reload(); } template <class T> -void OPimAccessTemplate<T>::save() { - m_backEnd->save(); +bool OPimAccessTemplate<T>::save() { + return m_backEnd->save(); } template <class T> OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { QArray<int> ints = m_backEnd->allRecords(); List lis(ints, this ); return lis; } template <class T> 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 ) { +T OPimAccessTemplate<T>::find( int uid ) const{ T t = m_backEnd->find( uid ); return t; } template <class T> void OPimAccessTemplate<T>::clear() { invalidateCache(); m_backEnd->clear(); } @@ -183,9 +184,13 @@ void OPimAccessTemplate<T>::invalidateCache() { template <class T> 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; +} #endif diff --git a/libopie/pim/orecordlist.h b/libopie/pim/orecordlist.h index 3b30a73..75bb33c 100644 --- a/libopie/pim/orecordlist.h +++ b/libopie/pim/orecordlist.h @@ -9,38 +9,40 @@ /** * Our List Iterator * it behaves like STL or Qt * * for(it = list.begin(); it != list.end(); ++it ) * doSomeCoolStuff( (*it) ); */ +template <class T> class ORecordList; template <class T = OPimRecord> class ORecordListIterator { + friend class ORecordList<T>; public: typedef OTemplateBase<T> Base; - + /** * The c'tor used internally from * ORecordList */ ORecordListIterator( const QArray<int>, const Base* ); - + /** * The standard c'tor */ ORecordListIterator(); ~ORecordListIterator(); - + ORecordListIterator( const ORecordListIterator& ); ORecordListIterator &operator=(const ORecordListIterator& ); - + /** - * a * operator ;) + * a * operator ;) * use it like this T = (*it); */ T &operator*(); ORecordListIterator &operator++(); ORecordListIterator &operator--(); bool operator==( const ORecordListIterator& it ); bool operator!=( const ORecordListIterator& it ); @@ -54,35 +56,35 @@ private: /* d pointer for future versions */ class IteratorPrivate; IteratorPrivate *d; }; /** * The recordlist used as a return type * from OPimAccessTemplate - */ + */ template <class T = OPimRecord > class ORecordList { public: typedef OTemplateBase<T> Base; typedef ORecordListIterator<T> Iterator; - - /** + + /** * c'tor */ ORecordList( const QArray<int>& ids, const Base* ); ~ORecordList(); - + /** * the first iterator */ Iterator begin(); - + /** * the end */ Iterator end(); /* ConstIterator begin()const; ConstIterator end()const; */ @@ -100,16 +102,17 @@ ORecordListIterator<T>::ORecordListIterator() { } template <class T> ORecordListIterator<T>::~ORecordListIterator() { /* nothing to delete */ } template <class T> ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) { + qWarning("ORecordListIterator"); m_uids = it.m_uids; m_current = it.m_current; m_temp = it.m_temp; m_end = it.m_end; m_record = it.m_record; } template <class T> @@ -120,27 +123,28 @@ ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIter m_end = it.m_end; m_record = it.m_record; return *this; } template <class T> T &ORecordListIterator<T>::operator*() { + qWarning("operator* %d %d", m_current, m_uids[m_current] ); if (!m_end ) m_record = m_temp->find( m_uids[m_current] ); else m_record = T(); return m_record; } template <class T> ORecordListIterator<T> &ORecordListIterator<T>::operator++() { - if (m_current < m_uids.count() ) { + if (m_current < (int)m_uids.count() ) { m_end = false; ++m_current; }else m_end = true; return *this; } template <class T> @@ -184,18 +188,21 @@ ORecordList<T>::ORecordList( const QArray<int>& ids, { } template <class T> ORecordList<T>::~ORecordList() { /* nothing to do here */ } template <class T> ORecordList<T>::Iterator ORecordList<T>::begin() { + qWarning("ORecordList::begin"); Iterator it( m_ids, m_acc ); return it; } template <class T> ORecordList<T>::Iterator ORecordList<T>::end() { Iterator it( m_ids, m_acc ); it.m_end = true; it.m_current = m_ids.count(); + + return it; } #endif diff --git a/libopie/pim/otemplatebase.h b/libopie/pim/otemplatebase.h index add1de4..f71417b 100644 --- a/libopie/pim/otemplatebase.h +++ b/libopie/pim/otemplatebase.h @@ -8,14 +8,14 @@ */ template <class T = OPimRecord> class OTemplateBase { public: OTemplateBase() { }; virtual ~OTemplateBase() { } - virtual T find( int uid ) = 0; + virtual T find( int uid )const = 0; }; #endif diff --git a/libopie/pim/otodo.cpp b/libopie/pim/otodo.cpp index 8239ba6..b3c14e6 100644 --- a/libopie/pim/otodo.cpp +++ b/libopie/pim/otodo.cpp @@ -31,36 +31,39 @@ struct OTodo::OTodoData : public QShared { bool hasAlarmDateTime :1; QDateTime alarmDateTime; }; OTodo::OTodo(const OTodo &event ) : OPimRecord( event ), data( event.data ) { data->ref(); - //qWarning("ref up"); + qWarning("ref up"); } OTodo::~OTodo() { + qWarning("~OTodo " + data->sum ); if ( data->deref() ) { - //qWarning("OTodo::dereffing"); + 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"); + 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; @@ -69,20 +72,22 @@ OTodo::OTodo(bool completed, int priority, 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"); + 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; @@ -345,17 +350,17 @@ QMap<QString, QString> OTodo::toExtraMap()const { } /** * 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"); + qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } void OTodo::copy( OTodoData* src, OTodoData* dest ) { dest->date = src->date; diff --git a/libopie/pim/otodo.h b/libopie/pim/otodo.h index 75af44c..1443e4f 100644 --- a/libopie/pim/otodo.h +++ b/libopie/pim/otodo.h @@ -130,26 +130,16 @@ public: * reimplementation */ QString type()const; QString toShortText()const; QMap<QString, QString> toExtraMap()const; QString recordField(int id )const; /** - * returns a list of apps which have related items - */ - QStringList relatedApps()const; - - /** - * returns all relations for one app - */ - QArray<int> relations( const QString& app )const; - - /** * toMap puts all data into the map. int relates * to ToDoEvent RecordFields enum */ QMap<int, QString> toMap()const; /** * Set if this Todo is completed */ diff --git a/libopie/pim/otodoaccess.cpp b/libopie/pim/otodoaccess.cpp new file mode 100644 index 0000000..a65cf5c --- a/dev/null +++ b/libopie/pim/otodoaccess.cpp @@ -0,0 +1,71 @@ +#include <qdatetime.h> + +#include <qpe/alarmserver.h> + +#include "otodoaccessxml.h" +#include "otodoaccess.h" + + +OTodoAccess::OTodoAccess( OTodoAccessBackend* end ) + : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end ) +{ + if (end == 0l ) + m_todoBackEnd = new OTodoAccessXML( "Todolist" ); + + 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() ) + 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 ); +} + diff --git a/libopie/pim/otodoaccess.h b/libopie/pim/otodoaccess.h new file mode 100644 index 0000000..c43efe9 --- a/dev/null +++ b/libopie/pim/otodoaccess.h @@ -0,0 +1,79 @@ +#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: + /** + * if you use 0l + * the default resource will be + * icked 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(); + /** + * merge a list of OTodos into + * the resource + */ + void mergeWith( const QValueList<OTodo>& ); + + /** + * 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: + OTodoAccessBackend* m_todoBackEnd; + class OTodoAccessPrivate; + OTodoAccessPrivate* d; +}; + +#endif diff --git a/libopie/pim/otodoaccessbackend.cpp b/libopie/pim/otodoaccessbackend.cpp new file mode 100644 index 0000000..baaeecc --- a/dev/null +++ b/libopie/pim/otodoaccessbackend.cpp @@ -0,0 +1,10 @@ + +#include "otodoaccessbackend.h" + +OTodoAccessBackend::OTodoAccessBackend() + : OPimAccessBackend<OTodo>() +{ +} +OTodoAccessBackend::~OTodoAccessBackend() { + +} diff --git a/libopie/pim/otodoaccessbackend.h b/libopie/pim/otodoaccessbackend.h new file mode 100644 index 0000000..ebe2189 --- a/dev/null +++ b/libopie/pim/otodoaccessbackend.h @@ -0,0 +1,18 @@ +#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; + +}; + +#endif diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp new file mode 100644 index 0000000..21756c9 --- a/dev/null +++ b/libopie/pim/otodoaccessxml.cpp @@ -0,0 +1,362 @@ +#include <qfile.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 = false; + m_changed = false; + /* initialize dict */ + /* + * UPDATE dict if you change anything!!! + */ + QAsciiDict<int> dict(15); + 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) ); + + Opie::XMLElement *root = Opie::XMLElement::load( m_file ); + int day, year, month; + day = year = month = -1; + + /* if opened */ + if ( root != 0l ) { + Opie::XMLElement *element = root->firstChild(); + if ( element == 0l ) + return false; + + element = element->firstChild(); + + while ( element ) { + if ( element->tagName() != QString::fromLatin1("Task") ) { + element = element->nextChild(); + continue; + } + /* here is the right element for a task */ + OTodo ev = todo( &dict, element ); + m_events.insert( ev.uid(), ev ); + + element = element->nextChild(); + } + return true; + }else { + qWarning("could not parse"); + return false;; + } + delete root; + + m_opened = true; + return true; +} +bool OTodoAccessXML::reload() { + return load(); +} +bool OTodoAccessXML::save() { + if (!m_opened || !m_changed ) + 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 sort ) { + 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 ) { + 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 */ +OTodo OTodoAccessXML::todo( QAsciiDict<int>* dict, Opie::XMLElement* element)const { + qWarning("parse to do from XMLElement" ); + OTodo ev; + QMap<QString, QString> attributes = element->attributes(); + QMap<QString, QString>::Iterator it; + + int *find=0; + int day, month, year; + day = month = year = -1; + for ( it = attributes.begin(); it != attributes.end(); ++it ) { + find = (*dict)[ it.key() ]; + if (!find ) { + qWarning("Unknown option" + it.key() ); + ev.setCustomField( it.key(), it.data() ); + continue; + } + + switch( *find ) { + case OTodo::Uid: + ev.setUid( it.data().toInt() ); + break; + case OTodo::Category: + ev.setCategories( ev.idsFromString( it.data() ) ); + break; + case OTodo::HasDate: + ev.setHasDueDate( it.data().toInt() ); + break; + case OTodo::Completed: + ev.setCompleted( it.data().toInt() ); + break; + case OTodo::Description: + ev.setDescription( it.data() ); + break; + case OTodo::Summary: + ev.setSummary( it.data() ); + break; + case OTodo::Priority: + ev.setPriority( it.data().toInt() ); + break; + case OTodo::DateDay: + day = it.data().toInt(); + break; + case OTodo::DateMonth: + month = it.data().toInt(); + break; + case OTodo::DateYear: + year = it.data().toInt(); + break; + case OTodo::Progress: + ev.setProgress( it.data().toInt() ); + break; + case OTodo::CrossReference: + { + /* + * A cross refernce looks like + * appname,id;appname,id + * we need to split it up + */ + QStringList refs = QStringList::split(';', it.data() ); + 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( it.data().toInt() ); + break; + case OTodo::AlarmDateTime: { + /* this sounds better ;) zecke */ + ev.setAlarmDateTime( TimeConversion::fromISO8601( it.data().local8Bit() ) ); + break; + } + default: + break; + } + } + if ( ev.hasDueDate() ) { + QDate date( year, month, day ); + ev.setDueDate( date ); + } + + return ev; +} +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() ) + "\" "; + } + 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 + QStringList list = ev.relatedApps(); + QStringList::Iterator listIt; + QString refs; + str += "CrossReference=\""; + bool added = false; + for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { + added = true; + QArray<int> ints = ev.relations( (*listIt) ); + for ( uint i = 0; i< ints.count(); i++ ) { + str += (*listIt) + "," + QString::number( i ) + ";"; + } + } + if ( added ) + str = str.remove( str.length()-1, 1 ); + + str += "\" "; + + str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; + + return str; +} +QString OTodoAccessXML::toString( const QArray<int>& ints ) const { + return Qtopia::Record::idsToString( ints ); +} diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h new file mode 100644 index 0000000..be9109d --- a/dev/null +++ b/libopie/pim/otodoaccessxml.h @@ -0,0 +1,53 @@ +#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 sort ); + OTodo find( int uid )const; + void clear(); + bool add( const OTodo& ); + bool remove( int uid ); + bool replace( const OTodo& ); + + /* our functions */ + QArray<int> effectiveToDos( const QDate& start, + const QDate& end, + bool includeNoDates ); + QArray<int> overDue(); +private: + OTodo todo( QAsciiDict<int>*, Opie::XMLElement* )const; + 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; + +}; + +#endif diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h index 5707b58..c27acbb 100644 --- a/libopie2/opiepim/backend/opimaccessbackend.h +++ b/libopie2/opiepim/backend/opimaccessbackend.h @@ -14,66 +14,66 @@ * the resource the implementation takes care * of */ template <class T = OPimRecord> class OPimAccessBackend { public: OPimAccessBackend(); virtual ~OPimAccessBackend(); - + /** * load the resource */ - virtual void load() = 0; - + virtual bool load() = 0; + /** * reload the resource */ - virtual void reload() = 0; - + virtual bool reload() = 0; + /** * save the resource and * all it's changes */ - virtual void save() = 0; - + virtual bool save() = 0; + /** * return an array of * all available uids */ virtual QArray<int> allRecords()const = 0; - + /** * queryByExample for T with the SortOrder * sort */ virtual QArray<int> queryByExample( const T& t, int sort ) = 0; - + /** * find the OPimRecord with uid @param uid * returns T and T.isEmpty() if nothing was found */ - virtual T find(int uid ) = 0; - + virtual T find(int uid )const = 0; + /** * clear the back end */ virtual void clear() = 0; - + /** * add T */ virtual bool add( const T& t ) = 0; - + /** * remove */ virtual bool remove( int uid ) = 0; - + /** * replace a record with T.uid() */ virtual bool replace( const T& t ) = 0; }; diff --git a/libopie2/opiepim/backend/otodoaccessbackend.cpp b/libopie2/opiepim/backend/otodoaccessbackend.cpp new file mode 100644 index 0000000..baaeecc --- a/dev/null +++ b/libopie2/opiepim/backend/otodoaccessbackend.cpp @@ -0,0 +1,10 @@ + +#include "otodoaccessbackend.h" + +OTodoAccessBackend::OTodoAccessBackend() + : OPimAccessBackend<OTodo>() +{ +} +OTodoAccessBackend::~OTodoAccessBackend() { + +} diff --git a/libopie2/opiepim/backend/otodoaccessbackend.h b/libopie2/opiepim/backend/otodoaccessbackend.h new file mode 100644 index 0000000..ebe2189 --- a/dev/null +++ b/libopie2/opiepim/backend/otodoaccessbackend.h @@ -0,0 +1,18 @@ +#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; + +}; + +#endif diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp new file mode 100644 index 0000000..21756c9 --- a/dev/null +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp @@ -0,0 +1,362 @@ +#include <qfile.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 = false; + m_changed = false; + /* initialize dict */ + /* + * UPDATE dict if you change anything!!! + */ + QAsciiDict<int> dict(15); + 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) ); + + Opie::XMLElement *root = Opie::XMLElement::load( m_file ); + int day, year, month; + day = year = month = -1; + + /* if opened */ + if ( root != 0l ) { + Opie::XMLElement *element = root->firstChild(); + if ( element == 0l ) + return false; + + element = element->firstChild(); + + while ( element ) { + if ( element->tagName() != QString::fromLatin1("Task") ) { + element = element->nextChild(); + continue; + } + /* here is the right element for a task */ + OTodo ev = todo( &dict, element ); + m_events.insert( ev.uid(), ev ); + + element = element->nextChild(); + } + return true; + }else { + qWarning("could not parse"); + return false;; + } + delete root; + + m_opened = true; + return true; +} +bool OTodoAccessXML::reload() { + return load(); +} +bool OTodoAccessXML::save() { + if (!m_opened || !m_changed ) + 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 sort ) { + 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 ) { + 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 */ +OTodo OTodoAccessXML::todo( QAsciiDict<int>* dict, Opie::XMLElement* element)const { + qWarning("parse to do from XMLElement" ); + OTodo ev; + QMap<QString, QString> attributes = element->attributes(); + QMap<QString, QString>::Iterator it; + + int *find=0; + int day, month, year; + day = month = year = -1; + for ( it = attributes.begin(); it != attributes.end(); ++it ) { + find = (*dict)[ it.key() ]; + if (!find ) { + qWarning("Unknown option" + it.key() ); + ev.setCustomField( it.key(), it.data() ); + continue; + } + + switch( *find ) { + case OTodo::Uid: + ev.setUid( it.data().toInt() ); + break; + case OTodo::Category: + ev.setCategories( ev.idsFromString( it.data() ) ); + break; + case OTodo::HasDate: + ev.setHasDueDate( it.data().toInt() ); + break; + case OTodo::Completed: + ev.setCompleted( it.data().toInt() ); + break; + case OTodo::Description: + ev.setDescription( it.data() ); + break; + case OTodo::Summary: + ev.setSummary( it.data() ); + break; + case OTodo::Priority: + ev.setPriority( it.data().toInt() ); + break; + case OTodo::DateDay: + day = it.data().toInt(); + break; + case OTodo::DateMonth: + month = it.data().toInt(); + break; + case OTodo::DateYear: + year = it.data().toInt(); + break; + case OTodo::Progress: + ev.setProgress( it.data().toInt() ); + break; + case OTodo::CrossReference: + { + /* + * A cross refernce looks like + * appname,id;appname,id + * we need to split it up + */ + QStringList refs = QStringList::split(';', it.data() ); + 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( it.data().toInt() ); + break; + case OTodo::AlarmDateTime: { + /* this sounds better ;) zecke */ + ev.setAlarmDateTime( TimeConversion::fromISO8601( it.data().local8Bit() ) ); + break; + } + default: + break; + } + } + if ( ev.hasDueDate() ) { + QDate date( year, month, day ); + ev.setDueDate( date ); + } + + return ev; +} +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() ) + "\" "; + } + 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 + QStringList list = ev.relatedApps(); + QStringList::Iterator listIt; + QString refs; + str += "CrossReference=\""; + bool added = false; + for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { + added = true; + QArray<int> ints = ev.relations( (*listIt) ); + for ( uint i = 0; i< ints.count(); i++ ) { + str += (*listIt) + "," + QString::number( i ) + ";"; + } + } + if ( added ) + str = str.remove( str.length()-1, 1 ); + + str += "\" "; + + str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; + + return str; +} +QString OTodoAccessXML::toString( const QArray<int>& ints ) const { + return Qtopia::Record::idsToString( ints ); +} diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h new file mode 100644 index 0000000..be9109d --- a/dev/null +++ b/libopie2/opiepim/backend/otodoaccessxml.h @@ -0,0 +1,53 @@ +#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 sort ); + OTodo find( int uid )const; + void clear(); + bool add( const OTodo& ); + bool remove( int uid ); + bool replace( const OTodo& ); + + /* our functions */ + QArray<int> effectiveToDos( const QDate& start, + const QDate& end, + bool includeNoDates ); + QArray<int> overDue(); +private: + OTodo todo( QAsciiDict<int>*, Opie::XMLElement* )const; + 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; + +}; + +#endif diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h index 36f5a99..31ab516 100644 --- a/libopie2/opiepim/core/opimaccesstemplate.h +++ b/libopie2/opiepim/core/opimaccesstemplate.h @@ -9,17 +9,17 @@ #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 + * 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; @@ -31,85 +31,86 @@ public: enum SortOrder { WildCards = 0, IgnoreCase = 1, RegExp = 2, ExactMatch = 4 }; /** * c'tor BackEnd */ OPimAccessTemplate( BackEnd* end); virtual ~OPimAccessTemplate(); - + /** * load from the backend */ - virtual void load(); - + virtual bool load(); + /** * reload from the backend */ - virtual void reload(); - + virtual bool reload(); + /** - * save to the backend + * save to the backend */ - virtual void save(); + virtual bool save(); /** * if the resource was changed externally */ bool wasChangedExternally()const; - + /** * return a List of records * you can iterate over them */ virtual List allRecords()const; - + /** - * queryByExample + * queryByExample */ virtual List queryByExample( const T& t, int sortOrder ); - + /** * find the OPimRecord uid */ - virtual T find( int uid ); + virtual T find( int uid )const; /* invalidate cache here */ /** * clears the backend and invalidates the backend */ virtual void clear() ; - + /** * add T to the backend */ virtual bool add( const T& t ) ; /* only the uid matters */ /** * remove T from the backend */ virtual bool remove( const T& t ); - + /** * remove the OPimRecord with uid */ virtual bool remove( int uid ); - + /** * replace T from backend */ virtual bool replace( const T& t) ; protected: /** * invalidate the cache */ void invalidateCache(); - + + void setBackEnd( BackEnd* end ); /** * returns the backend */ BackEnd* backEnd(); BackEnd* m_backEnd; }; @@ -120,43 +121,43 @@ OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) } template <class T> OPimAccessTemplate<T>::~OPimAccessTemplate() { qWarning("~OPimAccessTemplate<T>"); delete m_backEnd; } template <class T> -void OPimAccessTemplate<T>::load() { - m_backEnd->load(); +bool OPimAccessTemplate<T>::load() { + return m_backEnd->load(); } template <class T> -void OPimAccessTemplate<T>::reload() { - m_backEnd->reload(); +bool OPimAccessTemplate<T>::reload() { + return m_backEnd->reload(); } template <class T> -void OPimAccessTemplate<T>::save() { - m_backEnd->save(); +bool OPimAccessTemplate<T>::save() { + return m_backEnd->save(); } template <class T> OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { QArray<int> ints = m_backEnd->allRecords(); List lis(ints, this ); return lis; } template <class T> 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 ) { +T OPimAccessTemplate<T>::find( int uid ) const{ T t = m_backEnd->find( uid ); return t; } template <class T> void OPimAccessTemplate<T>::clear() { invalidateCache(); m_backEnd->clear(); } @@ -183,9 +184,13 @@ void OPimAccessTemplate<T>::invalidateCache() { template <class T> 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; +} #endif diff --git a/libopie2/opiepim/core/otemplatebase.h b/libopie2/opiepim/core/otemplatebase.h index add1de4..f71417b 100644 --- a/libopie2/opiepim/core/otemplatebase.h +++ b/libopie2/opiepim/core/otemplatebase.h @@ -8,14 +8,14 @@ */ template <class T = OPimRecord> class OTemplateBase { public: OTemplateBase() { }; virtual ~OTemplateBase() { } - virtual T find( int uid ) = 0; + virtual T find( int uid )const = 0; }; #endif diff --git a/libopie2/opiepim/core/otodoaccess.cpp b/libopie2/opiepim/core/otodoaccess.cpp new file mode 100644 index 0000000..a65cf5c --- a/dev/null +++ b/libopie2/opiepim/core/otodoaccess.cpp @@ -0,0 +1,71 @@ +#include <qdatetime.h> + +#include <qpe/alarmserver.h> + +#include "otodoaccessxml.h" +#include "otodoaccess.h" + + +OTodoAccess::OTodoAccess( OTodoAccessBackend* end ) + : QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end ) +{ + if (end == 0l ) + m_todoBackEnd = new OTodoAccessXML( "Todolist" ); + + 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() ) + 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 ); +} + diff --git a/libopie2/opiepim/core/otodoaccess.h b/libopie2/opiepim/core/otodoaccess.h new file mode 100644 index 0000000..c43efe9 --- a/dev/null +++ b/libopie2/opiepim/core/otodoaccess.h @@ -0,0 +1,79 @@ +#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: + /** + * if you use 0l + * the default resource will be + * icked 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(); + /** + * merge a list of OTodos into + * the resource + */ + void mergeWith( const QValueList<OTodo>& ); + + /** + * 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: + OTodoAccessBackend* m_todoBackEnd; + class OTodoAccessPrivate; + OTodoAccessPrivate* d; +}; + +#endif diff --git a/libopie2/opiepim/orecordlist.h b/libopie2/opiepim/orecordlist.h index 3b30a73..75bb33c 100644 --- a/libopie2/opiepim/orecordlist.h +++ b/libopie2/opiepim/orecordlist.h @@ -9,38 +9,40 @@ /** * Our List Iterator * it behaves like STL or Qt * * for(it = list.begin(); it != list.end(); ++it ) * doSomeCoolStuff( (*it) ); */ +template <class T> class ORecordList; template <class T = OPimRecord> class ORecordListIterator { + friend class ORecordList<T>; public: typedef OTemplateBase<T> Base; - + /** * The c'tor used internally from * ORecordList */ ORecordListIterator( const QArray<int>, const Base* ); - + /** * The standard c'tor */ ORecordListIterator(); ~ORecordListIterator(); - + ORecordListIterator( const ORecordListIterator& ); ORecordListIterator &operator=(const ORecordListIterator& ); - + /** - * a * operator ;) + * a * operator ;) * use it like this T = (*it); */ T &operator*(); ORecordListIterator &operator++(); ORecordListIterator &operator--(); bool operator==( const ORecordListIterator& it ); bool operator!=( const ORecordListIterator& it ); @@ -54,35 +56,35 @@ private: /* d pointer for future versions */ class IteratorPrivate; IteratorPrivate *d; }; /** * The recordlist used as a return type * from OPimAccessTemplate - */ + */ template <class T = OPimRecord > class ORecordList { public: typedef OTemplateBase<T> Base; typedef ORecordListIterator<T> Iterator; - - /** + + /** * c'tor */ ORecordList( const QArray<int>& ids, const Base* ); ~ORecordList(); - + /** * the first iterator */ Iterator begin(); - + /** * the end */ Iterator end(); /* ConstIterator begin()const; ConstIterator end()const; */ @@ -100,16 +102,17 @@ ORecordListIterator<T>::ORecordListIterator() { } template <class T> ORecordListIterator<T>::~ORecordListIterator() { /* nothing to delete */ } template <class T> ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) { + qWarning("ORecordListIterator"); m_uids = it.m_uids; m_current = it.m_current; m_temp = it.m_temp; m_end = it.m_end; m_record = it.m_record; } template <class T> @@ -120,27 +123,28 @@ ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIter m_end = it.m_end; m_record = it.m_record; return *this; } template <class T> T &ORecordListIterator<T>::operator*() { + qWarning("operator* %d %d", m_current, m_uids[m_current] ); if (!m_end ) m_record = m_temp->find( m_uids[m_current] ); else m_record = T(); return m_record; } template <class T> ORecordListIterator<T> &ORecordListIterator<T>::operator++() { - if (m_current < m_uids.count() ) { + if (m_current < (int)m_uids.count() ) { m_end = false; ++m_current; }else m_end = true; return *this; } template <class T> @@ -184,18 +188,21 @@ ORecordList<T>::ORecordList( const QArray<int>& ids, { } template <class T> ORecordList<T>::~ORecordList() { /* nothing to do here */ } template <class T> ORecordList<T>::Iterator ORecordList<T>::begin() { + qWarning("ORecordList::begin"); Iterator it( m_ids, m_acc ); return it; } template <class T> ORecordList<T>::Iterator ORecordList<T>::end() { Iterator it( m_ids, m_acc ); it.m_end = true; it.m_current = m_ids.count(); + + return it; } #endif diff --git a/libopie2/opiepim/otodo.cpp b/libopie2/opiepim/otodo.cpp index 8239ba6..b3c14e6 100644 --- a/libopie2/opiepim/otodo.cpp +++ b/libopie2/opiepim/otodo.cpp @@ -31,36 +31,39 @@ struct OTodo::OTodoData : public QShared { bool hasAlarmDateTime :1; QDateTime alarmDateTime; }; OTodo::OTodo(const OTodo &event ) : OPimRecord( event ), data( event.data ) { data->ref(); - //qWarning("ref up"); + qWarning("ref up"); } OTodo::~OTodo() { + qWarning("~OTodo " + data->sum ); if ( data->deref() ) { - //qWarning("OTodo::dereffing"); + 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"); + 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; @@ -69,20 +72,22 @@ OTodo::OTodo(bool completed, int priority, 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"); + 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; @@ -345,17 +350,17 @@ QMap<QString, QString> OTodo::toExtraMap()const { } /** * 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"); + qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } void OTodo::copy( OTodoData* src, OTodoData* dest ) { dest->date = src->date; diff --git a/libopie2/opiepim/otodo.h b/libopie2/opiepim/otodo.h index 75af44c..1443e4f 100644 --- a/libopie2/opiepim/otodo.h +++ b/libopie2/opiepim/otodo.h @@ -130,26 +130,16 @@ public: * reimplementation */ QString type()const; QString toShortText()const; QMap<QString, QString> toExtraMap()const; QString recordField(int id )const; /** - * returns a list of apps which have related items - */ - QStringList relatedApps()const; - - /** - * returns all relations for one app - */ - QArray<int> relations( const QString& app )const; - - /** * toMap puts all data into the map. int relates * to ToDoEvent RecordFields enum */ QMap<int, QString> toMap()const; /** * Set if this Todo is completed */ |