summaryrefslogtreecommitdiff
path: root/libopie
authorzecke <zecke>2002-10-07 09:10:05 (UTC)
committer zecke <zecke>2002-10-07 09:10:05 (UTC)
commitacd2d0062dd87635feb03927663b1f700305d67b (patch) (side-by-side diff)
tree179217749ec7ba3217ca71f80a6e1064f249d1b0 /libopie
parentde56dc7c5a21cbd70e9d1e66ab68ca95a277c45c (diff)
downloadopie-acd2d0062dd87635feb03927663b1f700305d67b.zip
opie-acd2d0062dd87635feb03927663b1f700305d67b.tar.gz
opie-acd2d0062dd87635feb03927663b1f700305d67b.tar.bz2
First SQL backend Resource
The DB layout is not fully what we've in mind but for example I do lack the Categories infrastructure for that I've to implement sorted lists and then I'll make Todolist fast
Diffstat (limited to 'libopie') (more/less context) (show whitespace changes)
-rw-r--r--libopie/pim/orecordlist.h3
-rw-r--r--libopie/pim/otodoaccess.cpp4
-rw-r--r--libopie/pim/otodoaccesssql.cpp397
-rw-r--r--libopie/pim/otodoaccesssql.h46
-rw-r--r--libopie/pim/otodoaccessxml.cpp1
5 files changed, 447 insertions, 4 deletions
diff --git a/libopie/pim/orecordlist.h b/libopie/pim/orecordlist.h
index 1fd0741..b6fa7fa 100644
--- a/libopie/pim/orecordlist.h
+++ b/libopie/pim/orecordlist.h
@@ -1,260 +1,259 @@
#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 );
/**
* the current item
*/
uint current()const;
/**
* the number of items
*/
uint count()const;
/**
* sets the current item
*/
void setCurrent( uint cur );
private:
QArray<int> m_uids;
uint 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 () {
}
ORecordList( const QArray<int>& ids,
const Base* );
~ORecordList();
/**
* the first iterator
*/
Iterator begin();
/**
* the end
*/
Iterator end();
/**
* the number of items in the list
*/
uint count()const;
T operator[]( uint i );
// FIXME implemenent remove
/*
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;
m_record = T();
}
template <class T>
ORecordListIterator<T>::~ORecordListIterator() {
/* nothing to delete */
}
template <class T>
ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
// qWarning("ORecordListIterator copy c'tor");
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] );
+ qWarning("operator* %d %d", m_current, m_uids[m_current] );
if (!m_end )
/* FIXME
* until the cache is in place
* we do the uid match uid check
*/
- if(m_record.uid() != m_uids[m_current] )
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() ) {
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>
uint ORecordListIterator<T>::current()const {
return m_current;
}
template <class T>
void ORecordListIterator<T>::setCurrent( uint cur ) {
if( cur < m_uids.count() ) {
m_end = false;
m_current= cur;
}
}
template <class T>
uint ORecordListIterator<T>::count()const {
return m_uids.count();
}
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() {
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;
}
template <class T>
uint ORecordList<T>::count()const {
return m_ids.count();
}
template <class T>
T ORecordList<T>::operator[]( uint i ) {
return m_acc->find( m_ids[i] );
}
#endif
diff --git a/libopie/pim/otodoaccess.cpp b/libopie/pim/otodoaccess.cpp
index f51da29..5990841 100644
--- a/libopie/pim/otodoaccess.cpp
+++ b/libopie/pim/otodoaccess.cpp
@@ -1,77 +1,77 @@
#include <qdatetime.h>
#include <qpe/alarmserver.h>
-#include "otodoaccessxml.h"
+#include "otodoaccesssql.h"
#include "otodoaccess.h"
OTodoAccess::OTodoAccess( OTodoAccessBackend* end )
: QObject(), OPimAccessTemplate<OTodo>( end ), m_todoBackEnd( end )
{
if (end == 0l )
- m_todoBackEnd = new OTodoAccessXML( "Todolist" );
+ m_todoBackEnd = new OTodoAccessBackendSQL( QString::null);
setBackEnd( m_todoBackEnd );
}
OTodoAccess::~OTodoAccess() {
// qWarning("~OTodoAccess");
}
void OTodoAccess::mergeWith( const QValueList<OTodo>& list ) {
QValueList<OTodo>::ConstIterator it;
for ( it = list.begin(); it != list.end(); ++it ) {
replace( (*it) );
}
}
OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
const QDate& end,
bool includeNoDates ) {
QArray<int> ints = m_todoBackEnd->effectiveToDos( start, end, includeNoDates );
List lis( ints, this );
return lis;
}
OTodoAccess::List OTodoAccess::effectiveToDos( const QDate& start,
bool includeNoDates ) {
return effectiveToDos( start, QDate::currentDate(),
includeNoDates );
}
OTodoAccess::List OTodoAccess::overDue() {
List lis( m_todoBackEnd->overDue(), this );
return lis;
}
void OTodoAccess::addAlarm( const OTodo& event) {
if (!event.hasAlarmDateTime() )
return;
QDateTime now = QDateTime::currentDateTime();
QDateTime schedule = event.alarmDateTime();
if ( schedule > now ){
AlarmServer::addAlarm( schedule,
"QPE/Application/todolist",
"alarm(QDateTime,int)", event.uid() );
}
}
void OTodoAccess::delAlarm( int uid) {
QDateTime schedule; // Create null DateTime
// I hope this will remove all scheduled alarms
// with the given uid !?
// If not: I have to rethink how to remove already
// scheduled events... (se)
// it should be fine -zecke
// qWarning("Removing alarm for event with uid %d", uid );
AlarmServer::deleteAlarm( schedule ,
"QPE/Application/todolist",
"alarm(QDateTime,int)", uid );
}
/* sort order */
OTodoAccess::List OTodoAccess::sorted( bool ascending, int sort,int filter, int cat ) {
QArray<int> ints = m_todoBackEnd->sorted( ascending, sort,
filter, cat );
OTodoAccess::List list( ints, this );
return list;
}
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
new file mode 100644
index 0000000..209e714
--- a/dev/null
+++ b/libopie/pim/otodoaccesssql.cpp
@@ -0,0 +1,397 @@
+
+#include <qdatetime.h>
+
+#include <qpe/global.h>
+
+#include <opie/osqldriver.h>
+#include <opie/osqlresult.h>
+#include <opie/osqlmanager.h>
+#include <opie/osqlquery.h>
+
+#include "otodoaccesssql.h"
+
+/*
+ * first some query
+ * CREATE query
+ * LOAD query
+ * INSERT
+ * REMOVE
+ * CLEAR
+ */
+namespace {
+ /**
+ * CreateQuery for the Todolist Table
+ */
+ class CreateQuery : public OSQLQuery {
+ public:
+ CreateQuery();
+ ~CreateQuery();
+ QString query()const;
+ };
+
+ /**
+ * LoadQuery
+ * this one queries for all uids
+ */
+ class LoadQuery : public OSQLQuery {
+ public:
+ LoadQuery();
+ ~LoadQuery();
+ QString query()const;
+ };
+
+ /**
+ * inserts/adds a OTodo to the table
+ */
+ class InsertQuery : public OSQLQuery {
+ public:
+ InsertQuery(const OTodo& );
+ ~InsertQuery();
+ QString query()const;
+ private:
+ OTodo m_todo;
+ };
+
+ /**
+ * removes one from the table
+ */
+ class RemoveQuery : public OSQLQuery {
+ public:
+ RemoveQuery(int uid );
+ ~RemoveQuery();
+ QString query()const;
+ private:
+ int m_uid;
+ };
+
+ /**
+ * Clears (delete) a Table
+ */
+ class ClearQuery : public OSQLQuery {
+ public:
+ ClearQuery();
+ ~ClearQuery();
+ QString query()const;
+
+ };
+
+ /**
+ * a find query
+ */
+ class FindQuery : public OSQLQuery {
+ public:
+ FindQuery(int uid);
+ ~FindQuery();
+ QString query()const;
+ private:
+ int m_uid;
+ };
+
+ /**
+ * overdue query
+ */
+ class OverDueQuery : public OSQLQuery {
+ public:
+ OverDueQuery();
+ ~OverDueQuery();
+ QString query()const;
+ };
+ class EffQuery : public OSQLQuery {
+ public:
+ EffQuery( const QDate&, const QDate&, bool inc );
+ ~EffQuery();
+ QString query()const;
+ private:
+ QString with()const;
+ QString out()const;
+ QDate m_start;
+ QDate m_end;
+ bool m_inc :1;
+ };
+
+
+ CreateQuery::CreateQuery() : OSQLQuery() {}
+ CreateQuery::~CreateQuery() {}
+ QString CreateQuery::query()const {
+ QString qu;
+ qu += "create table todolist( uid, categories, completed, progress, ";
+ qu += "summary, DueDate, priority, description )";
+ return qu;
+ }
+
+ LoadQuery::LoadQuery() : OSQLQuery() {}
+ LoadQuery::~LoadQuery() {}
+ QString LoadQuery::query()const {
+ QString qu;
+ qu += "select distinct uid from todolist";
+
+ return qu;
+ }
+
+ InsertQuery::InsertQuery( const OTodo& todo )
+ : OSQLQuery(), m_todo( todo ) {
+ }
+ InsertQuery::~InsertQuery() {
+ }
+ /*
+ * converts from a OTodo to a query
+ * we leave out X-Ref + Alarms
+ */
+ QString InsertQuery::query()const{
+ int year, month, day;
+ year = month = day = 0;
+ if (m_todo.hasDueDate() ) {
+ QDate date = m_todo.dueDate();
+ year = date.year();
+ month = date.month();
+ day = date.day();
+ }
+ QString qu;
+ qu = "insert into todolist VALUES(" + QString::number( m_todo.uid() ) + ",'" + m_todo.idsToString( m_todo.categories() ) + "',";
+ qu += QString::number( m_todo.isCompleted() ) + "," + QString::number( m_todo.progress() ) + ",";
+ qu += "'"+m_todo.summary()+"','"+QString::number(year)+"-"+QString::number(month)+"-"+QString::number(day)+"',";
+ qu += QString::number(m_todo.priority() ) +",'" + m_todo.description() + "')";
+
+ qWarning("add %s", qu.latin1() );
+ return qu;
+ }
+
+ RemoveQuery::RemoveQuery(int uid )
+ : OSQLQuery(), m_uid( uid ) {}
+ RemoveQuery::~RemoveQuery() {}
+ QString RemoveQuery::query()const {
+ QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
+ return qu;
+ }
+
+
+ ClearQuery::ClearQuery()
+ : OSQLQuery() {}
+ ClearQuery::~ClearQuery() {}
+ QString ClearQuery::query()const {
+ QString qu = "drop table todolist";
+ return qu;
+ }
+ FindQuery::FindQuery(int uid)
+ : OSQLQuery(), m_uid(uid ) {
+ }
+ FindQuery::~FindQuery() {
+ }
+ QString FindQuery::query()const{
+ QString qu = "select uid, categories, completed, progress, summary, ";
+ qu += "DueDate, priority, description from todolist where uid = " + QString::number(m_uid);
+ return qu;
+ }
+
+ OverDueQuery::OverDueQuery(): OSQLQuery() {}
+ OverDueQuery::~OverDueQuery() {}
+ QString OverDueQuery::query()const {
+ QDate date = QDate::currentDate();
+ QString str;
+ str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
+
+ return str;
+ }
+
+
+ EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
+ : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
+ EffQuery::~EffQuery() {}
+ QString EffQuery::query()const {
+ return m_inc ? with() : out();
+ }
+ QString EffQuery::with()const {
+ QString str;
+ str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
+ .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
+ .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
+ return str;
+ }
+ QString EffQuery::out()const {
+ QString str;
+ str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
+ .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
+ .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
+
+ return str;
+ }
+};
+
+OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
+ : OTodoAccessBackend(), m_dict(15)
+{
+ QString fi = file;
+ if ( fi.isEmpty() )
+ fi = Global::applicationFileName( "todolist", "todolist.db" );
+ OSQLManager man;
+ m_driver = man.standard();
+ m_driver->setUrl(fi);
+ fillDict();
+}
+
+OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
+}
+bool OTodoAccessBackendSQL::load(){
+ if (!m_driver->open() )
+ return false;
+
+ CreateQuery creat;
+ OSQLResult res = m_driver->query(&creat );
+
+ update();
+ qWarning("loaded %d", m_uids.count() );
+ return true;
+}
+bool OTodoAccessBackendSQL::reload(){
+ return load();
+}
+
+bool OTodoAccessBackendSQL::save(){
+ return m_driver->close();
+}
+QArray<int> OTodoAccessBackendSQL::allRecords()const {
+ return m_uids;
+}
+QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int ){
+ QArray<int> ints(0);
+ return ints;
+}
+OTodo OTodoAccessBackendSQL::find(int uid ) const{
+ FindQuery query( uid );
+ return todo( m_driver->query(&query) );
+
+}
+void OTodoAccessBackendSQL::clear() {
+ ClearQuery cle;
+ OSQLResult res = m_driver->query( &cle );
+ CreateQuery qu;
+ res = m_driver->query(&qu);
+}
+bool OTodoAccessBackendSQL::add( const OTodo& t) {
+ InsertQuery ins( t );
+ OSQLResult res = m_driver->query( &ins );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+ int c = m_uids.count();
+ m_uids.resize( c+1 );
+ m_uids[c] = t.uid();
+
+ return true;
+}
+bool OTodoAccessBackendSQL::remove( int uid ) {
+ RemoveQuery rem( uid );
+ OSQLResult res = m_driver->query(&rem );
+
+ if ( res.state() == OSQLResult::Failure )
+ return false;
+
+ update();
+ return true;
+}
+/*
+ * FIXME better set query
+ * but we need the cache for that
+ * now we remove
+ */
+bool OTodoAccessBackendSQL::replace( const OTodo& t) {
+ remove( t.uid() );
+ return add(t);
+}
+QArray<int> OTodoAccessBackendSQL::overDue() {
+ OverDueQuery qu;
+ return uids( m_driver->query(&qu ) );
+}
+QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
+ const QDate& t,
+ bool u) {
+ EffQuery ef(s, t, u );
+ return uids (m_driver->query(&ef) );
+}
+QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
+ int sortFilter, int cat ) {
+ QArray<int> ints(0);
+ return ints;
+}
+bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
+ if ( str == "0-0-0" )
+ return false;
+ else{
+ int day, year, month;
+ QStringList list = QStringList::split("-", str );
+ year = list[0].toInt();
+ month = list[1].toInt();
+ day = list[2].toInt();
+ da.setYMD( year, month, day );
+ return true;
+ }
+}
+OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
+ if ( res.state() == OSQLResult::Failure ) {
+ OTodo to;
+ return to;
+ }
+
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it = list.begin();
+
+ bool has = false; QDate da = QDate::currentDate();
+ has = date( da, (*it).data("DueDate") );
+ QStringList cats = QStringList::split(";", (*it).data("categories") );
+
+ OTodo to( (bool)(*it).data("completed").toInt(), (*it).data("priority").toInt(),
+ cats, (*it).data("summary"), (*it).data("description"),
+ (*it).data("progress").toUShort(), has, da, (*it).data("uid").toInt() );
+ return to;
+}
+OTodo OTodoAccessBackendSQL::todo( int uid )const {
+ FindQuery find( uid );
+ return todo( m_driver->query(&find) );
+}
+/*
+ * update the dict
+ */
+void OTodoAccessBackendSQL::fillDict() {
+ /* initialize dict */
+ /*
+ * UPDATE dict if you change anything!!!
+ */
+ m_dict.setAutoDelete( TRUE );
+ m_dict.insert("Categories" , new int(OTodo::Category) );
+ m_dict.insert("Uid" , new int(OTodo::Uid) );
+ m_dict.insert("HasDate" , new int(OTodo::HasDate) );
+ m_dict.insert("Completed" , new int(OTodo::Completed) );
+ m_dict.insert("Description" , new int(OTodo::Description) );
+ m_dict.insert("Summary" , new int(OTodo::Summary) );
+ m_dict.insert("Priority" , new int(OTodo::Priority) );
+ m_dict.insert("DateDay" , new int(OTodo::DateDay) );
+ m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
+ m_dict.insert("DateYear" , new int(OTodo::DateYear) );
+ m_dict.insert("Progress" , new int(OTodo::Progress) );
+ m_dict.insert("Completed", new int(OTodo::Completed) );
+ m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
+ m_dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) );
+ m_dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) );
+}
+void OTodoAccessBackendSQL::update() {
+ LoadQuery lo;
+ OSQLResult res = m_driver->query(&lo);
+ if ( res.state() != OSQLResult::Success )
+ return;
+
+ m_uids = uids( res );
+}
+QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
+
+ OSQLResultItem::ValueList list = res.results();
+ OSQLResultItem::ValueList::Iterator it;
+ QArray<int> ints(list.count() );
+
+ int i = 0;
+ for (it = list.begin(); it != list.end(); ++it ) {
+ ints[i] = (*it).data("uid").toInt();
+ i++;
+ }
+ return ints;
+}
+
diff --git a/libopie/pim/otodoaccesssql.h b/libopie/pim/otodoaccesssql.h
new file mode 100644
index 0000000..966628d
--- a/dev/null
+++ b/libopie/pim/otodoaccesssql.h
@@ -0,0 +1,46 @@
+#ifndef OPIE_PIM_ACCESS_SQL_H
+#define OPIE_PIM_ACCESS_SQL_H
+
+#include <qasciidict.h>
+
+#include "otodoaccessbackend.h"
+
+class OSQLDriver;
+class OSQLResult;
+class OTodoAccessBackendSQL : public OTodoAccessBackend {
+public:
+ OTodoAccessBackendSQL( const QString& file );
+ ~OTodoAccessBackendSQL();
+
+ bool load();
+ bool reload();
+ bool save();
+ QArray<int> allRecords()const;
+
+ QArray<int> queryByExample( const OTodo& t, int sort );
+ OTodo find(int uid)const;
+ void clear();
+ bool add( const OTodo& t );
+ bool remove( int uid );
+ bool replace( const OTodo& t );
+
+ QArray<int> overDue();
+ QArray<int> effectiveToDos( const QDate& start,
+ const QDate& end, bool includeNoDates );
+ QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
+
+private:
+ void update();
+ void fillDict();
+ bool date( QDate& date, const QString& )const;
+ OTodo todo( const OSQLResult& )const;
+ QArray<int> uids( const OSQLResult& )const;
+ OTodo todo( int uid )const;
+
+ QAsciiDict<int> m_dict;
+ OSQLDriver* m_driver;
+ QArray<int> m_uids;
+};
+
+
+#endif
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index 31822d4..80b8599 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -1,505 +1,506 @@
#include <qfile.h>
#include <qvector.h>
#include <qpe/global.h>
#include <qpe/stringutil.h>
#include <qpe/timeconversion.h>
#include <opie/xmltree.h>
#include "otodoaccessxml.h"
OTodoAccessXML::OTodoAccessXML( const QString& appName,
const QString& fileName )
: OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
{
if (!fileName.isEmpty() )
m_file = fileName;
else
m_file = Global::applicationFileName( "todolist", "todolist.xml" );
}
OTodoAccessXML::~OTodoAccessXML() {
}
bool OTodoAccessXML::load() {
m_opened = true;
m_changed = false;
/* initialize dict */
/*
* UPDATE dict if you change anything!!!
*/
QAsciiDict<int> dict(15);
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) );
// here the custom XML parser from TT it's GPL
// but we want to push that to TT.....
QFile f(m_file );
if (!f.open(IO_ReadOnly) )
return false;
QByteArray ba = f.readAll();
f.close();
char* dt = ba.data();
int len = ba.size();
int i = 0;
char *point;
const char* collectionString = "<Task ";
while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) {
i = point -dt;
i+= strlen(collectionString);
OTodo ev;
m_year = m_month = m_day = 0;
while ( TRUE ) {
while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
++i;
if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
break;
// we have another attribute, read it.
int j = i;
while ( j < len && dt[j] != '=' )
++j;
QCString attr( dt+i, j-i+1);
i = ++j; // skip =
// find the start of quotes
while ( i < len && dt[i] != '"' )
++i;
j = ++i;
bool haveUtf = FALSE;
bool haveEnt = FALSE;
while ( j < len && dt[j] != '"' ) {
if ( ((unsigned char)dt[j]) > 0x7f )
haveUtf = TRUE;
if ( dt[j] == '&' )
haveEnt = TRUE;
++j;
}
if ( i == j ) {
// empty value
i = j + 1;
continue;
}
QCString value( dt+i, j-i+1 );
i = j + 1;
QString str = (haveUtf ? QString::fromUtf8( value )
: QString::fromLatin1( value ) );
if ( haveEnt )
str = Qtopia::plainString( str );
/*
* add key + value
*/
todo( &dict, ev, attr, str );
}
/*
* now add it
*/
m_events.insert(ev.uid(), ev );
}
+ qWarning("counts %d", m_events.count() );
return true;
}
bool OTodoAccessXML::reload() {
return load();
}
bool OTodoAccessXML::save() {
// qWarning("saving");
if (!m_opened || !m_changed ) {
// qWarning("not saving");
return true;
}
QString strNewFile = m_file + ".new";
QFile f( strNewFile );
if (!f.open( IO_WriteOnly|IO_Raw ) )
return false;
int written;
QString out;
out = "<!DOCTYPE Tasks>\n<Tasks>\n";
// for all todos
QMap<int, OTodo>::Iterator it;
for (it = m_events.begin(); it != m_events.end(); ++it ) {
out+= "<Task " + toString( (*it) ) + " />\n";
QCString cstr = out.utf8();
written = f.writeBlock( cstr.data(), cstr.length() );
/* less written then we wanted */
if ( written != (int)cstr.length() ) {
f.close();
QFile::remove( strNewFile );
return false;
}
out = QString::null;
}
out += "</Tasks>";
QCString cstr = out.utf8();
written = f.writeBlock( cstr.data(), cstr.length() );
if ( written != (int)cstr.length() ) {
f.close();
QFile::remove( strNewFile );
return false;
}
/* flush before renaming */
f.close();
if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
// qWarning("error renaming");
QFile::remove( strNewFile );
}
m_changed = false;
return true;
}
QArray<int> OTodoAccessXML::allRecords()const {
QArray<int> ids( m_events.count() );
QMap<int, OTodo>::ConstIterator it;
int i = 0;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
ids[i] = it.key();
i++;
}
return ids;
}
QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int 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 ) {
// qWarning("add");
m_changed = true;
m_events.insert( todo.uid(), todo );
return true;
}
bool OTodoAccessXML::remove( int uid ) {
m_changed = true;
m_events.remove( uid );
return true;
}
bool OTodoAccessXML::replace( const OTodo& todo) {
m_changed = true;
m_events.replace( todo.uid(), todo );
return true;
}
QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
const QDate& end,
bool includeNoDates ) {
QArray<int> ids( m_events.count() );
QMap<int, OTodo>::Iterator it;
int i = 0;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
if ( !it.data().hasDueDate() ) {
if ( includeNoDates ) {
ids[i] = it.key();
i++;
}
}else if ( it.data().dueDate() >= start &&
it.data().dueDate() <= end ) {
ids[i] = it.key();
i++;
}
}
ids.resize( i );
return ids;
}
QArray<int> OTodoAccessXML::overDue() {
QArray<int> ids( m_events.count() );
int i = 0;
QMap<int, OTodo>::Iterator it;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
if ( it.data().isOverdue() ) {
ids[i] = it.key();
i++;
}
}
ids.resize( i );
return ids;
}
/* private */
void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
const QCString& attr, const QString& val) {
// qWarning("parse to do from XMLElement" );
int *find=0;
find = (*dict)[ attr.data() ];
if (!find ) {
// qWarning("Unknown option" + it.key() );
ev.setCustomField( attr, val );
return;
}
switch( *find ) {
case OTodo::Uid:
ev.setUid( val.toInt() );
break;
case OTodo::Category:
ev.setCategories( ev.idsFromString( val ) );
break;
case OTodo::HasDate:
ev.setHasDueDate( val.toInt() );
break;
case OTodo::Completed:
ev.setCompleted( val.toInt() );
break;
case OTodo::Description:
ev.setDescription( val );
break;
case OTodo::Summary:
ev.setSummary( val );
break;
case OTodo::Priority:
ev.setPriority( val.toInt() );
break;
case OTodo::DateDay:
m_day = val.toInt();
break;
case OTodo::DateMonth:
m_month = val.toInt();
break;
case OTodo::DateYear:
m_year = val.toInt();
break;
case OTodo::Progress:
ev.setProgress( val.toInt() );
break;
case OTodo::CrossReference:
{
/*
* A cross refernce looks like
* appname,id;appname,id
* we need to split it up
*/
QStringList refs = QStringList::split(';', val );
QStringList::Iterator strIt;
for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
int pos = (*strIt).find(',');
if ( pos > -1 )
ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
}
break;
}
case OTodo::HasAlarmDateTime:
ev.setHasAlarmDateTime( val.toInt() );
break;
case OTodo::AlarmDateTime: {
/* this sounds better ;) zecke */
ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) );
break;
}
default:
break;
}
if ( ev.hasDueDate() ) {
QDate date( m_year, m_month, m_day );
ev.setDueDate( date );
}
}
QString OTodoAccessXML::toString( const OTodo& ev )const {
QString str;
str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
str += "Categories=\"" + toString( ev.categories() ) + "\" ";
str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
if ( ev.hasDueDate() ) {
str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
}
// qWarning( "Uid %d", ev.uid() );
str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
// append the extra options
/* FIXME Qtopia::Record this is currently not
* possible you can set custom fields
* but don' iterate over the list
* I may do #define private protected
* for this case - cough --zecke
*/
/*
QMap<QString, QString> extras = ev.extras();
QMap<QString, QString>::Iterator extIt;
for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
str += extIt.key() + "=\"" + extIt.data() + "\" ";
*/
// cross refernce
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 );
}
/* internal class for sorting */
struct OTodoXMLContainer {
OTodo todo;
};
/*
* Returns:
* 0 if item1 == item2
*
* non-zero if item1 != item2
*
* This function returns int rather than bool so that reimplementations
* can return one of three values and use it to sort by:
*
* 0 if item1 == item2
*
* > 0 (positive integer) if item1 > item2
*
* < 0 (negative integer) if item1 < item2
*
*/
class OTodoXMLVector : public QVector<OTodoXMLContainer> {
public:
OTodoXMLVector(int size, bool asc, int sort)
: QVector<OTodoXMLContainer>( size )
{
setAutoDelete( true );
m_asc = asc;
m_sort = sort;
}
/* return the summary/description */
QString string( const OTodo& todo) {
return todo.summary().isEmpty() ?
todo.description().left(20 ) :
todo.summary();
}
/**
* we take the sortorder( switch on it )
*
*/
int compareItems( Item d1, Item d2 ) {
qWarning("compare items");
int ret =0;
OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
/* same item */
if ( con1->todo.uid() == con2->todo.uid() )
return 0;
qWarning("m_sort %d", m_sort );
switch ( m_sort ) {
/* completed */
case 0: {
ret = 0;
if ( con1->todo.isCompleted() ) ret++;
if ( con2->todo.isCompleted() ) ret--;
break;
}
/* priority */
case 1: {
ret = con1->todo.priority() - con2->todo.priority();
qWarning(" priority %d %d %d", ret,
con1->todo.priority(),
con2->todo.priority()
);
break;
}
/* description */
case 2: {
QString str1 = string( con1->todo );
QString str2 = string( con2->todo );
ret = QString::compare( str1, str2 );
break;
}
/* deadline */
case 3: {
/* either bot got a dueDate
* or one of them got one
*/
if ( con1->todo.hasDueDate() &&
con2->todo.hasDueDate() )
ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() );
else if ( con1->todo.hasDueDate() )
ret = -1;
else if ( con2->todo.hasDueDate() )
ret = 0;
break;
}
default:
ret = 0;
break;
};
/* twist it we're not ascending*/
if (!m_asc)
ret = ret * -1;
return ret;
}
private: