24 files changed, 1264 insertions, 64 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 @@ -1,89 +1,89 @@ #ifndef OPIE_PIM_ACCESS_BACKEND #define OPIE_PIM_ACCESS_BACKEND #include <qarray.h> #include <opie/opimrecord.h> /** * OPimAccessBackend is the base class * for all private backends * it operates on OPimRecord as the base class * and it's responsible for fast manipulating * 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; }; template <class T> OPimAccessBackend<T>::OPimAccessBackend() { } template <class T> OPimAccessBackend<T>::~OPimAccessBackend() { } #endif 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 @@ -1,191 +1,196 @@ #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 "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; /** * our sort order * should be safe explaining */ 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 */ - 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 */ 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; }; template <class T> OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) : OTemplateBase<T>(), m_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(); } template <class T> bool OPimAccessTemplate<T>::add( const T& t ) { return m_backEnd->add( t ); } template <class T> bool OPimAccessTemplate<T>::remove( const T& t ) { return m_backEnd->remove( t.uid() ); } template <class T> bool OPimAccessTemplate<T>::remove( int uid ) { return m_backEnd->remove( uid ); } template <class T> bool OPimAccessTemplate<T>::replace( const T& t ) { return m_backEnd->replace( t ); } template <class T> 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 @@ -1,201 +1,208 @@ #ifndef OPIE_RECORD_LIST_H #define OPIE_RECORD_LIST_H #include <qarray.h> #include "otemplatebase.h" #include "opimrecord.h" /** * 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 ;) * use it like this T = (*it); */ T &operator*(); ORecordListIterator &operator++(); ORecordListIterator &operator--(); bool operator==( const ORecordListIterator& it ); bool operator!=( const ORecordListIterator& it ); private: QArray<int> m_uids; int m_current; const Base* m_temp; bool m_end : 1; T m_record; /* 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; */ private: QArray<int> m_ids; const Base* m_acc; }; /* ok now implement it */ template <class T> ORecordListIterator<T>::ORecordListIterator() { m_current = 0; m_temp = 0l; m_end = true; } 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> ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) { 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; 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> ORecordListIterator<T> &ORecordListIterator<T>::operator--() { if ( m_current > 0 ) { --m_current; m_end = false; } else m_end = true; return *this; } template <class T> bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) { /* if both are at we're the same.... */ if ( m_end == it.m_end ) return true; if ( m_uids != it.m_uids ) return false; if ( m_current != it.m_current ) return false; if ( m_temp != it.m_temp ) return false; return true; } template <class T> bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) { return !(*this == it ); } template <class T> ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids, const Base* t ) : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ) { } template <class T> ORecordList<T>::ORecordList( const QArray<int>& ids, const Base* acc ) : m_ids( ids ), m_acc( acc ) { } 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 @@ -1,21 +1,21 @@ #ifndef OPIE_TEMPLATE_BASE_H #define OPIE_TEMPLATE_BASE_H #include "opimrecord.h" /** * internal template base */ 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 @@ -1,128 +1,133 @@ #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 "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; }; 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; } 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; } 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; } 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 { @@ -305,74 +310,74 @@ void OTodo::deref() { //qWarning("deref in ToDoEvent"); if ( data->deref() ) { //qWarning("deleting"); delete data; d= 0; } } OTodo &OTodo::operator=(const OTodo &item ) { OPimRecord::operator=( item ); //qWarning("operator= ref "); item.data->ref(); deref(); 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() ); 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"); + qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } 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; } QString OTodo::type() const { return QString::fromLatin1("OTodo"); } QString OTodo::recordField(int id )const { return QString::null; } 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 @@ -90,106 +90,96 @@ public: */ 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 */ QDateTime alarmDateTime()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; /** * 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 */ 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 ); /** * 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 ); /** * set the alarm time */ void setAlarmDateTime ( const QDateTime& alarm ); void setDescription(const QString& ); void setSummary(const QString& ); bool isOverdue(); bool match( const QRegExp &r )const; bool operator<(const OTodo &toDoEvent )const; 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 @@ -1,89 +1,89 @@ #ifndef OPIE_PIM_ACCESS_BACKEND #define OPIE_PIM_ACCESS_BACKEND #include <qarray.h> #include <opie/opimrecord.h> /** * OPimAccessBackend is the base class * for all private backends * it operates on OPimRecord as the base class * and it's responsible for fast manipulating * 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; }; template <class T> OPimAccessBackend<T>::OPimAccessBackend() { } template <class T> OPimAccessBackend<T>::~OPimAccessBackend() { } #endif 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 @@ -1,191 +1,196 @@ #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 "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; /** * our sort order * should be safe explaining */ 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 */ - 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 */ 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; }; template <class T> OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) : OTemplateBase<T>(), m_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(); } template <class T> bool OPimAccessTemplate<T>::add( const T& t ) { return m_backEnd->add( t ); } template <class T> bool OPimAccessTemplate<T>::remove( const T& t ) { return m_backEnd->remove( t.uid() ); } template <class T> bool OPimAccessTemplate<T>::remove( int uid ) { return m_backEnd->remove( uid ); } template <class T> bool OPimAccessTemplate<T>::replace( const T& t ) { return m_backEnd->replace( t ); } template <class T> 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 @@ -1,21 +1,21 @@ #ifndef OPIE_TEMPLATE_BASE_H #define OPIE_TEMPLATE_BASE_H #include "opimrecord.h" /** * internal template base */ 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 @@ -1,201 +1,208 @@ #ifndef OPIE_RECORD_LIST_H #define OPIE_RECORD_LIST_H #include <qarray.h> #include "otemplatebase.h" #include "opimrecord.h" /** * 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 ;) * use it like this T = (*it); */ T &operator*(); ORecordListIterator &operator++(); ORecordListIterator &operator--(); bool operator==( const ORecordListIterator& it ); bool operator!=( const ORecordListIterator& it ); private: QArray<int> m_uids; int m_current; const Base* m_temp; bool m_end : 1; T m_record; /* 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; */ private: QArray<int> m_ids; const Base* m_acc; }; /* ok now implement it */ template <class T> ORecordListIterator<T>::ORecordListIterator() { m_current = 0; m_temp = 0l; m_end = true; } 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> ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) { 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; 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> ORecordListIterator<T> &ORecordListIterator<T>::operator--() { if ( m_current > 0 ) { --m_current; m_end = false; } else m_end = true; return *this; } template <class T> bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) { /* if both are at we're the same.... */ if ( m_end == it.m_end ) return true; if ( m_uids != it.m_uids ) return false; if ( m_current != it.m_current ) return false; if ( m_temp != it.m_temp ) return false; return true; } template <class T> bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) { return !(*this == it ); } template <class T> ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids, const Base* t ) : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ) { } template <class T> ORecordList<T>::ORecordList( const QArray<int>& ids, const Base* acc ) : m_ids( ids ), m_acc( acc ) { } 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 @@ -1,128 +1,133 @@ #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 "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; }; 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; } 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; } 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; } 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 { @@ -305,74 +310,74 @@ void OTodo::deref() { //qWarning("deref in ToDoEvent"); if ( data->deref() ) { //qWarning("deleting"); delete data; d= 0; } } OTodo &OTodo::operator=(const OTodo &item ) { OPimRecord::operator=( item ); //qWarning("operator= ref "); item.data->ref(); deref(); 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() ); 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"); + qWarning("changeOrModify"); data->deref(); OTodoData* d2 = new OTodoData(); copy(data, d2 ); data = d2; } } 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; } QString OTodo::type() const { return QString::fromLatin1("OTodo"); } QString OTodo::recordField(int id )const { return QString::null; } 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 @@ -90,106 +90,96 @@ public: */ 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 */ QDateTime alarmDateTime()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; /** * 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 */ 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 ); /** * 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 ); /** * set the alarm time */ void setAlarmDateTime ( const QDateTime& alarm ); void setDescription(const QString& ); void setSummary(const QString& ); bool isOverdue(); bool match( const QRegExp &r )const; bool operator<(const OTodo &toDoEvent )const; |