-rw-r--r-- | libopie/pim/otodo.cpp | 1 | ||||
-rw-r--r-- | libopie/pim/otodoaccessxml.cpp | 240 | ||||
-rw-r--r-- | libopie/pim/otodoaccessxml.h | 3 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.cpp | 240 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.h | 3 | ||||
-rw-r--r-- | libopie2/opiepim/otodo.cpp | 1 |
6 files changed, 280 insertions, 208 deletions
diff --git a/libopie/pim/otodo.cpp b/libopie/pim/otodo.cpp index eb9dad3..6dd4c0e 100644 --- a/libopie/pim/otodo.cpp +++ b/libopie/pim/otodo.cpp @@ -127,97 +127,96 @@ QString OTodo::summary() const return data->sum; } ushort OTodo::progress() const { return data->prog; } QDate OTodo::dueDate()const { return data->date; } QDateTime OTodo::alarmDateTime() const { return data->alarmDateTime; } QString OTodo::description()const { return data->desc; } void OTodo::setCompleted( bool completed ) { changeOrModify(); data->isCompleted = completed; } void OTodo::setHasDueDate( bool hasDate ) { changeOrModify(); data->hasDate = hasDate; } void OTodo::setHasAlarmDateTime( bool hasAlarmDateTime ) { changeOrModify(); data->hasAlarmDateTime = hasAlarmDateTime; } void OTodo::setDescription(const QString &desc ) { // qWarning( "desc " + desc ); changeOrModify(); data->desc = Qtopia::simplifyMultiLineSpace(desc ); } void OTodo::setSummary( const QString& sum ) { changeOrModify(); data->sum = sum; } void OTodo::setPriority(int prio ) { - qWarning("set priority %d", prio); changeOrModify(); data->priority = prio; } void OTodo::setDueDate( QDate date ) { changeOrModify(); data->date = date; } void OTodo::setAlarmDateTime( const QDateTime& alarm ) { changeOrModify(); data->alarmDateTime = alarm; } bool OTodo::isOverdue( ) { if( data->hasDate ) return QDate::currentDate() > data->date; return false; } void OTodo::setProgress(ushort progress ) { changeOrModify(); data->prog = progress; } QString OTodo::toShortText() const { return summary(); } /*! Returns a richt text string */ QString OTodo::toRichText() const { QString text; QStringList catlist; // Description of the todo if ( !summary().isEmpty() ) { text += "<b>" + QObject::tr( "Summary:") + "</b><br>"; text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; } if( !description().isEmpty() ){ text += "<b>" + QObject::tr( "Description:" ) + "</b><br>"; text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) ; } text += "<br><br><br>"; text += "<b>" + QObject::tr( "Priority:") +" </b>" + QString::number( priority() ) + " <br>"; diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp index 692483e..31822d4 100644 --- a/libopie/pim/otodoaccessxml.cpp +++ b/libopie/pim/otodoaccessxml.cpp @@ -1,126 +1,169 @@ #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) ); - 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(); + // 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; - 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 ); + 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 ); - element = element->nextChild(); } - }else { -// qWarning("could not parse"); - return false;; + /* + * now add it + */ + m_events.insert(ev.uid(), ev ); } - delete root; -// qWarning("Access %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(); @@ -175,183 +218,176 @@ bool OTodoAccessXML::remove( int 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 { +void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, + const QCString& attr, const QString& val) { // 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 ) { + + find = (*dict)[ attr.data() ]; + if (!find ) { // qWarning("Unknown option" + it.key() ); - ev.setCustomField( it.key(), it.data() ); - continue; - } + ev.setCustomField( attr, val ); + return; + } - 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: - qWarning("ParsePriority " + it.data() ); - 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() ); + 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( it.data().toInt() ); - break; - case OTodo::AlarmDateTime: { - /* this sounds better ;) zecke */ - ev.setAlarmDateTime( TimeConversion::fromISO8601( it.data().local8Bit() ) ); - break; - } - default: - break; } + 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( year, month, day ); + QDate date( m_year, m_month, m_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() ) + "\" "; } // 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 ) @@ -435,77 +471,77 @@ public: ); 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: bool m_asc; int m_sort; }; QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, int sortFilter, int cat ) { OTodoXMLVector vector(m_events.count(), asc,sortOrder ); QMap<int, OTodo>::Iterator it; int item = 0; bool bCat = sortFilter & 1 ? true : false; bool bOver = sortFilter & 0 ? true : false; - bool bOnly = split & 2 ? true : false; + bool bOnly = sortFilter & 2 ? true : false; for ( it = m_events.begin(); it != m_events.end(); ++it ) { /* show category */ if ( bCat ) if (!(*it).categories().contains( cat ) ) continue; /* isOverdue but we should not show overdue */ if ( (*it).isOverdue() && ( !bOver || !bOnly ) ) continue; if ( !(*it).isOverdue() && bOnly ) continue; OTodoXMLContainer* con = new OTodoXMLContainer(); con->todo = (*it); vector.insert(item, con ); item++; } vector.resize( item ); /* sort it now */ vector.sort(); /* now get the uids */ QArray<int> array( vector.count() ); for (uint i= 0; i < vector.count(); i++ ) { array[i] = ( vector.at(i) )->todo.uid(); } return array; }; diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h index 6886bab..1e7e371 100644 --- a/libopie/pim/otodoaccessxml.h +++ b/libopie/pim/otodoaccessxml.h @@ -1,55 +1,56 @@ #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(); QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ); private: - OTodo todo( QAsciiDict<int>*, Opie::XMLElement* )const; + void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); QString toString( const OTodo& )const; QString toString( const QArray<int>& ints ) const; QMap<int, OTodo> m_events; QString m_file; QString m_app; bool m_opened : 1; bool m_changed : 1; class OTodoAccessXMLPrivate; OTodoAccessXMLPrivate* d; + int m_year, m_month, m_day; }; #endif diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index 692483e..31822d4 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp @@ -1,126 +1,169 @@ #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) ); - 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(); + // 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; - 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 ); + 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 ); - element = element->nextChild(); } - }else { -// qWarning("could not parse"); - return false;; + /* + * now add it + */ + m_events.insert(ev.uid(), ev ); } - delete root; -// qWarning("Access %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(); @@ -175,183 +218,176 @@ bool OTodoAccessXML::remove( int 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 { +void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, + const QCString& attr, const QString& val) { // 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 ) { + + find = (*dict)[ attr.data() ]; + if (!find ) { // qWarning("Unknown option" + it.key() ); - ev.setCustomField( it.key(), it.data() ); - continue; - } + ev.setCustomField( attr, val ); + return; + } - 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: - qWarning("ParsePriority " + it.data() ); - 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() ); + 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( it.data().toInt() ); - break; - case OTodo::AlarmDateTime: { - /* this sounds better ;) zecke */ - ev.setAlarmDateTime( TimeConversion::fromISO8601( it.data().local8Bit() ) ); - break; - } - default: - break; } + 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( year, month, day ); + QDate date( m_year, m_month, m_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() ) + "\" "; } // 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 ) @@ -435,77 +471,77 @@ public: ); 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: bool m_asc; int m_sort; }; QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, int sortFilter, int cat ) { OTodoXMLVector vector(m_events.count(), asc,sortOrder ); QMap<int, OTodo>::Iterator it; int item = 0; bool bCat = sortFilter & 1 ? true : false; bool bOver = sortFilter & 0 ? true : false; - bool bOnly = split & 2 ? true : false; + bool bOnly = sortFilter & 2 ? true : false; for ( it = m_events.begin(); it != m_events.end(); ++it ) { /* show category */ if ( bCat ) if (!(*it).categories().contains( cat ) ) continue; /* isOverdue but we should not show overdue */ if ( (*it).isOverdue() && ( !bOver || !bOnly ) ) continue; if ( !(*it).isOverdue() && bOnly ) continue; OTodoXMLContainer* con = new OTodoXMLContainer(); con->todo = (*it); vector.insert(item, con ); item++; } vector.resize( item ); /* sort it now */ vector.sort(); /* now get the uids */ QArray<int> array( vector.count() ); for (uint i= 0; i < vector.count(); i++ ) { array[i] = ( vector.at(i) )->todo.uid(); } return array; }; diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h index 6886bab..1e7e371 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.h +++ b/libopie2/opiepim/backend/otodoaccessxml.h @@ -1,55 +1,56 @@ #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(); QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ); private: - OTodo todo( QAsciiDict<int>*, Opie::XMLElement* )const; + void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); QString toString( const OTodo& )const; QString toString( const QArray<int>& ints ) const; QMap<int, OTodo> m_events; QString m_file; QString m_app; bool m_opened : 1; bool m_changed : 1; class OTodoAccessXMLPrivate; OTodoAccessXMLPrivate* d; + int m_year, m_month, m_day; }; #endif diff --git a/libopie2/opiepim/otodo.cpp b/libopie2/opiepim/otodo.cpp index eb9dad3..6dd4c0e 100644 --- a/libopie2/opiepim/otodo.cpp +++ b/libopie2/opiepim/otodo.cpp @@ -127,97 +127,96 @@ QString OTodo::summary() const return data->sum; } ushort OTodo::progress() const { return data->prog; } QDate OTodo::dueDate()const { return data->date; } QDateTime OTodo::alarmDateTime() const { return data->alarmDateTime; } QString OTodo::description()const { return data->desc; } void OTodo::setCompleted( bool completed ) { changeOrModify(); data->isCompleted = completed; } void OTodo::setHasDueDate( bool hasDate ) { changeOrModify(); data->hasDate = hasDate; } void OTodo::setHasAlarmDateTime( bool hasAlarmDateTime ) { changeOrModify(); data->hasAlarmDateTime = hasAlarmDateTime; } void OTodo::setDescription(const QString &desc ) { // qWarning( "desc " + desc ); changeOrModify(); data->desc = Qtopia::simplifyMultiLineSpace(desc ); } void OTodo::setSummary( const QString& sum ) { changeOrModify(); data->sum = sum; } void OTodo::setPriority(int prio ) { - qWarning("set priority %d", prio); changeOrModify(); data->priority = prio; } void OTodo::setDueDate( QDate date ) { changeOrModify(); data->date = date; } void OTodo::setAlarmDateTime( const QDateTime& alarm ) { changeOrModify(); data->alarmDateTime = alarm; } bool OTodo::isOverdue( ) { if( data->hasDate ) return QDate::currentDate() > data->date; return false; } void OTodo::setProgress(ushort progress ) { changeOrModify(); data->prog = progress; } QString OTodo::toShortText() const { return summary(); } /*! Returns a richt text string */ QString OTodo::toRichText() const { QString text; QStringList catlist; // Description of the todo if ( !summary().isEmpty() ) { text += "<b>" + QObject::tr( "Summary:") + "</b><br>"; text += Qtopia::escapeString(summary() ).replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; } if( !description().isEmpty() ){ text += "<b>" + QObject::tr( "Description:" ) + "</b><br>"; text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "<br>" ) ; } text += "<br><br><br>"; text += "<b>" + QObject::tr( "Priority:") +" </b>" + QString::number( priority() ) + " <br>"; |