summaryrefslogtreecommitdiff
path: root/noncore/unsupported/libopie/pim/otodoaccessxml.cpp
Unidiff
Diffstat (limited to 'noncore/unsupported/libopie/pim/otodoaccessxml.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/libopie/pim/otodoaccessxml.cpp876
1 files changed, 876 insertions, 0 deletions
diff --git a/noncore/unsupported/libopie/pim/otodoaccessxml.cpp b/noncore/unsupported/libopie/pim/otodoaccessxml.cpp
new file mode 100644
index 0000000..4a5cb33
--- a/dev/null
+++ b/noncore/unsupported/libopie/pim/otodoaccessxml.cpp
@@ -0,0 +1,876 @@
1#include <errno.h>
2#include <fcntl.h>
3
4#include <sys/mman.h>
5#include <sys/stat.h>
6#include <sys/types.h>
7
8#include <unistd.h>
9
10
11#include <qfile.h>
12#include <qvector.h>
13
14#include <qpe/global.h>
15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h>
17
18#include "oconversion.h"
19#include "opimstate.h"
20#include "otimezone.h"
21#include "opimnotifymanager.h"
22#include "orecur.h"
23#include "otodoaccessxml.h"
24
25namespace {
26 time_t rp_end;
27 ORecur* rec;
28 ORecur *recur() {
29 if (!rec ) rec = new ORecur;
30 return rec;
31 }
32 int snd;
33 enum MoreAttributes {
34 FRType = OTodo::CompletedDate + 2,
35 FRWeekdays,
36 FRPosition,
37 FRFreq,
38 FRHasEndDate,
39 FREndDate,
40 FRStart,
41 FREnd
42 };
43 // FROM TT again
44char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
45{
46 char needleChar;
47 char haystackChar;
48 if (!needle || !haystack || !hLen || !nLen)
49 return 0;
50
51 const char* hsearch = haystack;
52
53 if ((needleChar = *needle++) != 0) {
54 nLen--; //(to make up for needle++)
55 do {
56 do {
57 if ((haystackChar = *hsearch++) == 0)
58 return (0);
59 if (hsearch >= haystack + hLen)
60 return (0);
61 } while (haystackChar != needleChar);
62 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
63 hsearch--;
64 }
65 return ((char *)hsearch);
66}
67}
68
69
70OTodoAccessXML::OTodoAccessXML( const QString& appName,
71 const QString& fileName )
72 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
73{
74 if (!fileName.isEmpty() )
75 m_file = fileName;
76 else
77 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
78}
79OTodoAccessXML::~OTodoAccessXML() {
80
81}
82bool OTodoAccessXML::load() {
83 rec = 0;
84 m_opened = true;
85 m_changed = false;
86 /* initialize dict */
87 /*
88 * UPDATE dict if you change anything!!!
89 */
90 QAsciiDict<int> dict(26);
91 dict.setAutoDelete( TRUE );
92 dict.insert("Categories" , new int(OTodo::Category) );
93 dict.insert("Uid" , new int(OTodo::Uid) );
94 dict.insert("HasDate" , new int(OTodo::HasDate) );
95 dict.insert("Completed" , new int(OTodo::Completed) );
96 dict.insert("Description" , new int(OTodo::Description) );
97 dict.insert("Summary" , new int(OTodo::Summary) );
98 dict.insert("Priority" , new int(OTodo::Priority) );
99 dict.insert("DateDay" , new int(OTodo::DateDay) );
100 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
101 dict.insert("DateYear" , new int(OTodo::DateYear) );
102 dict.insert("Progress" , new int(OTodo::Progress) );
103 dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
104 dict.insert("StartDate", new int(OTodo::StartDate) );
105 dict.insert("CrossReference", new int(OTodo::CrossReference) );
106 dict.insert("State", new int(OTodo::State) );
107 dict.insert("Alarms", new int(OTodo::Alarms) );
108 dict.insert("Reminders", new int(OTodo::Reminders) );
109 dict.insert("Notifiers", new int(OTodo::Notifiers) );
110 dict.insert("Maintainer", new int(OTodo::Maintainer) );
111 dict.insert("rtype", new int(FRType) );
112 dict.insert("rweekdays", new int(FRWeekdays) );
113 dict.insert("rposition", new int(FRPosition) );
114 dict.insert("rfreq", new int(FRFreq) );
115 dict.insert("start", new int(FRStart) );
116 dict.insert("rhasenddate", new int(FRHasEndDate) );
117 dict.insert("enddt", new int(FREndDate) );
118
119 // here the custom XML parser from TT it's GPL
120 // but we want to push OpiePIM... to TT.....
121 // mmap part from zecke :)
122 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
123 struct stat attribut;
124 if ( fd < 0 ) return false;
125
126 if ( fstat(fd, &attribut ) == -1 ) {
127 ::close( fd );
128 return false;
129 }
130 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
131 if ( map_addr == ( (caddr_t)-1) ) {
132 ::close(fd );
133 return false;
134 }
135 /* advise the kernel who we want to read it */
136 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
137 /* we do not the file any more */
138 ::close( fd );
139
140 char* dt = (char*)map_addr;
141 int len = attribut.st_size;
142 int i = 0;
143 char *point;
144 const char* collectionString = "<Task ";
145 int strLen = strlen(collectionString);
146 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
147 i = point -dt;
148 i+= strLen;
149 qWarning("Found a start at %d %d", i, (point-dt) );
150
151 OTodo ev;
152 m_year = m_month = m_day = 0;
153
154 while ( TRUE ) {
155 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
156 ++i;
157 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
158 break;
159
160 // we have another attribute, read it.
161 int j = i;
162 while ( j < len && dt[j] != '=' )
163 ++j;
164 QCString attr( dt+i, j-i+1);
165
166 i = ++j; // skip =
167
168 // find the start of quotes
169 while ( i < len && dt[i] != '"' )
170 ++i;
171 j = ++i;
172
173 bool haveUtf = FALSE;
174 bool haveEnt = FALSE;
175 while ( j < len && dt[j] != '"' ) {
176 if ( ((unsigned char)dt[j]) > 0x7f )
177 haveUtf = TRUE;
178 if ( dt[j] == '&' )
179 haveEnt = TRUE;
180 ++j;
181 }
182 if ( i == j ) {
183 // empty value
184 i = j + 1;
185 continue;
186 }
187
188 QCString value( dt+i, j-i+1 );
189 i = j + 1;
190
191 QString str = (haveUtf ? QString::fromUtf8( value )
192 : QString::fromLatin1( value ) );
193 if ( haveEnt )
194 str = Qtopia::plainString( str );
195
196 /*
197 * add key + value
198 */
199 todo( &dict, ev, attr, str );
200
201 }
202 /*
203 * now add it
204 */
205 qWarning("End at %d", i );
206 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
207 ev.setUid( 1 );
208 m_changed = true;
209 }
210 if ( ev.hasDueDate() ) {
211 ev.setDueDate( QDate(m_year, m_month, m_day) );
212 }
213 if ( rec && rec->doesRecur() ) {
214 OTimeZone utc = OTimeZone::utc();
215 ORecur recu( *rec ); // call copy c'tor
216 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
217 recu.setStart( ev.dueDate() );
218 ev.setRecurrence( recu );
219 }
220 m_events.insert(ev.uid(), ev );
221 m_year = m_month = m_day = -1;
222 delete rec;
223 rec = 0;
224 }
225
226 munmap(map_addr, attribut.st_size );
227
228 qWarning("counts %d records loaded!", m_events.count() );
229 return true;
230}
231bool OTodoAccessXML::reload() {
232 m_events.clear();
233 return load();
234}
235bool OTodoAccessXML::save() {
236// qWarning("saving");
237 if (!m_opened || !m_changed ) {
238// qWarning("not saving");
239 return true;
240 }
241 QString strNewFile = m_file + ".new";
242 QFile f( strNewFile );
243 if (!f.open( IO_WriteOnly|IO_Raw ) )
244 return false;
245
246 int written;
247 QString out;
248 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
249
250 // for all todos
251 QMap<int, OTodo>::Iterator it;
252 for (it = m_events.begin(); it != m_events.end(); ++it ) {
253 out+= "<Task " + toString( (*it) ) + " />\n";
254 QCString cstr = out.utf8();
255 written = f.writeBlock( cstr.data(), cstr.length() );
256
257 /* less written then we wanted */
258 if ( written != (int)cstr.length() ) {
259 f.close();
260 QFile::remove( strNewFile );
261 return false;
262 }
263 out = QString::null;
264 }
265
266 out += "</Tasks>";
267 QCString cstr = out.utf8();
268 written = f.writeBlock( cstr.data(), cstr.length() );
269
270 if ( written != (int)cstr.length() ) {
271 f.close();
272 QFile::remove( strNewFile );
273 return false;
274 }
275 /* flush before renaming */
276 f.close();
277
278 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
279// qWarning("error renaming");
280 QFile::remove( strNewFile );
281 }
282
283 m_changed = false;
284 return true;
285}
286QArray<int> OTodoAccessXML::allRecords()const {
287 QArray<int> ids( m_events.count() );
288 QMap<int, OTodo>::ConstIterator it;
289 int i = 0;
290
291 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
292 ids[i] = it.key();
293 i++;
294 }
295 return ids;
296}
297QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
298 QArray<int> ids(0);
299 return ids;
300}
301OTodo OTodoAccessXML::find( int uid )const {
302 OTodo todo;
303 todo.setUid( 0 ); // isEmpty()
304 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
305 if ( it != m_events.end() )
306 todo = it.data();
307
308 return todo;
309}
310void OTodoAccessXML::clear() {
311 if (m_opened )
312 m_changed = true;
313
314 m_events.clear();
315}
316bool OTodoAccessXML::add( const OTodo& todo ) {
317// qWarning("add");
318 m_changed = true;
319 m_events.insert( todo.uid(), todo );
320
321 return true;
322}
323bool OTodoAccessXML::remove( int uid ) {
324 m_changed = true;
325 m_events.remove( uid );
326
327 return true;
328}
329bool OTodoAccessXML::replace( const OTodo& todo) {
330 m_changed = true;
331 m_events.replace( todo.uid(), todo );
332
333 return true;
334}
335QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
336 const QDate& end,
337 bool includeNoDates ) {
338 QArray<int> ids( m_events.count() );
339 QMap<int, OTodo>::Iterator it;
340
341 int i = 0;
342 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
343 if ( !it.data().hasDueDate() ) {
344 if ( includeNoDates ) {
345 ids[i] = it.key();
346 i++;
347 }
348 }else if ( it.data().dueDate() >= start &&
349 it.data().dueDate() <= end ) {
350 ids[i] = it.key();
351 i++;
352 }
353 }
354 ids.resize( i );
355 return ids;
356}
357QArray<int> OTodoAccessXML::overDue() {
358 QArray<int> ids( m_events.count() );
359 int i = 0;
360
361 QMap<int, OTodo>::Iterator it;
362 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
363 if ( it.data().isOverdue() ) {
364 ids[i] = it.key();
365 i++;
366 }
367 }
368 ids.resize( i );
369 return ids;
370}
371
372
373/* private */
374void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
375 const QCString& attr, const QString& val) {
376// qWarning("parse to do from XMLElement" );
377
378 int *find=0;
379
380 find = (*dict)[ attr.data() ];
381 if (!find ) {
382// qWarning("Unknown option" + it.key() );
383 ev.setCustomField( attr, val );
384 return;
385 }
386
387 switch( *find ) {
388 case OTodo::Uid:
389 ev.setUid( val.toInt() );
390 break;
391 case OTodo::Category:
392 ev.setCategories( ev.idsFromString( val ) );
393 break;
394 case OTodo::HasDate:
395 ev.setHasDueDate( val.toInt() );
396 break;
397 case OTodo::Completed:
398 ev.setCompleted( val.toInt() );
399 break;
400 case OTodo::Description:
401 ev.setDescription( val );
402 break;
403 case OTodo::Summary:
404 ev.setSummary( val );
405 break;
406 case OTodo::Priority:
407 ev.setPriority( val.toInt() );
408 break;
409 case OTodo::DateDay:
410 m_day = val.toInt();
411 break;
412 case OTodo::DateMonth:
413 m_month = val.toInt();
414 break;
415 case OTodo::DateYear:
416 m_year = val.toInt();
417 break;
418 case OTodo::Progress:
419 ev.setProgress( val.toInt() );
420 break;
421 case OTodo::CompletedDate:
422 ev.setCompletedDate( OConversion::dateFromString( val ) );
423 break;
424 case OTodo::StartDate:
425 ev.setStartDate( OConversion::dateFromString( val ) );
426 break;
427 case OTodo::State:
428 ev.setState( val.toInt() );
429 break;
430 case OTodo::Alarms:{
431 OPimNotifyManager &manager = ev.notifiers();
432 QStringList als = QStringList::split(";", val );
433 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
434 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
435 qWarning("alarm: %s", alarm.join("___").latin1() );
436 qWarning("alarm[0]: %s %s", alarm[0].latin1(), OConversion::dateTimeFromString( alarm[0] ).toString().latin1() );
437 OPimAlarm al( alarm[2].toInt(), OConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() );
438 manager.add( al );
439 }
440 }
441 break;
442 case OTodo::Reminders:{
443 OPimNotifyManager &manager = ev.notifiers();
444 QStringList rems = QStringList::split(";", val );
445 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
446 OPimReminder rem( (*it).toInt() );
447 manager.add( rem );
448 }
449 }
450 break;
451 case OTodo::CrossReference:
452 {
453 /*
454 * A cross refernce looks like
455 * appname,id;appname,id
456 * we need to split it up
457 */
458 QStringList refs = QStringList::split(';', val );
459 QStringList::Iterator strIt;
460 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
461 int pos = (*strIt).find(',');
462 if ( pos > -1 )
463 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
464
465 }
466 break;
467 }
468 /* Recurrence stuff below + post processing later */
469 case FRType:
470 if ( val == "Daily" )
471 recur()->setType( ORecur::Daily );
472 else if ( val == "Weekly" )
473 recur()->setType( ORecur::Weekly);
474 else if ( val == "MonthlyDay" )
475 recur()->setType( ORecur::MonthlyDay );
476 else if ( val == "MonthlyDate" )
477 recur()->setType( ORecur::MonthlyDate );
478 else if ( val == "Yearly" )
479 recur()->setType( ORecur::Yearly );
480 else
481 recur()->setType( ORecur::NoRepeat );
482 break;
483 case FRWeekdays:
484 recur()->setDays( val.toInt() );
485 break;
486 case FRPosition:
487 recur()->setPosition( val.toInt() );
488 break;
489 case FRFreq:
490 recur()->setFrequency( val.toInt() );
491 break;
492 case FRHasEndDate:
493 recur()->setHasEndDate( val.toInt() );
494 break;
495 case FREndDate: {
496 rp_end = (time_t) val.toLong();
497 break;
498 }
499 default:
500 ev.setCustomField( attr, val );
501 break;
502 }
503}
504
505// from PalmtopRecord... GPL ### FIXME
506namespace {
507QString customToXml(const QMap<QString, QString>& customMap )
508{
509 //qWarning(QString("writing custom %1").arg(customMap.count()));
510 QString buf(" ");
511 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
512 cit != customMap.end(); ++cit) {
513 // qWarning(".ITEM.");
514 buf += cit.key();
515 buf += "=\"";
516 buf += Qtopia::escapeString(cit.data());
517 buf += "\" ";
518 }
519 return buf;
520}
521
522
523}
524
525QString OTodoAccessXML::toString( const OTodo& ev )const {
526 QString str;
527
528 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
529 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
530 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
531 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
532
533 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
534 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
535 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
536
537 if ( ev.hasDueDate() ) {
538 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
539 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
540 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
541 }
542// qWarning( "Uid %d", ev.uid() );
543 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
544
545// append the extra options
546 /* FIXME Qtopia::Record this is currently not
547 * possible you can set custom fields
548 * but don' iterate over the list
549 * I may do #define private protected
550 * for this case - cough --zecke
551 */
552 /*
553 QMap<QString, QString> extras = ev.extras();
554 QMap<QString, QString>::Iterator extIt;
555 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
556 str += extIt.key() + "=\"" + extIt.data() + "\" ";
557 */
558 // cross refernce
559 if ( ev.hasRecurrence() ) {
560 str += ev.recurrence().toString();
561 }
562 if ( ev.hasStartDate() )
563 str += "StartDate=\""+ OConversion::dateToString( ev.startDate() ) +"\" ";
564 if ( ev.hasCompletedDate() )
565 str += "CompletedDate=\""+ OConversion::dateToString( ev.completedDate() ) +"\" ";
566 if ( ev.hasState() )
567 str += "State=\""+QString::number( ev.state().state() )+"\" ";
568
569 /*
570 * save reminders and notifiers!
571 * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:....
572 */
573 if ( ev.hasNotifiers() ) {
574 OPimNotifyManager manager = ev.notifiers();
575 OPimNotifyManager::Alarms alarms = manager.alarms();
576 if (!alarms.isEmpty() ) {
577 QStringList als;
578 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
579 for ( ; it != alarms.end(); ++it ) {
580 /* only if time is valid */
581 if ( (*it).dateTime().isValid() ) {
582 als << OConversion::dateTimeToString( (*it).dateTime() )
583 + ":" + QString::number( (*it).duration() )
584 + ":" + QString::number( (*it).sound() )
585 + ":";
586 }
587 }
588 // now write the list
589 qWarning("als: %s", als.join("____________").latin1() );
590 str += "Alarms=\""+als.join(";") +"\" ";
591 }
592
593 /*
594 * now the same for reminders but more easy. We just save the uid of the OEvent.
595 */
596 OPimNotifyManager::Reminders reminders = manager.reminders();
597 if (!reminders.isEmpty() ) {
598 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
599 QStringList records;
600 for ( ; it != reminders.end(); ++it ) {
601 records << QString::number( (*it).recordUid() );
602 }
603 str += "Reminders=\""+ records.join(";") +"\" ";
604 }
605 }
606 str += customToXml( ev.toExtraMap() );
607
608
609 return str;
610}
611QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
612 return Qtopia::Record::idsToString( ints );
613}
614
615/* internal class for sorting
616 *
617 * Inspired by todoxmlio.cpp from TT
618 */
619
620struct OTodoXMLContainer {
621 OTodo todo;
622};
623
624namespace {
625 inline QString string( const OTodo& todo) {
626 return todo.summary().isEmpty() ?
627 todo.description().left(20 ) :
628 todo.summary();
629 }
630 inline int completed( const OTodo& todo1, const OTodo& todo2) {
631 int ret = 0;
632 if ( todo1.isCompleted() ) ret++;
633 if ( todo2.isCompleted() ) ret--;
634 return ret;
635 }
636 inline int priority( const OTodo& t1, const OTodo& t2) {
637 return ( t1.priority() - t2.priority() );
638 }
639 inline int description( const OTodo& t1, const OTodo& t2) {
640 return QString::compare( string(t1), string(t2) );
641 }
642 inline int deadline( const OTodo& t1, const OTodo& t2) {
643 int ret = 0;
644 if ( t1.hasDueDate() &&
645 t2.hasDueDate() )
646 ret = t2.dueDate().daysTo( t1.dueDate() );
647 else if ( t1.hasDueDate() )
648 ret = -1;
649 else if ( t2.hasDueDate() )
650 ret = 1;
651 else
652 ret = 0;
653
654 return ret;
655 }
656
657};
658
659/*
660 * Returns:
661 * 0 if item1 == item2
662 *
663 * non-zero if item1 != item2
664 *
665 * This function returns int rather than bool so that reimplementations
666 * can return one of three values and use it to sort by:
667 *
668 * 0 if item1 == item2
669 *
670 * > 0 (positive integer) if item1 > item2
671 *
672 * < 0 (negative integer) if item1 < item2
673 *
674 */
675class OTodoXMLVector : public QVector<OTodoXMLContainer> {
676public:
677 OTodoXMLVector(int size, bool asc, int sort)
678 : QVector<OTodoXMLContainer>( size )
679 {
680 setAutoDelete( true );
681 m_asc = asc;
682 m_sort = sort;
683 }
684 /* return the summary/description */
685 QString string( const OTodo& todo) {
686 return todo.summary().isEmpty() ?
687 todo.description().left(20 ) :
688 todo.summary();
689 }
690 /**
691 * we take the sortorder( switch on it )
692 *
693 */
694 int compareItems( Item d1, Item d2 ) {
695 bool seComp, sePrio, seDesc, seDeadline;
696 seComp = sePrio = seDeadline = seDesc = false;
697 int ret =0;
698 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
699 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
700
701 /* same item */
702 if ( con1->todo.uid() == con2->todo.uid() )
703 return 0;
704
705 switch ( m_sort ) {
706 /* completed */
707 case 0: {
708 ret = completed( con1->todo, con2->todo );
709 seComp = TRUE;
710 break;
711 }
712 /* priority */
713 case 1: {
714 ret = priority( con1->todo, con2->todo );
715 sePrio = TRUE;
716 break;
717 }
718 /* description */
719 case 2: {
720 ret = description( con1->todo, con2->todo );
721 seDesc = TRUE;
722 break;
723 }
724 /* deadline */
725 case 3: {
726 ret = deadline( con1->todo, con2->todo );
727 seDeadline = TRUE;
728 break;
729 }
730 default:
731 ret = 0;
732 break;
733 };
734 /*
735 * FIXME do better sorting if the first sort criteria
736 * ret equals 0 start with complete and so on...
737 */
738
739 /* twist it we're not ascending*/
740 if (!m_asc)
741 ret = ret * -1;
742
743 if ( ret )
744 return ret;
745
746 // default did not gave difference let's try it other way around
747 /*
748 * General try if already checked if not test
749 * and return
750 * 1.Completed
751 * 2.Priority
752 * 3.Description
753 * 4.DueDate
754 */
755 if (!seComp ) {
756 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
757 if (!m_asc ) ret *= -1;
758 return ret;
759 }
760 }
761 if (!sePrio ) {
762 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
763 if (!m_asc ) ret *= -1;
764 return ret;
765 }
766 }
767 if (!seDesc ) {
768 if ( (ret = description(con1->todo, con2->todo ) ) ) {
769 if (!m_asc) ret *= -1;
770 return ret;
771 }
772 }
773 if (!seDeadline) {
774 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
775 if (!m_asc) ret *= -1;
776 return ret;
777 }
778 }
779
780 return 0;
781 }
782 private:
783 bool m_asc;
784 int m_sort;
785
786};
787
788QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
789 int sortFilter, int cat ) {
790 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
791 QMap<int, OTodo>::Iterator it;
792 int item = 0;
793
794 bool bCat = sortFilter & 1 ? true : false;
795 bool bOnly = sortFilter & 2 ? true : false;
796 bool comp = sortFilter & 4 ? true : false;
797 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
798
799 /* show category */
800 /* -1 == unfiled */
801 if ( bCat && cat == -1 ) {
802 if(!(*it).categories().isEmpty() )
803 continue;
804 }else if ( bCat && cat != 0)
805 if (!(*it).categories().contains( cat ) ) {
806 continue;
807 }
808 /* isOverdue but we should not show overdue - why?*/
809/* if ( (*it).isOverdue() && !bOnly ) {
810 qWarning("item is overdue but !bOnly");
811 continue;
812 }
813*/
814 if ( !(*it).isOverdue() && bOnly ) {
815 continue;
816 }
817
818 if ((*it).isCompleted() && comp ) {
819 continue;
820 }
821
822
823 OTodoXMLContainer* con = new OTodoXMLContainer();
824 con->todo = (*it);
825 vector.insert(item, con );
826 item++;
827 }
828 vector.resize( item );
829 /* sort it now */
830 vector.sort();
831 /* now get the uids */
832 QArray<int> array( vector.count() );
833 for (uint i= 0; i < vector.count(); i++ ) {
834 array[i] = ( vector.at(i) )->todo.uid();
835 }
836 return array;
837};
838void OTodoAccessXML::removeAllCompleted() {
839 QMap<int, OTodo> events = m_events;
840 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
841 if ( (*it).isCompleted() )
842 events.remove( it.key() );
843 }
844 m_events = events;
845}
846QBitArray OTodoAccessXML::supports()const {
847 static QBitArray ar = sup();
848 return ar;
849}
850QBitArray OTodoAccessXML::sup() {
851 QBitArray ar( OTodo::CompletedDate +1 );
852 ar.fill( true );
853 ar[OTodo::CrossReference] = false;
854 ar[OTodo::State ] = false;
855 ar[OTodo::Reminders] = false;
856 ar[OTodo::Notifiers] = false;
857 ar[OTodo::Maintainer] = false;
858
859 return ar;
860}
861QArray<int> OTodoAccessXML::matchRegexp( const QRegExp &r ) const
862{
863 QArray<int> m_currentQuery( m_events.count() );
864 uint arraycounter = 0;
865
866 QMap<int, OTodo>::ConstIterator it;
867 for (it = m_events.begin(); it != m_events.end(); ++it ) {
868 if ( it.data().match( r ) )
869 m_currentQuery[arraycounter++] = it.data().uid();
870
871 }
872 // Shrink to fit..
873 m_currentQuery.resize(arraycounter);
874
875 return m_currentQuery;
876}