summaryrefslogtreecommitdiff
path: root/libopie
authorzecke <zecke>2003-05-07 16:03:03 (UTC)
committer zecke <zecke>2003-05-07 16:03:03 (UTC)
commit7c8110d568ac60517916114ac5fc4e850156d4e5 (patch) (unidiff)
treecb4ffab444f078f013de7edd3d180e2e80b23ffa /libopie
parentaccd04a63230ac46978f77deae1b0d1419618730 (diff)
downloadopie-7c8110d568ac60517916114ac5fc4e850156d4e5.zip
opie-7c8110d568ac60517916114ac5fc4e850156d4e5.tar.gz
opie-7c8110d568ac60517916114ac5fc4e850156d4e5.tar.bz2
Save recurrence
Diffstat (limited to 'libopie') (more/less context) (show whitespace changes)
-rw-r--r--libopie/pim/otodoaccessxml.cpp4
1 files changed, 3 insertions, 1 deletions
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index 55f268b..c0d8dfc 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -1,113 +1,114 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <unistd.h> 8#include <unistd.h>
9 9
10 10
11#include <qfile.h> 11#include <qfile.h>
12#include <qvector.h> 12#include <qvector.h>
13 13
14#include <qpe/global.h> 14#include <qpe/global.h>
15#include <qpe/stringutil.h> 15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h> 16#include <qpe/timeconversion.h>
17 17
18#include "orecur.h"
18#include "otodoaccessxml.h" 19#include "otodoaccessxml.h"
19 20
20namespace { 21namespace {
21 // FROM TT again 22 // FROM TT again
22char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 23char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
23{ 24{
24 char needleChar; 25 char needleChar;
25 char haystackChar; 26 char haystackChar;
26 if (!needle || !haystack || !hLen || !nLen) 27 if (!needle || !haystack || !hLen || !nLen)
27 return 0; 28 return 0;
28 29
29 const char* hsearch = haystack; 30 const char* hsearch = haystack;
30 31
31 if ((needleChar = *needle++) != 0) { 32 if ((needleChar = *needle++) != 0) {
32 nLen--; //(to make up for needle++) 33 nLen--; //(to make up for needle++)
33 do { 34 do {
34 do { 35 do {
35 if ((haystackChar = *hsearch++) == 0) 36 if ((haystackChar = *hsearch++) == 0)
36 return (0); 37 return (0);
37 if (hsearch >= haystack + hLen) 38 if (hsearch >= haystack + hLen)
38 return (0); 39 return (0);
39 } while (haystackChar != needleChar); 40 } while (haystackChar != needleChar);
40 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 41 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
41 hsearch--; 42 hsearch--;
42 } 43 }
43 return ((char *)hsearch); 44 return ((char *)hsearch);
44} 45}
45} 46}
46 47
47 48
48OTodoAccessXML::OTodoAccessXML( const QString& appName, 49OTodoAccessXML::OTodoAccessXML( const QString& appName,
49 const QString& fileName ) 50 const QString& fileName )
50 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 51 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
51{ 52{
52 if (!fileName.isEmpty() ) 53 if (!fileName.isEmpty() )
53 m_file = fileName; 54 m_file = fileName;
54 else 55 else
55 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 56 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
56} 57}
57OTodoAccessXML::~OTodoAccessXML() { 58OTodoAccessXML::~OTodoAccessXML() {
58 59
59} 60}
60bool OTodoAccessXML::load() { 61bool OTodoAccessXML::load() {
61 m_opened = true; 62 m_opened = true;
62 m_changed = false; 63 m_changed = false;
63 /* initialize dict */ 64 /* initialize dict */
64 /* 65 /*
65 * UPDATE dict if you change anything!!! 66 * UPDATE dict if you change anything!!!
66 */ 67 */
67 QAsciiDict<int> dict(21); 68 QAsciiDict<int> dict(21);
68 dict.setAutoDelete( TRUE ); 69 dict.setAutoDelete( TRUE );
69 dict.insert("Categories" , new int(OTodo::Category) ); 70 dict.insert("Categories" , new int(OTodo::Category) );
70 dict.insert("Uid" , new int(OTodo::Uid) ); 71 dict.insert("Uid" , new int(OTodo::Uid) );
71 dict.insert("HasDate" , new int(OTodo::HasDate) ); 72 dict.insert("HasDate" , new int(OTodo::HasDate) );
72 dict.insert("Completed" , new int(OTodo::Completed) ); 73 dict.insert("Completed" , new int(OTodo::Completed) );
73 dict.insert("Description" , new int(OTodo::Description) ); 74 dict.insert("Description" , new int(OTodo::Description) );
74 dict.insert("Summary" , new int(OTodo::Summary) ); 75 dict.insert("Summary" , new int(OTodo::Summary) );
75 dict.insert("Priority" , new int(OTodo::Priority) ); 76 dict.insert("Priority" , new int(OTodo::Priority) );
76 dict.insert("DateDay" , new int(OTodo::DateDay) ); 77 dict.insert("DateDay" , new int(OTodo::DateDay) );
77 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 78 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
78 dict.insert("DateYear" , new int(OTodo::DateYear) ); 79 dict.insert("DateYear" , new int(OTodo::DateYear) );
79 dict.insert("Progress" , new int(OTodo::Progress) ); 80 dict.insert("Progress" , new int(OTodo::Progress) );
80 dict.insert("Completed", new int(OTodo::Completed) ); 81 dict.insert("Completed", new int(OTodo::Completed) );
81 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 82 dict.insert("CrossReference", new int(OTodo::CrossReference) );
82 dict.insert("State", new int(OTodo::State) ); 83 dict.insert("State", new int(OTodo::State) );
83 dict.insert("Recurrence", new int(OTodo::Recurrence) ); 84 dict.insert("Recurrence", new int(OTodo::Recurrence) );
84 dict.insert("Alarms", new int(OTodo::Alarms) ); 85 dict.insert("Alarms", new int(OTodo::Alarms) );
85 dict.insert("Reminders", new int(OTodo::Reminders) ); 86 dict.insert("Reminders", new int(OTodo::Reminders) );
86 dict.insert("Notifiers", new int(OTodo::Notifiers) ); 87 dict.insert("Notifiers", new int(OTodo::Notifiers) );
87 dict.insert("Maintainer", new int(OTodo::Maintainer) ); 88 dict.insert("Maintainer", new int(OTodo::Maintainer) );
88 89
89 // here the custom XML parser from TT it's GPL 90 // here the custom XML parser from TT it's GPL
90 // but we want to push OpiePIM... to TT..... 91 // but we want to push OpiePIM... to TT.....
91 // mmap part from zecke :) 92 // mmap part from zecke :)
92 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 93 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
93 struct stat attribut; 94 struct stat attribut;
94 if ( fd < 0 ) return false; 95 if ( fd < 0 ) return false;
95 96
96 if ( fstat(fd, &attribut ) == -1 ) { 97 if ( fstat(fd, &attribut ) == -1 ) {
97 ::close( fd ); 98 ::close( fd );
98 return false; 99 return false;
99 } 100 }
100 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 101 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
101 if ( map_addr == ( (caddr_t)-1) ) { 102 if ( map_addr == ( (caddr_t)-1) ) {
102 ::close(fd ); 103 ::close(fd );
103 return false; 104 return false;
104 } 105 }
105 /* advise the kernel who we want to read it */ 106 /* advise the kernel who we want to read it */
106 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 107 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
107 /* we do not the file any more */ 108 /* we do not the file any more */
108 ::close( fd ); 109 ::close( fd );
109 110
110 char* dt = (char*)map_addr; 111 char* dt = (char*)map_addr;
111 int len = attribut.st_size; 112 int len = attribut.st_size;
112 int i = 0; 113 int i = 0;
113 char *point; 114 char *point;
@@ -341,193 +342,194 @@ void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
341 find = (*dict)[ attr.data() ]; 342 find = (*dict)[ attr.data() ];
342 if (!find ) { 343 if (!find ) {
343// qWarning("Unknown option" + it.key() ); 344// qWarning("Unknown option" + it.key() );
344 ev.setCustomField( attr, val ); 345 ev.setCustomField( attr, val );
345 return; 346 return;
346 } 347 }
347 348
348 switch( *find ) { 349 switch( *find ) {
349 case OTodo::Uid: 350 case OTodo::Uid:
350 ev.setUid( val.toInt() ); 351 ev.setUid( val.toInt() );
351 break; 352 break;
352 case OTodo::Category: 353 case OTodo::Category:
353 ev.setCategories( ev.idsFromString( val ) ); 354 ev.setCategories( ev.idsFromString( val ) );
354 break; 355 break;
355 case OTodo::HasDate: 356 case OTodo::HasDate:
356 ev.setHasDueDate( val.toInt() ); 357 ev.setHasDueDate( val.toInt() );
357 break; 358 break;
358 case OTodo::Completed: 359 case OTodo::Completed:
359 ev.setCompleted( val.toInt() ); 360 ev.setCompleted( val.toInt() );
360 break; 361 break;
361 case OTodo::Description: 362 case OTodo::Description:
362 ev.setDescription( val ); 363 ev.setDescription( val );
363 break; 364 break;
364 case OTodo::Summary: 365 case OTodo::Summary:
365 ev.setSummary( val ); 366 ev.setSummary( val );
366 break; 367 break;
367 case OTodo::Priority: 368 case OTodo::Priority:
368 ev.setPriority( val.toInt() ); 369 ev.setPriority( val.toInt() );
369 break; 370 break;
370 case OTodo::DateDay: 371 case OTodo::DateDay:
371 m_day = val.toInt(); 372 m_day = val.toInt();
372 break; 373 break;
373 case OTodo::DateMonth: 374 case OTodo::DateMonth:
374 m_month = val.toInt(); 375 m_month = val.toInt();
375 break; 376 break;
376 case OTodo::DateYear: 377 case OTodo::DateYear:
377 m_year = val.toInt(); 378 m_year = val.toInt();
378 break; 379 break;
379 case OTodo::Progress: 380 case OTodo::Progress:
380 ev.setProgress( val.toInt() ); 381 ev.setProgress( val.toInt() );
381 break; 382 break;
382 case OTodo::CrossReference: 383 case OTodo::CrossReference:
383 { 384 {
384 /* 385 /*
385 * A cross refernce looks like 386 * A cross refernce looks like
386 * appname,id;appname,id 387 * appname,id;appname,id
387 * we need to split it up 388 * we need to split it up
388 */ 389 */
389 QStringList refs = QStringList::split(';', val ); 390 QStringList refs = QStringList::split(';', val );
390 QStringList::Iterator strIt; 391 QStringList::Iterator strIt;
391 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 392 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
392 int pos = (*strIt).find(','); 393 int pos = (*strIt).find(',');
393 if ( pos > -1 ) 394 if ( pos > -1 )
394 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 395 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
395 396
396 } 397 }
397 break; 398 break;
398 } 399 }
399 default: 400 default:
400 break; 401 break;
401 } 402 }
402} 403}
403QString OTodoAccessXML::toString( const OTodo& ev )const { 404QString OTodoAccessXML::toString( const OTodo& ev )const {
404 QString str; 405 QString str;
405 406
406 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 407 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
407 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 408 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
408 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 409 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
409 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 410 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
410 411
411 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 412 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
412 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 413 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
413 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 414 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
414 415
415 if ( ev.hasDueDate() ) { 416 if ( ev.hasDueDate() ) {
416 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 417 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
417 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 418 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
418 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 419 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
419 } 420 }
420// qWarning( "Uid %d", ev.uid() ); 421// qWarning( "Uid %d", ev.uid() );
421 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 422 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
422 423
423// append the extra options 424// append the extra options
424 /* FIXME Qtopia::Record this is currently not 425 /* FIXME Qtopia::Record this is currently not
425 * possible you can set custom fields 426 * possible you can set custom fields
426 * but don' iterate over the list 427 * but don' iterate over the list
427 * I may do #define private protected 428 * I may do #define private protected
428 * for this case - cough --zecke 429 * for this case - cough --zecke
429 */ 430 */
430 /* 431 /*
431 QMap<QString, QString> extras = ev.extras(); 432 QMap<QString, QString> extras = ev.extras();
432 QMap<QString, QString>::Iterator extIt; 433 QMap<QString, QString>::Iterator extIt;
433 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 434 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
434 str += extIt.key() + "=\"" + extIt.data() + "\" "; 435 str += extIt.key() + "=\"" + extIt.data() + "\" ";
435 */ 436 */
436 // cross refernce 437 // cross refernce
437 438 if ( ev.hasRecurrence() )
439 str += ev.recurrence().toString();
438 440
439 return str; 441 return str;
440} 442}
441QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 443QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
442 return Qtopia::Record::idsToString( ints ); 444 return Qtopia::Record::idsToString( ints );
443} 445}
444 446
445/* internal class for sorting 447/* internal class for sorting
446 * 448 *
447 * Inspired by todoxmlio.cpp from TT 449 * Inspired by todoxmlio.cpp from TT
448 */ 450 */
449 451
450struct OTodoXMLContainer { 452struct OTodoXMLContainer {
451 OTodo todo; 453 OTodo todo;
452}; 454};
453 455
454namespace { 456namespace {
455 inline QString string( const OTodo& todo) { 457 inline QString string( const OTodo& todo) {
456 return todo.summary().isEmpty() ? 458 return todo.summary().isEmpty() ?
457 todo.description().left(20 ) : 459 todo.description().left(20 ) :
458 todo.summary(); 460 todo.summary();
459 } 461 }
460 inline int completed( const OTodo& todo1, const OTodo& todo2) { 462 inline int completed( const OTodo& todo1, const OTodo& todo2) {
461 int ret = 0; 463 int ret = 0;
462 if ( todo1.isCompleted() ) ret++; 464 if ( todo1.isCompleted() ) ret++;
463 if ( todo2.isCompleted() ) ret--; 465 if ( todo2.isCompleted() ) ret--;
464 return ret; 466 return ret;
465 } 467 }
466 inline int priority( const OTodo& t1, const OTodo& t2) { 468 inline int priority( const OTodo& t1, const OTodo& t2) {
467 return ( t1.priority() - t2.priority() ); 469 return ( t1.priority() - t2.priority() );
468 } 470 }
469 inline int description( const OTodo& t1, const OTodo& t2) { 471 inline int description( const OTodo& t1, const OTodo& t2) {
470 return QString::compare( string(t1), string(t2) ); 472 return QString::compare( string(t1), string(t2) );
471 } 473 }
472 inline int deadline( const OTodo& t1, const OTodo& t2) { 474 inline int deadline( const OTodo& t1, const OTodo& t2) {
473 int ret = 0; 475 int ret = 0;
474 if ( t1.hasDueDate() && 476 if ( t1.hasDueDate() &&
475 t2.hasDueDate() ) 477 t2.hasDueDate() )
476 ret = t2.dueDate().daysTo( t1.dueDate() ); 478 ret = t2.dueDate().daysTo( t1.dueDate() );
477 else if ( t1.hasDueDate() ) 479 else if ( t1.hasDueDate() )
478 ret = -1; 480 ret = -1;
479 else if ( t2.hasDueDate() ) 481 else if ( t2.hasDueDate() )
480 ret = 1; 482 ret = 1;
481 else 483 else
482 ret = 0; 484 ret = 0;
483 485
484 return ret; 486 return ret;
485 } 487 }
486 488
487}; 489};
488 490
489/* 491/*
490 * Returns: 492 * Returns:
491 * 0 if item1 == item2 493 * 0 if item1 == item2
492 * 494 *
493 * non-zero if item1 != item2 495 * non-zero if item1 != item2
494 * 496 *
495 * This function returns int rather than bool so that reimplementations 497 * This function returns int rather than bool so that reimplementations
496 * can return one of three values and use it to sort by: 498 * can return one of three values and use it to sort by:
497 * 499 *
498 * 0 if item1 == item2 500 * 0 if item1 == item2
499 * 501 *
500 * > 0 (positive integer) if item1 > item2 502 * > 0 (positive integer) if item1 > item2
501 * 503 *
502 * < 0 (negative integer) if item1 < item2 504 * < 0 (negative integer) if item1 < item2
503 * 505 *
504 */ 506 */
505class OTodoXMLVector : public QVector<OTodoXMLContainer> { 507class OTodoXMLVector : public QVector<OTodoXMLContainer> {
506public: 508public:
507 OTodoXMLVector(int size, bool asc, int sort) 509 OTodoXMLVector(int size, bool asc, int sort)
508 : QVector<OTodoXMLContainer>( size ) 510 : QVector<OTodoXMLContainer>( size )
509 { 511 {
510 setAutoDelete( true ); 512 setAutoDelete( true );
511 m_asc = asc; 513 m_asc = asc;
512 m_sort = sort; 514 m_sort = sort;
513 } 515 }
514 /* return the summary/description */ 516 /* return the summary/description */
515 QString string( const OTodo& todo) { 517 QString string( const OTodo& todo) {
516 return todo.summary().isEmpty() ? 518 return todo.summary().isEmpty() ?
517 todo.description().left(20 ) : 519 todo.description().left(20 ) :
518 todo.summary(); 520 todo.summary();
519 } 521 }
520 /** 522 /**
521 * we take the sortorder( switch on it ) 523 * we take the sortorder( switch on it )
522 * 524 *
523 */ 525 */
524 int compareItems( Item d1, Item d2 ) { 526 int compareItems( Item d1, Item d2 ) {
525 bool seComp, sePrio, seDesc, seDeadline; 527 bool seComp, sePrio, seDesc, seDeadline;
526 seComp = sePrio = seDeadline = seDesc = false; 528 seComp = sePrio = seDeadline = seDesc = false;
527 int ret =0; 529 int ret =0;
528 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 530 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
529 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 531 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
530 532
531 /* same item */ 533 /* same item */
532 if ( con1->todo.uid() == con2->todo.uid() ) 534 if ( con1->todo.uid() == con2->todo.uid() )
533 return 0; 535 return 0;