summaryrefslogtreecommitdiff
path: root/libopie2/opiepim/backend
Unidiff
Diffstat (limited to 'libopie2/opiepim/backend') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp11
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.h5
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp221
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.h60
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp12
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.cpp5
6 files changed, 309 insertions, 5 deletions
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
index 132c9fc..dd9dbde 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
@@ -1,112 +1,115 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ===================================================================== 12 * =====================================================================
13 * Version: $Id$ 13 * Version: $Id$
14 * ===================================================================== 14 * =====================================================================
15 * History: 15 * History:
16 * $Log$ 16 * $Log$
17 * Revision 1.3 2003/12/08 15:18:10 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
17 * Revision 1.2 2003/09/29 07:44:26 eilers 20 * Revision 1.2 2003/09/29 07:44:26 eilers
18 * Improvement of PIM-SQL Databases, but search queries are still limited. 21 * Improvement of PIM-SQL Databases, but search queries are still limited.
19 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space. 22 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
20 * Todo: Started to add new attributes. Some type conversions missing. 23 * Todo: Started to add new attributes. Some type conversions missing.
21 * 24 *
22 * Revision 1.1 2003/09/22 14:31:16 eilers 25 * Revision 1.1 2003/09/22 14:31:16 eilers
23 * Added first experimental incarnation of sql-backend for addressbook. 26 * Added first experimental incarnation of sql-backend for addressbook.
24 * Some modifications to be able to compile the todo sql-backend. 27 * Some modifications to be able to compile the todo sql-backend.
25 * A lot of changes fill follow... 28 * A lot of changes fill follow...
26 * 29 *
27 */ 30 */
28 31
29#include "ocontactaccessbackend_sql.h" 32#include "ocontactaccessbackend_sql.h"
30 33
31#include <qarray.h> 34#include <qarray.h>
32#include <qdatetime.h> 35#include <qdatetime.h>
33#include <qstringlist.h> 36#include <qstringlist.h>
34 37
35#include <qpe/global.h> 38#include <qpe/global.h>
36#include <qpe/recordfields.h> 39#include <qpe/recordfields.h>
37 40
38#include <opie/ocontactfields.h> 41#include <opie/ocontactfields.h>
39#include <opie/oconversion.h> 42#include <opie/oconversion.h>
40#include <opie2/osqldriver.h> 43#include <opie2/osqldriver.h>
41#include <opie2/osqlresult.h> 44#include <opie2/osqlresult.h>
42#include <opie2/osqlmanager.h> 45#include <opie2/osqlmanager.h>
43#include <opie2/osqlquery.h> 46#include <opie2/osqlquery.h>
44 47
45 48
46 49
47 50
48// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead 51// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
49// vertical like "uid, type, value". 52// vertical like "uid, type, value".
50// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !! 53// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
51#define __STORE_HORIZONTAL_ 54#define __STORE_HORIZONTAL_
52 55
53// Distinct loading is not very fast. If I expect that every person has just 56// Distinct loading is not very fast. If I expect that every person has just
54// one (and always one) 'Last Name', I can request all uid's for existing lastnames, 57// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
55// which is faster.. 58// which is faster..
56// But this may not be true for all entries, like company contacts.. 59// But this may not be true for all entries, like company contacts..
57// The current AddressBook application handles this problem, but other may not.. (eilers) 60// The current AddressBook application handles this problem, but other may not.. (eilers)
58#define __USE_SUPERFAST_LOADQUERY 61#define __USE_SUPERFAST_LOADQUERY
59 62
60 63
61/* 64/*
62 * Implementation of used query types 65 * Implementation of used query types
63 * CREATE query 66 * CREATE query
64 * LOAD query 67 * LOAD query
65 * INSERT 68 * INSERT
66 * REMOVE 69 * REMOVE
67 * CLEAR 70 * CLEAR
68 */ 71 */
69namespace { 72namespace {
70 /** 73 /**
71 * CreateQuery for the Todolist Table 74 * CreateQuery for the Todolist Table
72 */ 75 */
73 class CreateQuery : public OSQLQuery { 76 class CreateQuery : public OSQLQuery {
74 public: 77 public:
75 CreateQuery(); 78 CreateQuery();
76 ~CreateQuery(); 79 ~CreateQuery();
77 QString query()const; 80 QString query()const;
78 }; 81 };
79 82
80 /** 83 /**
81 * Clears (delete) a Table 84 * Clears (delete) a Table
82 */ 85 */
83 class ClearQuery : public OSQLQuery { 86 class ClearQuery : public OSQLQuery {
84 public: 87 public:
85 ClearQuery(); 88 ClearQuery();
86 ~ClearQuery(); 89 ~ClearQuery();
87 QString query()const; 90 QString query()const;
88 91
89 }; 92 };
90 93
91 94
92 /** 95 /**
93 * LoadQuery 96 * LoadQuery
94 * this one queries for all uids 97 * this one queries for all uids
95 */ 98 */
96 class LoadQuery : public OSQLQuery { 99 class LoadQuery : public OSQLQuery {
97 public: 100 public:
98 LoadQuery(); 101 LoadQuery();
99 ~LoadQuery(); 102 ~LoadQuery();
100 QString query()const; 103 QString query()const;
101 }; 104 };
102 105
103 /** 106 /**
104 * inserts/adds a OContact to the table 107 * inserts/adds a OContact to the table
105 */ 108 */
106 class InsertQuery : public OSQLQuery { 109 class InsertQuery : public OSQLQuery {
107 public: 110 public:
108 InsertQuery(const OContact& ); 111 InsertQuery(const OContact& );
109 ~InsertQuery(); 112 ~InsertQuery();
110 QString query()const; 113 QString query()const;
111 private: 114 private:
112 OContact m_contact; 115 OContact m_contact;
@@ -361,214 +364,220 @@ namespace {
361 + "," 364 + ","
362 + QString::number( id++ ) 365 + QString::number( id++ )
363 + ",'" 366 + ",'"
364 + it.key() //.latin1() 367 + it.key() //.latin1()
365 + "'," 368 + "',"
366 + "0" // Priority for future enhancements 369 + "0" // Priority for future enhancements
367 + ",'" 370 + ",'"
368 + it.data() //.latin1() 371 + it.data() //.latin1()
369 + "');"; 372 + "');";
370 } 373 }
371 // qu += "commit;"; 374 // qu += "commit;";
372 qWarning("add %s", qu.latin1() ); 375 qWarning("add %s", qu.latin1() );
373 return qu; 376 return qu;
374 } 377 }
375 378
376 379
377 RemoveQuery::RemoveQuery(int uid ) 380 RemoveQuery::RemoveQuery(int uid )
378 : OSQLQuery(), m_uid( uid ) {} 381 : OSQLQuery(), m_uid( uid ) {}
379 RemoveQuery::~RemoveQuery() {} 382 RemoveQuery::~RemoveQuery() {}
380 QString RemoveQuery::query()const { 383 QString RemoveQuery::query()const {
381 QString qu = "DELETE from addressbook where uid = " 384 QString qu = "DELETE from addressbook where uid = "
382 + QString::number(m_uid) + ";"; 385 + QString::number(m_uid) + ";";
383 qu += "DELETE from custom_data where uid = " 386 qu += "DELETE from custom_data where uid = "
384 + QString::number(m_uid) + ";"; 387 + QString::number(m_uid) + ";";
385 return qu; 388 return qu;
386 } 389 }
387 390
388 391
389 392
390 393
391 FindQuery::FindQuery(int uid) 394 FindQuery::FindQuery(int uid)
392 : OSQLQuery(), m_uid( uid ) { 395 : OSQLQuery(), m_uid( uid ) {
393 } 396 }
394 FindQuery::FindQuery(const QArray<int>& ints) 397 FindQuery::FindQuery(const QArray<int>& ints)
395 : OSQLQuery(), m_uids( ints ){ 398 : OSQLQuery(), m_uids( ints ){
396 } 399 }
397 FindQuery::~FindQuery() { 400 FindQuery::~FindQuery() {
398 } 401 }
399 QString FindQuery::query()const{ 402 QString FindQuery::query()const{
400 // if ( m_uids.count() == 0 ) 403 // if ( m_uids.count() == 0 )
401 return single(); 404 return single();
402 } 405 }
403 /* 406 /*
404 else 407 else
405 return multi(); 408 return multi();
406 } 409 }
407 QString FindQuery::multi()const { 410 QString FindQuery::multi()const {
408 QString qu = "select uid, type, value from addressbook where"; 411 QString qu = "select uid, type, value from addressbook where";
409 for (uint i = 0; i < m_uids.count(); i++ ) { 412 for (uint i = 0; i < m_uids.count(); i++ ) {
410 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 413 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
411 } 414 }
412 qu.remove( qu.length()-2, 2 ); // Hmmmm.. 415 qu.remove( qu.length()-2, 2 ); // Hmmmm..
413 return qu; 416 return qu;
414 } 417 }
415 */ 418 */
416#ifdef __STORE_HORIZONTAL_ 419#ifdef __STORE_HORIZONTAL_
417 QString FindQuery::single()const{ 420 QString FindQuery::single()const{
418 QString qu = "select *"; 421 QString qu = "select *";
419 qu += " from addressbook where uid = " + QString::number(m_uid); 422 qu += " from addressbook where uid = " + QString::number(m_uid);
420 423
421 // qWarning("find query: %s", qu.latin1() ); 424 // qWarning("find query: %s", qu.latin1() );
422 return qu; 425 return qu;
423 } 426 }
424#else 427#else
425 QString FindQuery::single()const{ 428 QString FindQuery::single()const{
426 QString qu = "select uid, type, value from addressbook where uid = "; 429 QString qu = "select uid, type, value from addressbook where uid = ";
427 qu += QString::number(m_uid); 430 qu += QString::number(m_uid);
428 return qu; 431 return qu;
429 } 432 }
430#endif 433#endif
431 434
432 435
433 FindCustomQuery::FindCustomQuery(int uid) 436 FindCustomQuery::FindCustomQuery(int uid)
434 : OSQLQuery(), m_uid( uid ) { 437 : OSQLQuery(), m_uid( uid ) {
435 } 438 }
436 FindCustomQuery::FindCustomQuery(const QArray<int>& ints) 439 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
437 : OSQLQuery(), m_uids( ints ){ 440 : OSQLQuery(), m_uids( ints ){
438 } 441 }
439 FindCustomQuery::~FindCustomQuery() { 442 FindCustomQuery::~FindCustomQuery() {
440 } 443 }
441 QString FindCustomQuery::query()const{ 444 QString FindCustomQuery::query()const{
442 // if ( m_uids.count() == 0 ) 445 // if ( m_uids.count() == 0 )
443 return single(); 446 return single();
444 } 447 }
445 QString FindCustomQuery::single()const{ 448 QString FindCustomQuery::single()const{
446 QString qu = "select uid, type, value from custom_data where uid = "; 449 QString qu = "select uid, type, value from custom_data where uid = ";
447 qu += QString::number(m_uid); 450 qu += QString::number(m_uid);
448 return qu; 451 return qu;
449 } 452 }
450 453
451}; 454};
452 455
453 456
454/* --------------------------------------------------------------------------- */ 457/* --------------------------------------------------------------------------- */
455 458
456OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */, 459OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
457 const QString& filename ): m_changed(false) 460 const QString& filename ):
461 OContactAccessBackend(), m_changed(false), m_driver( NULL )
458{ 462{
459 qWarning("C'tor OContactAccessBackend_SQL starts"); 463 qWarning("C'tor OContactAccessBackend_SQL starts");
460 QTime t; 464 QTime t;
461 t.start(); 465 t.start();
462 466
463 /* Expecting to access the default filename if nothing else is set */ 467 /* Expecting to access the default filename if nothing else is set */
464 if ( filename.isEmpty() ){ 468 if ( filename.isEmpty() ){
465 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" ); 469 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
466 } else 470 } else
467 m_fileName = filename; 471 m_fileName = filename;
468 472
469 // Get the standart sql-driver from the OSQLManager.. 473 // Get the standart sql-driver from the OSQLManager..
470 OSQLManager man; 474 OSQLManager man;
471 m_driver = man.standard(); 475 m_driver = man.standard();
472 m_driver->setUrl( m_fileName ); 476 m_driver->setUrl( m_fileName );
473 477
474 load(); 478 load();
475 479
476 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() ); 480 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
477} 481}
478 482
483OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
484{
485 if( m_driver )
486 delete m_driver;
487}
479 488
480bool OContactAccessBackend_SQL::load () 489bool OContactAccessBackend_SQL::load ()
481{ 490{
482 if (!m_driver->open() ) 491 if (!m_driver->open() )
483 return false; 492 return false;
484 493
485 // Don't expect that the database exists. 494 // Don't expect that the database exists.
486 // It is save here to create the table, even if it 495 // It is save here to create the table, even if it
487 // do exist. ( Is that correct for all databases ?? ) 496 // do exist. ( Is that correct for all databases ?? )
488 CreateQuery creat; 497 CreateQuery creat;
489 OSQLResult res = m_driver->query( &creat ); 498 OSQLResult res = m_driver->query( &creat );
490 499
491 update(); 500 update();
492 501
493 return true; 502 return true;
494 503
495} 504}
496 505
497bool OContactAccessBackend_SQL::reload() 506bool OContactAccessBackend_SQL::reload()
498{ 507{
499 return load(); 508 return load();
500} 509}
501 510
502bool OContactAccessBackend_SQL::save() 511bool OContactAccessBackend_SQL::save()
503{ 512{
504 return m_driver->close(); 513 return m_driver->close();
505} 514}
506 515
507 516
508void OContactAccessBackend_SQL::clear () 517void OContactAccessBackend_SQL::clear ()
509{ 518{
510 ClearQuery cle; 519 ClearQuery cle;
511 OSQLResult res = m_driver->query( &cle ); 520 OSQLResult res = m_driver->query( &cle );
512 CreateQuery qu; 521 CreateQuery qu;
513 res = m_driver->query(&qu); 522 res = m_driver->query(&qu);
514} 523}
515 524
516bool OContactAccessBackend_SQL::wasChangedExternally() 525bool OContactAccessBackend_SQL::wasChangedExternally()
517{ 526{
518 return false; 527 return false;
519} 528}
520 529
521QArray<int> OContactAccessBackend_SQL::allRecords() const 530QArray<int> OContactAccessBackend_SQL::allRecords() const
522{ 531{
523 532
524 // FIXME: Think about cute handling of changed tables.. 533 // FIXME: Think about cute handling of changed tables..
525 // Thus, we don't have to call update here... 534 // Thus, we don't have to call update here...
526 if ( m_changed ) 535 if ( m_changed )
527 ((OContactAccessBackend_SQL*)this)->update(); 536 ((OContactAccessBackend_SQL*)this)->update();
528 537
529 return m_uids; 538 return m_uids;
530} 539}
531 540
532bool OContactAccessBackend_SQL::add ( const OContact &newcontact ) 541bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
533{ 542{
534 InsertQuery ins( newcontact ); 543 InsertQuery ins( newcontact );
535 OSQLResult res = m_driver->query( &ins ); 544 OSQLResult res = m_driver->query( &ins );
536 545
537 if ( res.state() == OSQLResult::Failure ) 546 if ( res.state() == OSQLResult::Failure )
538 return false; 547 return false;
539 548
540 int c = m_uids.count(); 549 int c = m_uids.count();
541 m_uids.resize( c+1 ); 550 m_uids.resize( c+1 );
542 m_uids[c] = newcontact.uid(); 551 m_uids[c] = newcontact.uid();
543 552
544 return true; 553 return true;
545} 554}
546 555
547 556
548bool OContactAccessBackend_SQL::remove ( int uid ) 557bool OContactAccessBackend_SQL::remove ( int uid )
549{ 558{
550 RemoveQuery rem( uid ); 559 RemoveQuery rem( uid );
551 OSQLResult res = m_driver->query(&rem ); 560 OSQLResult res = m_driver->query(&rem );
552 561
553 if ( res.state() == OSQLResult::Failure ) 562 if ( res.state() == OSQLResult::Failure )
554 return false; 563 return false;
555 564
556 m_changed = true; 565 m_changed = true;
557 566
558 return true; 567 return true;
559} 568}
560 569
561bool OContactAccessBackend_SQL::replace ( const OContact &contact ) 570bool OContactAccessBackend_SQL::replace ( const OContact &contact )
562{ 571{
563 if ( !remove( contact.uid() ) ) 572 if ( !remove( contact.uid() ) )
564 return false; 573 return false;
565 574
566 return add( contact ); 575 return add( contact );
567} 576}
568 577
569 578
570OContact OContactAccessBackend_SQL::find ( int uid ) const 579OContact OContactAccessBackend_SQL::find ( int uid ) const
571{ 580{
572 qWarning("OContactAccessBackend_SQL::find()"); 581 qWarning("OContactAccessBackend_SQL::find()");
573 QTime t; 582 QTime t;
574 t.start(); 583 t.start();
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
index bb22551..b8f1d8d 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
@@ -1,96 +1,101 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * 12 *
13 * 13 *
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.2 2003/12/08 15:18:11 eilers
20 * Committing unfinished sql implementation before merging to libopie2 starts..
21 *
19 * Revision 1.1 2003/09/22 14:31:16 eilers 22 * Revision 1.1 2003/09/22 14:31:16 eilers
20 * Added first experimental incarnation of sql-backend for addressbook. 23 * Added first experimental incarnation of sql-backend for addressbook.
21 * Some modifications to be able to compile the todo sql-backend. 24 * Some modifications to be able to compile the todo sql-backend.
22 * A lot of changes fill follow... 25 * A lot of changes fill follow...
23 * 26 *
24 * 27 *
25 */ 28 */
26 29
27#ifndef _OContactAccessBackend_SQL_ 30#ifndef _OContactAccessBackend_SQL_
28#define _OContactAccessBackend_SQL_ 31#define _OContactAccessBackend_SQL_
29 32
30#include "ocontactaccessbackend.h" 33#include "ocontactaccessbackend.h"
31#include "ocontactaccess.h" 34#include "ocontactaccess.h"
32 35
33#include <qlist.h> 36#include <qlist.h>
34#include <qdict.h> 37#include <qdict.h>
35 38
36class OSQLDriver; 39class OSQLDriver;
37class OSQLResult; 40class OSQLResult;
38class OSQLResultItem; 41class OSQLResultItem;
39 42
40/* the default xml implementation */ 43/* the default xml implementation */
41/** 44/**
42 * This class is the SQL implementation of a Contact backend 45 * This class is the SQL implementation of a Contact backend
43 * it does implement everything available for OContact. 46 * it does implement everything available for OContact.
44 * @see OPimAccessBackend for more information of available methods 47 * @see OPimAccessBackend for more information of available methods
45 */ 48 */
46class OContactAccessBackend_SQL : public OContactAccessBackend { 49class OContactAccessBackend_SQL : public OContactAccessBackend {
47 public: 50 public:
48 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null ); 51 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
49 52
53 ~OContactAccessBackend_SQL ();
54
50 bool save(); 55 bool save();
51 56
52 bool load (); 57 bool load ();
53 58
54 void clear (); 59 void clear ();
55 60
56 bool wasChangedExternally(); 61 bool wasChangedExternally();
57 62
58 QArray<int> allRecords() const; 63 QArray<int> allRecords() const;
59 64
60 OContact find ( int uid ) const; 65 OContact find ( int uid ) const;
61 // FIXME: Add lookahead-cache support ! 66 // FIXME: Add lookahead-cache support !
62 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 67 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
63 68
64 QArray<int> queryByExample ( const OContact &query, int settings, 69 QArray<int> queryByExample ( const OContact &query, int settings,
65 const QDateTime& d ); 70 const QDateTime& d );
66 71
67 QArray<int> matchRegexp( const QRegExp &r ) const; 72 QArray<int> matchRegexp( const QRegExp &r ) const;
68 73
69 const uint querySettings(); 74 const uint querySettings();
70 75
71 bool hasQuerySettings (uint querySettings) const; 76 bool hasQuerySettings (uint querySettings) const;
72 77
73 // Currently only asc implemented.. 78 // Currently only asc implemented..
74 QArray<int> sorted( bool asc, int , int , int ); 79 QArray<int> sorted( bool asc, int , int , int );
75 bool add ( const OContact &newcontact ); 80 bool add ( const OContact &newcontact );
76 81
77 bool replace ( const OContact &contact ); 82 bool replace ( const OContact &contact );
78 83
79 bool remove ( int uid ); 84 bool remove ( int uid );
80 bool reload(); 85 bool reload();
81 86
82 private: 87 private:
83 QArray<int> extractUids( OSQLResult& res ) const; 88 QArray<int> extractUids( OSQLResult& res ) const;
84 QMap<int, QString> requestNonCustom( int uid ) const; 89 QMap<int, QString> requestNonCustom( int uid ) const;
85 QMap<QString, QString> requestCustom( int uid ) const; 90 QMap<QString, QString> requestCustom( int uid ) const;
86 void update(); 91 void update();
87 92
88 protected: 93 protected:
89 bool m_changed; 94 bool m_changed;
90 QString m_fileName; 95 QString m_fileName;
91 QArray<int> m_uids; 96 QArray<int> m_uids;
92 97
93 OSQLDriver* m_driver; 98 OSQLDriver* m_driver;
94}; 99};
95 100
96#endif 101#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
new file mode 100644
index 0000000..9769bf7
--- a/dev/null
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
@@ -0,0 +1,221 @@
1/*
2 * SQL Backend for the OPIE-Calender Database.
3 *
4 * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2003/12/08 15:18:12 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include <qarray.h>
27#include <qstringlist.h>
28
29#include "orecur.h"
30#include "odatebookaccessbackend_sql.h"
31
32#include <opie2/osqldriver.h>
33#include <opie2/osqlresult.h>
34#include <opie2/osqlmanager.h>
35#include <opie2/osqlquery.h>
36
37namespace {
38
39
40
41};
42
43ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
44 const QString& fileName )
45 : ODateBookAccessBackend(), m_driver( NULL )
46{
47 m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
48
49 // Get the standart sql-driver from the OSQLManager..
50 OSQLManager man;
51 m_driver = man.standard();
52 m_driver->setUrl( m_fileName );
53
54 initFields();
55
56 load();
57}
58
59ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
60}
61
62void ODateBookAccessBackend_SQL::initFields()
63{
64
65 // This map contains the translation of the fieldtype id's to
66 // the names of the table columns
67 m_fieldMap.insert( OEvent::FUid, "uid" );
68 m_fieldMap.insert( OEvent::FCategories, "Categories" );
69 m_fieldMap.insert( OEvent::FDescription, "Description" );
70 m_fieldMap.insert( OEvent::FLocation, "Location" );
71 m_fieldMap.insert( OEvent::FType, "Type" );
72 m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
73 m_fieldMap.insert( OEvent::FSound, "Sound" );
74 m_fieldMap.insert( OEvent::FRType, "RType" );
75 m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
76 m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
77 m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
78 m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
79 m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
80 m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
81 m_fieldMap.insert( OEvent::FRExeptions, "RExceptions" );
82 m_fieldMap.insert( OEvent::FStart, "Start" );
83 m_fieldMap.insert( OEvent::FEnd, "End" );
84 m_fieldMap.insert( OEvent::FNote, "Note" );
85 m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
86 m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
87 m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
88}
89
90bool ODateBookAccessBackend_SQL::load()
91{
92 if (!m_driver->open() )
93 return false;
94
95 // Don't expect that the database exists.
96 // It is save here to create the table, even if it
97 // do exist. ( Is that correct for all databases ?? )
98 QStringqu = "create table datebook( uid INTEGER PRIMARY KEY ";
99
100 QMap<int, QString>::Iterator it;
101 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
102 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( it.data() );
103 }
104 qu += " );";
105
106 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
107
108 OSQLRawQuery raw( qu );
109 OSQLResult res = m_driver->query( &raw );
110 if ( res.state() != OSQLResult::Success )
111 return false;
112
113 update();
114
115 return true;
116}
117
118void ODateBookAccessBackend_SQL::update()
119{
120
121 QString qu = "select uid from datebook";
122 OSQLRawQuery raw( qu );
123 OSQLResult res = m_driver->query( &raw );
124 if ( res.state() != OSQLResult::Success ){
125 m_uids.clear();
126 return;
127 }
128
129 m_uids = extractUids( res );
130
131}
132
133QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
134{
135 qWarning("extractUids");
136
137 OSQLResultItem::ValueList list = res.results();
138 OSQLResultItem::ValueList::Iterator it;
139 QArray<int> ints(list.count() );
140 qWarning(" count = %d", list.count() );
141
142 int i = 0;
143 for (it = list.begin(); it != list.end(); ++it ) {
144 ints[i] = (*it).data("uid").toInt();
145 i++;
146 }
147
148 return ints;
149
150}
151
152bool ODateBookAccessBackend_SQL::reload()
153{
154 return load();
155}
156
157bool ODateBookAccessBackend_SQL::save()
158{
159 return m_driver->close();
160}
161
162QArray<int> ODateBookAccessBackend_SQL::allRecords()const
163{
164 return m_uids;
165}
166
167QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
168 return QArray<int>();
169}
170
171void ODateBookAccessBackend_SQL::clear()
172{
173 QString qu = "drop table datebook;";
174 qu += "drop table custom_data;";
175
176 OSQLRawQuery raw( qu );
177 OSQLResult res = m_driver->query( &raw );
178
179}
180
181
182OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
183}
184
185bool ODateBookAccessBackend_SQL::add( const OEvent& ev ) {
186 return true;
187}
188bool ODateBookAccessBackend_SQL::remove( int uid ) {
189
190 return true;
191}
192bool ODateBookAccessBackend_SQL::replace( const OEvent& ev ) {
193 remove( ev.uid() );
194 return add( ev );
195}
196QArray<int> ODateBookAccessBackend_SQL::rawEvents()const {
197 return allRecords();
198}
199QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const {
200
201 return ints;
202}
203QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const {
204
205 return ints;
206}
207OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats() {
208
209 return list;
210}
211OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats() {
212
213 return list;
214}
215
216
217QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
218{
219
220 return m_currentQuery;
221}
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.h b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
new file mode 100644
index 0000000..85e0d4f
--- a/dev/null
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
@@ -0,0 +1,60 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
3
4#include <qmap.h>
5
6#include "odatebookaccessbackend.h"
7
8class OSQLDriver;
9
10/**
11 * This is the default SQL implementation for DateBoook SQL storage
12 * It fully implements the interface
13 * @see ODateBookAccessBackend
14 * @see OPimAccessBackend
15 */
16class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
17public:
18 ODateBookAccessBackend_SQL( const QString& appName,
19 const QString& fileName = QString::null);
20 ~ODateBookAccessBackend_SQL();
21
22 bool load();
23 bool reload();
24 bool save();
25
26 QArray<int> allRecords()const;
27 QArray<int> matchRegexp(const QRegExp &r) const;
28 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
29 OEvent find( int uid )const;
30 void clear();
31 bool add( const OEvent& ev );
32 bool remove( int uid );
33 bool replace( const OEvent& ev );
34
35 QArray<UID> rawEvents()const;
36 QArray<UID> rawRepeats()const;
37 QArray<UID> nonRepeats()const;
38
39 OEvent::ValueList directNonRepeats();
40 OEvent::ValueList directRawRepeats();
41
42private:
43 bool loadFile();
44 QString m_fileName;
45 QArray<int> m_uids;
46
47 QMap<int, QString> m_fieldMap;
48
49 OSQLDriver* m_driver;
50
51 class Private;
52 Private *d;
53
54 void initFields();
55 void update();
56 QArray<int> extractUids( OSQLResult& res ) const;
57
58};
59
60#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index 39c43c5..929d004 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -1,542 +1,548 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdlib.h> 5#include <stdlib.h>
6 6
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10 10
11#include <unistd.h> 11#include <unistd.h>
12 12
13#include <qasciidict.h> 13#include <qasciidict.h>
14#include <qfile.h> 14#include <qfile.h>
15 15
16#include <qtopia/global.h> 16#include <qtopia/global.h>
17#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h> 18#include <qtopia/timeconversion.h>
19 19
20#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
21#include "orecur.h" 21#include "orecur.h"
22#include "otimezone.h" 22#include "otimezone.h"
23#include "odatebookaccessbackend_xml.h" 23#include "odatebookaccessbackend_xml.h"
24 24
25namespace { 25namespace {
26 // FROM TT again 26 // FROM TT again
27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
28{ 28{
29 char needleChar; 29 char needleChar;
30 char haystackChar; 30 char haystackChar;
31 if (!needle || !haystack || !hLen || !nLen) 31 if (!needle || !haystack || !hLen || !nLen)
32 return 0; 32 return 0;
33 33
34 const char* hsearch = haystack; 34 const char* hsearch = haystack;
35 35
36 if ((needleChar = *needle++) != 0) { 36 if ((needleChar = *needle++) != 0) {
37 nLen--; //(to make up for needle++) 37 nLen--; //(to make up for needle++)
38 do { 38 do {
39 do { 39 do {
40 if ((haystackChar = *hsearch++) == 0) 40 if ((haystackChar = *hsearch++) == 0)
41 return (0); 41 return (0);
42 if (hsearch >= haystack + hLen) 42 if (hsearch >= haystack + hLen)
43 return (0); 43 return (0);
44 } while (haystackChar != needleChar); 44 } while (haystackChar != needleChar);
45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
46 hsearch--; 46 hsearch--;
47 } 47 }
48 return ((char *)hsearch); 48 return ((char *)hsearch);
49} 49}
50} 50}
51 51
52namespace { 52namespace {
53 time_t start, end, created, rp_end; 53 time_t start, end, created, rp_end;
54 ORecur* rec; 54 ORecur* rec;
55 ORecur* recur() { 55 ORecur* recur() {
56 if (!rec) 56 if (!rec)
57 rec = new ORecur; 57 rec = new ORecur;
58 58
59 return rec; 59 return rec;
60 } 60 }
61 int alarmTime; 61 int alarmTime;
62 int snd; 62 int snd;
63 enum Attribute{ 63 enum Attribute{
64 FDescription = 0, 64 FDescription = 0,
65 FLocation, 65 FLocation,
66 FCategories, 66 FCategories,
67 FUid, 67 FUid,
68 FType, 68 FType,
69 FAlarm, 69 FAlarm,
70 FSound, 70 FSound,
71 FRType, 71 FRType,
72 FRWeekdays, 72 FRWeekdays,
73 FRPosition, 73 FRPosition,
74 FRFreq, 74 FRFreq,
75 FRHasEndDate, 75 FRHasEndDate,
76 FREndDate, 76 FREndDate,
77 FRStart, 77 FRStart,
78 FREnd, 78 FREnd,
79 FNote, 79 FNote,
80 FCreated, 80 FCreated, // Should't this be called FRCreated ?
81 FTimeZone, 81 FTimeZone,
82 FRecParent, 82 FRecParent,
83 FRecChildren, 83 FRecChildren,
84 FExceptions 84 FExceptions
85 }; 85 };
86
87 // FIXME: Use OEvent::toMap() here !! (eilers)
86 inline void save( const OEvent& ev, QString& buf ) { 88 inline void save( const OEvent& ev, QString& buf ) {
87 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() ); 89 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
88 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; 90 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
89 if (!ev.location().isEmpty() ) 91 if (!ev.location().isEmpty() )
90 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; 92 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
91 93
92 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; 94 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
93 buf += " uid=\"" + QString::number( ev.uid() ) + "\""; 95 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
94 96
95 if (ev.isAllDay() ) 97 if (ev.isAllDay() )
96 buf += " type=\"AllDay\""; // is that all ?? (eilers) 98 buf += " type=\"AllDay\""; // is that all ?? (eilers)
97 99
98 if (ev.hasNotifiers() ) { 100 if (ev.hasNotifiers() ) {
99 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first 101 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
100 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; 102 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
101 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; 103 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
102 if ( alarm.sound() == OPimAlarm::Loud ) 104 if ( alarm.sound() == OPimAlarm::Loud )
103 buf += "loud"; 105 buf += "loud";
104 else 106 else
105 buf += "silent"; 107 buf += "silent";
106 buf += "\""; 108 buf += "\"";
107 } 109 }
108 if ( ev.hasRecurrence() ) { 110 if ( ev.hasRecurrence() ) {
109 buf += ev.recurrence().toString(); 111 buf += ev.recurrence().toString();
110 } 112 }
111 113
112 /* 114 /*
113 * fscking timezones :) well, we'll first convert 115 * fscking timezones :) well, we'll first convert
114 * the QDateTime to a QDateTime in UTC time 116 * the QDateTime to a QDateTime in UTC time
115 * and then we'll create a nice time_t 117 * and then we'll create a nice time_t
116 */ 118 */
117 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 119 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
118 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\""; 120 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
119 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\""; 121 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
120 if (!ev.note().isEmpty() ) { 122 if (!ev.note().isEmpty() ) {
121 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\""; 123 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
122 } 124 }
123 125
124 buf += " timezone=\""; 126 buf += " timezone=\"";
125 if ( ev.timeZone().isEmpty() ) 127 if ( ev.timeZone().isEmpty() )
126 buf += "None"; 128 buf += "None";
127 else 129 else
128 buf += ev.timeZone(); 130 buf += ev.timeZone();
129 buf += "\""; 131 buf += "\"";
130 132
131 if (ev.parent() != 0 ) { 133 if (ev.parent() != 0 ) {
132 buf += " recparent=\""+QString::number(ev.parent() )+"\""; 134 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
133 } 135 }
134 136
135 if (ev.children().count() != 0 ) { 137 if (ev.children().count() != 0 ) {
136 QArray<int> children = ev.children(); 138 QArray<int> children = ev.children();
137 buf += " recchildren=\""; 139 buf += " recchildren=\"";
138 for ( uint i = 0; i < children.count(); i++ ) { 140 for ( uint i = 0; i < children.count(); i++ ) {
139 if ( i != 0 ) buf += " "; 141 if ( i != 0 ) buf += " ";
140 buf += QString::number( children[i] ); 142 buf += QString::number( children[i] );
141 } 143 }
142 buf+= "\""; 144 buf+= "\"";
143 } 145 }
144 146
145 // skip custom writing 147 // skip custom writing
146 } 148 }
147 149
148 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) { 150 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
149 QMap<int, OEvent>::ConstIterator it; 151 QMap<int, OEvent>::ConstIterator it;
150 QString buf; 152 QString buf;
151 QCString str; 153 QCString str;
152 int total_written; 154 int total_written;
153 for ( it = list.begin(); it != list.end(); ++it ) { 155 for ( it = list.begin(); it != list.end(); ++it ) {
154 buf = "<event"; 156 buf = "<event";
155 save( it.data(), buf ); 157 save( it.data(), buf );
156 buf += " />\n"; 158 buf += " />\n";
157 str = buf.utf8(); 159 str = buf.utf8();
158 160
159 total_written = file.writeBlock(str.data(), str.length() ); 161 total_written = file.writeBlock(str.data(), str.length() );
160 if ( total_written != int(str.length() ) ) 162 if ( total_written != int(str.length() ) )
161 return false; 163 return false;
162 } 164 }
163 return true; 165 return true;
164 } 166 }
165} 167}
166 168
167ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 169ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
168 const QString& fileName ) 170 const QString& fileName )
169 : ODateBookAccessBackend() { 171 : ODateBookAccessBackend() {
170 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; 172 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
171 m_changed = false; 173 m_changed = false;
172} 174}
173ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { 175ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
174} 176}
175bool ODateBookAccessBackend_XML::load() { 177bool ODateBookAccessBackend_XML::load() {
176 return loadFile(); 178 return loadFile();
177} 179}
178bool ODateBookAccessBackend_XML::reload() { 180bool ODateBookAccessBackend_XML::reload() {
179 clear(); 181 clear();
180 return load(); 182 return load();
181} 183}
182bool ODateBookAccessBackend_XML::save() { 184bool ODateBookAccessBackend_XML::save() {
183 if (!m_changed) return true; 185 if (!m_changed) return true;
184 186
185 int total_written; 187 int total_written;
186 QString strFileNew = m_name + ".new"; 188 QString strFileNew = m_name + ".new";
187 189
188 QFile f( strFileNew ); 190 QFile f( strFileNew );
189 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false; 191 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
190 192
191 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); 193 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
192 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; 194 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
193 buf += "<events>\n"; 195 buf += "<events>\n";
194 QCString str = buf.utf8(); 196 QCString str = buf.utf8();
195 total_written = f.writeBlock( str.data(), str.length() ); 197 total_written = f.writeBlock( str.data(), str.length() );
196 if ( total_written != int(str.length() ) ) { 198 if ( total_written != int(str.length() ) ) {
197 f.close(); 199 f.close();
198 QFile::remove( strFileNew ); 200 QFile::remove( strFileNew );
199 return false; 201 return false;
200 } 202 }
201 203
202 if (!forAll( m_raw, f ) ) { 204 if (!forAll( m_raw, f ) ) {
203 f.close(); 205 f.close();
204 QFile::remove( strFileNew ); 206 QFile::remove( strFileNew );
205 return false; 207 return false;
206 } 208 }
207 if (!forAll( m_rep, f ) ) { 209 if (!forAll( m_rep, f ) ) {
208 f.close(); 210 f.close();
209 QFile::remove( strFileNew ); 211 QFile::remove( strFileNew );
210 return false; 212 return false;
211 } 213 }
212 214
213 buf = "</events>\n</DATEBOOK>\n"; 215 buf = "</events>\n</DATEBOOK>\n";
214 str = buf.utf8(); 216 str = buf.utf8();
215 total_written = f.writeBlock( str.data(), str.length() ); 217 total_written = f.writeBlock( str.data(), str.length() );
216 if ( total_written != int(str.length() ) ) { 218 if ( total_written != int(str.length() ) ) {
217 f.close(); 219 f.close();
218 QFile::remove( strFileNew ); 220 QFile::remove( strFileNew );
219 return false; 221 return false;
220 } 222 }
221 f.close(); 223 f.close();
222 224
223 if ( ::rename( strFileNew, m_name ) < 0 ) { 225 if ( ::rename( strFileNew, m_name ) < 0 ) {
224 QFile::remove( strFileNew ); 226 QFile::remove( strFileNew );
225 return false; 227 return false;
226 } 228 }
227 229
228 m_changed = false; 230 m_changed = false;
229 return true; 231 return true;
230} 232}
231QArray<int> ODateBookAccessBackend_XML::allRecords()const { 233QArray<int> ODateBookAccessBackend_XML::allRecords()const {
232 QArray<int> ints( m_raw.count()+ m_rep.count() ); 234 QArray<int> ints( m_raw.count()+ m_rep.count() );
233 uint i = 0; 235 uint i = 0;
234 QMap<int, OEvent>::ConstIterator it; 236 QMap<int, OEvent>::ConstIterator it;
235 237
236 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 238 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
237 ints[i] = it.key(); 239 ints[i] = it.key();
238 i++; 240 i++;
239 } 241 }
240 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 242 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
241 ints[i] = it.key(); 243 ints[i] = it.key();
242 i++; 244 i++;
243 } 245 }
244 246
245 return ints; 247 return ints;
246} 248}
247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) { 249QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
248 return QArray<int>(); 250 return QArray<int>();
249} 251}
250void ODateBookAccessBackend_XML::clear() { 252void ODateBookAccessBackend_XML::clear() {
251 m_changed = true; 253 m_changed = true;
252 m_raw.clear(); 254 m_raw.clear();
253 m_rep.clear(); 255 m_rep.clear();
254} 256}
255OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 257OEvent ODateBookAccessBackend_XML::find( int uid ) const{
256 if ( m_raw.contains( uid ) ) 258 if ( m_raw.contains( uid ) )
257 return m_raw[uid]; 259 return m_raw[uid];
258 else 260 else
259 return m_rep[uid]; 261 return m_rep[uid];
260} 262}
261bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 263bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
262 m_changed = true; 264 m_changed = true;
263 if (ev.hasRecurrence() ) 265 if (ev.hasRecurrence() )
264 m_rep.insert( ev.uid(), ev ); 266 m_rep.insert( ev.uid(), ev );
265 else 267 else
266 m_raw.insert( ev.uid(), ev ); 268 m_raw.insert( ev.uid(), ev );
267 269
268 return true; 270 return true;
269} 271}
270bool ODateBookAccessBackend_XML::remove( int uid ) { 272bool ODateBookAccessBackend_XML::remove( int uid ) {
271 m_changed = true; 273 m_changed = true;
272 m_rep.remove( uid ); 274 m_rep.remove( uid );
273 m_rep.remove( uid ); 275 m_rep.remove( uid );
274 276
275 return true; 277 return true;
276} 278}
277bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 279bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
278 replace( ev.uid() ); 280 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
279 return add( ev ); 281 return add( ev );
280} 282}
281QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 283QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
282 return allRecords(); 284 return allRecords();
283} 285}
284QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 286QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
285 QArray<int> ints( m_rep.count() ); 287 QArray<int> ints( m_rep.count() );
286 uint i = 0; 288 uint i = 0;
287 QMap<int, OEvent>::ConstIterator it; 289 QMap<int, OEvent>::ConstIterator it;
288 290
289 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 291 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
290 ints[i] = it.key(); 292 ints[i] = it.key();
291 i++; 293 i++;
292 } 294 }
293 295
294 return ints; 296 return ints;
295} 297}
296QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 298QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
297 QArray<int> ints( m_raw.count() ); 299 QArray<int> ints( m_raw.count() );
298 uint i = 0; 300 uint i = 0;
299 QMap<int, OEvent>::ConstIterator it; 301 QMap<int, OEvent>::ConstIterator it;
300 302
301 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 303 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
302 ints[i] = it.key(); 304 ints[i] = it.key();
303 i++; 305 i++;
304 } 306 }
305 307
306 return ints; 308 return ints;
307} 309}
308OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 310OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
309 OEvent::ValueList list; 311 OEvent::ValueList list;
310 QMap<int, OEvent>::ConstIterator it; 312 QMap<int, OEvent>::ConstIterator it;
311 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 313 for (it = m_raw.begin(); it != m_raw.end(); ++it )
312 list.append( it.data() ); 314 list.append( it.data() );
313 315
314 return list; 316 return list;
315} 317}
316OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 318OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
317 OEvent::ValueList list; 319 OEvent::ValueList list;
318 QMap<int, OEvent>::ConstIterator it; 320 QMap<int, OEvent>::ConstIterator it;
319 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 321 for (it = m_rep.begin(); it != m_rep.end(); ++it )
320 list.append( it.data() ); 322 list.append( it.data() );
321 323
322 return list; 324 return list;
323} 325}
326
327// FIXME: Use OEvent::fromMap() (eilers)
324bool ODateBookAccessBackend_XML::loadFile() { 328bool ODateBookAccessBackend_XML::loadFile() {
325 m_changed = false; 329 m_changed = false;
326 330
327 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 331 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
328 if ( fd < 0 ) return false; 332 if ( fd < 0 ) return false;
329 333
330 struct stat attribute; 334 struct stat attribute;
331 if ( ::fstat(fd, &attribute ) == -1 ) { 335 if ( ::fstat(fd, &attribute ) == -1 ) {
332 ::close( fd ); 336 ::close( fd );
333 return false; 337 return false;
334 } 338 }
335 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 339 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
336 if ( map_addr == ( (caddr_t)-1) ) { 340 if ( map_addr == ( (caddr_t)-1) ) {
337 ::close( fd ); 341 ::close( fd );
338 return false; 342 return false;
339 } 343 }
340 344
341 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 345 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
342 ::close( fd ); 346 ::close( fd );
343 347
344 QAsciiDict<int> dict(FExceptions+1); 348 QAsciiDict<int> dict(FExceptions+1);
345 dict.setAutoDelete( true ); 349 dict.setAutoDelete( true );
346 dict.insert( "description", new int(FDescription) ); 350 dict.insert( "description", new int(FDescription) );
347 dict.insert( "location", new int(FLocation) ); 351 dict.insert( "location", new int(FLocation) );
348 dict.insert( "categories", new int(FCategories) ); 352 dict.insert( "categories", new int(FCategories) );
349 dict.insert( "uid", new int(FUid) ); 353 dict.insert( "uid", new int(FUid) );
350 dict.insert( "type", new int(FType) ); 354 dict.insert( "type", new int(FType) );
351 dict.insert( "alarm", new int(FAlarm) ); 355 dict.insert( "alarm", new int(FAlarm) );
352 dict.insert( "sound", new int(FSound) ); 356 dict.insert( "sound", new int(FSound) );
353 dict.insert( "rtype", new int(FRType) ); 357 dict.insert( "rtype", new int(FRType) );
354 dict.insert( "rweekdays", new int(FRWeekdays) ); 358 dict.insert( "rweekdays", new int(FRWeekdays) );
355 dict.insert( "rposition", new int(FRPosition) ); 359 dict.insert( "rposition", new int(FRPosition) );
356 dict.insert( "rfreq", new int(FRFreq) ); 360 dict.insert( "rfreq", new int(FRFreq) );
357 dict.insert( "rhasenddate", new int(FRHasEndDate) ); 361 dict.insert( "rhasenddate", new int(FRHasEndDate) );
358 dict.insert( "enddt", new int(FREndDate) ); 362 dict.insert( "enddt", new int(FREndDate) );
359 dict.insert( "start", new int(FRStart) ); 363 dict.insert( "start", new int(FRStart) );
360 dict.insert( "end", new int(FREnd) ); 364 dict.insert( "end", new int(FREnd) );
361 dict.insert( "note", new int(FNote) ); 365 dict.insert( "note", new int(FNote) );
362 dict.insert( "created", new int(FCreated) ); 366 dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
363 dict.insert( "recparent", new int(FRecParent) ); 367 dict.insert( "recparent", new int(FRecParent) );
364 dict.insert( "recchildren", new int(FRecChildren) ); 368 dict.insert( "recchildren", new int(FRecChildren) );
365 dict.insert( "exceptions", new int(FExceptions) ); 369 dict.insert( "exceptions", new int(FExceptions) );
366 dict.insert( "timezone", new int(FTimeZone) ); 370 dict.insert( "timezone", new int(FTimeZone) );
367 371
368 char* dt = (char*)map_addr; 372 char* dt = (char*)map_addr;
369 int len = attribute.st_size; 373 int len = attribute.st_size;
370 int i = 0; 374 int i = 0;
371 char* point; 375 char* point;
372 const char* collectionString = "<event "; 376 const char* collectionString = "<event ";
373 int strLen = ::strlen(collectionString); 377 int strLen = ::strlen(collectionString);
374 int *find; 378 int *find;
375 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) { 379 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
376 i = point -dt; 380 i = point -dt;
377 i+= strLen; 381 i+= strLen;
378 382
379 alarmTime = -1; 383 alarmTime = -1;
380 snd = 0; // silent 384 snd = 0; // silent
381 385
382 OEvent ev; 386 OEvent ev;
383 rec = 0; 387 rec = 0;
384 388
385 while ( TRUE ) { 389 while ( TRUE ) {
386 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 390 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
387 ++i; 391 ++i;
388 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 392 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
389 break; 393 break;
390 394
391 395
392 // we have another attribute, read it. 396 // we have another attribute, read it.
393 int j = i; 397 int j = i;
394 while ( j < len && dt[j] != '=' ) 398 while ( j < len && dt[j] != '=' )
395 ++j; 399 ++j;
396 QCString attr( dt+i, j-i+1); 400 QCString attr( dt+i, j-i+1);
397 401
398 i = ++j; // skip = 402 i = ++j; // skip =
399 403
400 // find the start of quotes 404 // find the start of quotes
401 while ( i < len && dt[i] != '"' ) 405 while ( i < len && dt[i] != '"' )
402 ++i; 406 ++i;
403 j = ++i; 407 j = ++i;
404 408
405 bool haveUtf = FALSE; 409 bool haveUtf = FALSE;
406 bool haveEnt = FALSE; 410 bool haveEnt = FALSE;
407 while ( j < len && dt[j] != '"' ) { 411 while ( j < len && dt[j] != '"' ) {
408 if ( ((unsigned char)dt[j]) > 0x7f ) 412 if ( ((unsigned char)dt[j]) > 0x7f )
409 haveUtf = TRUE; 413 haveUtf = TRUE;
410 if ( dt[j] == '&' ) 414 if ( dt[j] == '&' )
411 haveEnt = TRUE; 415 haveEnt = TRUE;
412 ++j; 416 ++j;
413 } 417 }
414 if ( i == j ) { 418 if ( i == j ) {
415 // empty value 419 // empty value
416 i = j + 1; 420 i = j + 1;
417 continue; 421 continue;
418 } 422 }
419 423
420 QCString value( dt+i, j-i+1 ); 424 QCString value( dt+i, j-i+1 );
421 i = j + 1; 425 i = j + 1;
422 426
423 QString str = (haveUtf ? QString::fromUtf8( value ) 427 QString str = (haveUtf ? QString::fromUtf8( value )
424 : QString::fromLatin1( value ) ); 428 : QString::fromLatin1( value ) );
425 if ( haveEnt ) 429 if ( haveEnt )
426 str = Qtopia::plainString( str ); 430 str = Qtopia::plainString( str );
427 431
428 /* 432 /*
429 * add key + value 433 * add key + value
430 */ 434 */
431 find = dict[attr.data()]; 435 find = dict[attr.data()];
432 if (!find) 436 if (!find)
433 ev.setCustomField( attr, str ); 437 ev.setCustomField( attr, str );
434 else { 438 else {
435 setField( ev, *find, str ); 439 setField( ev, *find, str );
436 } 440 }
437 } 441 }
438 /* time to finalize */ 442 /* time to finalize */
439 finalizeRecord( ev ); 443 finalizeRecord( ev );
440 delete rec; 444 delete rec;
441 } 445 }
442 ::munmap(map_addr, attribute.st_size ); 446 ::munmap(map_addr, attribute.st_size );
443 m_changed = false; // changed during add 447 m_changed = false; // changed during add
444 448
445 return true; 449 return true;
446} 450}
451
452// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
447void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { 453void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
448 /* AllDay is alway in UTC */ 454 /* AllDay is alway in UTC */
449 if ( ev.isAllDay() ) { 455 if ( ev.isAllDay() ) {
450 OTimeZone utc = OTimeZone::utc(); 456 OTimeZone utc = OTimeZone::utc();
451 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 457 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
452 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 458 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
453 ev.setTimeZone( "UTC"); // make sure it is really utc 459 ev.setTimeZone( "UTC"); // make sure it is really utc
454 }else { 460 }else {
455 /* to current date time */ 461 /* to current date time */
456 // qWarning(" Start is %d", start ); 462 // qWarning(" Start is %d", start );
457 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 463 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
458 QDateTime date = zone.toDateTime( start ); 464 QDateTime date = zone.toDateTime( start );
459 qWarning(" Start is %s", date.toString().latin1() ); 465 qWarning(" Start is %s", date.toString().latin1() );
460 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); 466 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
461 467
462 date = zone.toDateTime( end ); 468 date = zone.toDateTime( end );
463 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); 469 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
464 } 470 }
465 if ( rec && rec->doesRecur() ) { 471 if ( rec && rec->doesRecur() ) {
466 OTimeZone utc = OTimeZone::utc(); 472 OTimeZone utc = OTimeZone::utc();
467 ORecur recu( *rec ); // call copy c'tor; 473 ORecur recu( *rec ); // call copy c'tor;
468 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); 474 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
469 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); 475 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
470 recu.setStart( ev.startDateTime().date() ); 476 recu.setStart( ev.startDateTime().date() );
471 ev.setRecurrence( recu ); 477 ev.setRecurrence( recu );
472 } 478 }
473 479
474 if (alarmTime != -1 ) { 480 if (alarmTime != -1 ) {
475 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 481 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
476 OPimAlarm al( snd , dt ); 482 OPimAlarm al( snd , dt );
477 ev.notifiers().add( al ); 483 ev.notifiers().add( al );
478 } 484 }
479 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 485 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
480 qWarning("already contains assign uid"); 486 qWarning("already contains assign uid");
481 ev.setUid( 1 ); 487 ev.setUid( 1 );
482 } 488 }
483 qWarning("addind %d %s", ev.uid(), ev.description().latin1() ); 489 qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
484 if ( ev.hasRecurrence() ) 490 if ( ev.hasRecurrence() )
485 m_rep.insert( ev.uid(), ev ); 491 m_rep.insert( ev.uid(), ev );
486 else 492 else
487 m_raw.insert( ev.uid(), ev ); 493 m_raw.insert( ev.uid(), ev );
488 494
489} 495}
490void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { 496void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
491// qWarning(" setting %s", value.latin1() ); 497// qWarning(" setting %s", value.latin1() );
492 switch( id ) { 498 switch( id ) {
493 case FDescription: 499 case FDescription:
494 e.setDescription( value ); 500 e.setDescription( value );
495 break; 501 break;
496 case FLocation: 502 case FLocation:
497 e.setLocation( value ); 503 e.setLocation( value );
498 break; 504 break;
499 case FCategories: 505 case FCategories:
500 e.setCategories( e.idsFromString( value ) ); 506 e.setCategories( e.idsFromString( value ) );
501 break; 507 break;
502 case FUid: 508 case FUid:
503 e.setUid( value.toInt() ); 509 e.setUid( value.toInt() );
504 break; 510 break;
505 case FType: 511 case FType:
506 if ( value == "AllDay" ) { 512 if ( value == "AllDay" ) {
507 e.setAllDay( true ); 513 e.setAllDay( true );
508 e.setTimeZone( "UTC" ); 514 e.setTimeZone( "UTC" );
509 } 515 }
510 break; 516 break;
511 case FAlarm: 517 case FAlarm:
512 alarmTime = value.toInt(); 518 alarmTime = value.toInt();
513 break; 519 break;
514 case FSound: 520 case FSound:
515 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 521 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
516 break; 522 break;
517 // recurrence stuff 523 // recurrence stuff
518 case FRType: 524 case FRType:
519 if ( value == "Daily" ) 525 if ( value == "Daily" )
520 recur()->setType( ORecur::Daily ); 526 recur()->setType( ORecur::Daily );
521 else if ( value == "Weekly" ) 527 else if ( value == "Weekly" )
522 recur()->setType( ORecur::Weekly); 528 recur()->setType( ORecur::Weekly);
523 else if ( value == "MonthlyDay" ) 529 else if ( value == "MonthlyDay" )
524 recur()->setType( ORecur::MonthlyDay ); 530 recur()->setType( ORecur::MonthlyDay );
525 else if ( value == "MonthlyDate" ) 531 else if ( value == "MonthlyDate" )
526 recur()->setType( ORecur::MonthlyDate ); 532 recur()->setType( ORecur::MonthlyDate );
527 else if ( value == "Yearly" ) 533 else if ( value == "Yearly" )
528 recur()->setType( ORecur::Yearly ); 534 recur()->setType( ORecur::Yearly );
529 else 535 else
530 recur()->setType( ORecur::NoRepeat ); 536 recur()->setType( ORecur::NoRepeat );
531 break; 537 break;
532 case FRWeekdays: 538 case FRWeekdays:
533 recur()->setDays( value.toInt() ); 539 recur()->setDays( value.toInt() );
534 break; 540 break;
535 case FRPosition: 541 case FRPosition:
536 recur()->setPosition( value.toInt() ); 542 recur()->setPosition( value.toInt() );
537 break; 543 break;
538 case FRFreq: 544 case FRFreq:
539 recur()->setFrequency( value.toInt() ); 545 recur()->setFrequency( value.toInt() );
540 break; 546 break;
541 case FRHasEndDate: 547 case FRHasEndDate:
542 recur()->setHasEndDate( value.toInt() ); 548 recur()->setHasEndDate( value.toInt() );
diff --git a/libopie2/opiepim/backend/otodoaccesssql.cpp b/libopie2/opiepim/backend/otodoaccesssql.cpp
index 3913661..75a0860 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.cpp
+++ b/libopie2/opiepim/backend/otodoaccesssql.cpp
@@ -206,205 +206,208 @@ namespace {
206 else{ 206 else{
207 qu += QString( "''" ) + "," 207 qu += QString( "''" ) + ","
208 + "''" + ","; 208 + "''" + ",";
209 } 209 }
210 210
211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !) 211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
212 + "'" + QString::number(sYear) + "-" 212 + "'" + QString::number(sYear) + "-"
213 + QString::number(sMonth) 213 + QString::number(sMonth)
214 + "-" + QString::number(sDay) + "'" + "," 214 + "-" + QString::number(sDay) + "'" + ","
215 + "'" + QString::number(eYear) + "-" 215 + "'" + QString::number(eYear) + "-"
216 + QString::number(eMonth) 216 + QString::number(eMonth)
217 + "-"+QString::number(eDay) + "'" 217 + "-"+QString::number(eDay) + "'"
218 + ")"; 218 + ")";
219 219
220 qWarning("add %s", qu.latin1() ); 220 qWarning("add %s", qu.latin1() );
221 return qu; 221 return qu;
222 } 222 }
223 223
224 RemoveQuery::RemoveQuery(int uid ) 224 RemoveQuery::RemoveQuery(int uid )
225 : OSQLQuery(), m_uid( uid ) {} 225 : OSQLQuery(), m_uid( uid ) {}
226 RemoveQuery::~RemoveQuery() {} 226 RemoveQuery::~RemoveQuery() {}
227 QString RemoveQuery::query()const { 227 QString RemoveQuery::query()const {
228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid); 228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
229 return qu; 229 return qu;
230 } 230 }
231 231
232 232
233 ClearQuery::ClearQuery() 233 ClearQuery::ClearQuery()
234 : OSQLQuery() {} 234 : OSQLQuery() {}
235 ClearQuery::~ClearQuery() {} 235 ClearQuery::~ClearQuery() {}
236 QString ClearQuery::query()const { 236 QString ClearQuery::query()const {
237 QString qu = "drop table todolist"; 237 QString qu = "drop table todolist";
238 return qu; 238 return qu;
239 } 239 }
240 FindQuery::FindQuery(int uid) 240 FindQuery::FindQuery(int uid)
241 : OSQLQuery(), m_uid(uid ) { 241 : OSQLQuery(), m_uid(uid ) {
242 } 242 }
243 FindQuery::FindQuery(const QArray<int>& ints) 243 FindQuery::FindQuery(const QArray<int>& ints)
244 : OSQLQuery(), m_uids(ints){ 244 : OSQLQuery(), m_uids(ints){
245 } 245 }
246 FindQuery::~FindQuery() { 246 FindQuery::~FindQuery() {
247 } 247 }
248 QString FindQuery::query()const{ 248 QString FindQuery::query()const{
249 if (m_uids.count() == 0 ) 249 if (m_uids.count() == 0 )
250 return single(); 250 return single();
251 else 251 else
252 return multi(); 252 return multi();
253 } 253 }
254 QString FindQuery::single()const{ 254 QString FindQuery::single()const{
255 QString qu = "select * from todolist where uid = " + QString::number(m_uid); 255 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
256 return qu; 256 return qu;
257 } 257 }
258 QString FindQuery::multi()const { 258 QString FindQuery::multi()const {
259 QString qu = "select * from todolist where "; 259 QString qu = "select * from todolist where ";
260 for (uint i = 0; i < m_uids.count(); i++ ) { 260 for (uint i = 0; i < m_uids.count(); i++ ) {
261 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 261 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
262 } 262 }
263 qu.remove( qu.length()-2, 2 ); 263 qu.remove( qu.length()-2, 2 );
264 return qu; 264 return qu;
265 } 265 }
266 266
267 OverDueQuery::OverDueQuery(): OSQLQuery() {} 267 OverDueQuery::OverDueQuery(): OSQLQuery() {}
268 OverDueQuery::~OverDueQuery() {} 268 OverDueQuery::~OverDueQuery() {}
269 QString OverDueQuery::query()const { 269 QString OverDueQuery::query()const {
270 QDate date = QDate::currentDate(); 270 QDate date = QDate::currentDate();
271 QString str; 271 QString str;
272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() ); 272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
273 273
274 return str; 274 return str;
275 } 275 }
276 276
277 277
278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc ) 278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {} 279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
280 EffQuery::~EffQuery() {} 280 EffQuery::~EffQuery() {}
281 QString EffQuery::query()const { 281 QString EffQuery::query()const {
282 return m_inc ? with() : out(); 282 return m_inc ? with() : out();
283 } 283 }
284 QString EffQuery::with()const { 284 QString EffQuery::with()const {
285 QString str; 285 QString str;
286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ") 286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() ) 287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() ); 288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
289 return str; 289 return str;
290 } 290 }
291 QString EffQuery::out()const { 291 QString EffQuery::out()const {
292 QString str; 292 QString str;
293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") 293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) 294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); 295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
296 296
297 return str; 297 return str;
298 } 298 }
299}; 299};
300 300
301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) 301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
302 : OTodoAccessBackend(), m_dict(15), m_dirty(true) 302 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
303{ 303{
304 QString fi = file; 304 QString fi = file;
305 if ( fi.isEmpty() ) 305 if ( fi.isEmpty() )
306 fi = Global::applicationFileName( "todolist", "todolist.db" ); 306 fi = Global::applicationFileName( "todolist", "todolist.db" );
307 OSQLManager man; 307 OSQLManager man;
308 m_driver = man.standard(); 308 m_driver = man.standard();
309 m_driver->setUrl(fi); 309 m_driver->setUrl(fi);
310 // fillDict(); 310 // fillDict();
311} 311}
312 312
313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ 313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
314 if( m_driver )
315 delete m_driver;
314} 316}
317
315bool OTodoAccessBackendSQL::load(){ 318bool OTodoAccessBackendSQL::load(){
316 if (!m_driver->open() ) 319 if (!m_driver->open() )
317 return false; 320 return false;
318 321
319 CreateQuery creat; 322 CreateQuery creat;
320 OSQLResult res = m_driver->query(&creat ); 323 OSQLResult res = m_driver->query(&creat );
321 324
322 m_dirty = true; 325 m_dirty = true;
323 return true; 326 return true;
324} 327}
325bool OTodoAccessBackendSQL::reload(){ 328bool OTodoAccessBackendSQL::reload(){
326 return load(); 329 return load();
327} 330}
328 331
329bool OTodoAccessBackendSQL::save(){ 332bool OTodoAccessBackendSQL::save(){
330 return m_driver->close(); 333 return m_driver->close();
331} 334}
332QArray<int> OTodoAccessBackendSQL::allRecords()const { 335QArray<int> OTodoAccessBackendSQL::allRecords()const {
333 if (m_dirty ) 336 if (m_dirty )
334 update(); 337 update();
335 338
336 return m_uids; 339 return m_uids;
337} 340}
338QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){ 341QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
339 QArray<int> ints(0); 342 QArray<int> ints(0);
340 return ints; 343 return ints;
341} 344}
342OTodo OTodoAccessBackendSQL::find(int uid ) const{ 345OTodo OTodoAccessBackendSQL::find(int uid ) const{
343 FindQuery query( uid ); 346 FindQuery query( uid );
344 return todo( m_driver->query(&query) ); 347 return todo( m_driver->query(&query) );
345 348
346} 349}
347OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 350OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
348 uint cur, Frontend::CacheDirection dir ) const{ 351 uint cur, Frontend::CacheDirection dir ) const{
349 uint CACHE = readAhead(); 352 uint CACHE = readAhead();
350 qWarning("searching for %d", uid ); 353 qWarning("searching for %d", uid );
351 QArray<int> search( CACHE ); 354 QArray<int> search( CACHE );
352 uint size =0; 355 uint size =0;
353 OTodo to; 356 OTodo to;
354 357
355 // we try to cache CACHE items 358 // we try to cache CACHE items
356 switch( dir ) { 359 switch( dir ) {
357 /* forward */ 360 /* forward */
358 case 0: // FIXME: Not a good style to use magic numbers here (eilers) 361 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
359 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 362 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
360 qWarning("size %d %d", size, ints[i] ); 363 qWarning("size %d %d", size, ints[i] );
361 search[size] = ints[i]; 364 search[size] = ints[i];
362 size++; 365 size++;
363 } 366 }
364 break; 367 break;
365 /* reverse */ 368 /* reverse */
366 case 1: // FIXME: Not a good style to use magic numbers here (eilers) 369 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
367 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 370 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
368 search[size] = ints[i]; 371 search[size] = ints[i];
369 size++; 372 size++;
370 } 373 }
371 break; 374 break;
372 } 375 }
373 search.resize( size ); 376 search.resize( size );
374 FindQuery query( search ); 377 FindQuery query( search );
375 OSQLResult res = m_driver->query( &query ); 378 OSQLResult res = m_driver->query( &query );
376 if ( res.state() != OSQLResult::Success ) 379 if ( res.state() != OSQLResult::Success )
377 return to; 380 return to;
378 381
379 return todo( res ); 382 return todo( res );
380} 383}
381void OTodoAccessBackendSQL::clear() { 384void OTodoAccessBackendSQL::clear() {
382 ClearQuery cle; 385 ClearQuery cle;
383 OSQLResult res = m_driver->query( &cle ); 386 OSQLResult res = m_driver->query( &cle );
384 CreateQuery qu; 387 CreateQuery qu;
385 res = m_driver->query(&qu); 388 res = m_driver->query(&qu);
386} 389}
387bool OTodoAccessBackendSQL::add( const OTodo& t) { 390bool OTodoAccessBackendSQL::add( const OTodo& t) {
388 InsertQuery ins( t ); 391 InsertQuery ins( t );
389 OSQLResult res = m_driver->query( &ins ); 392 OSQLResult res = m_driver->query( &ins );
390 393
391 if ( res.state() == OSQLResult::Failure ) 394 if ( res.state() == OSQLResult::Failure )
392 return false; 395 return false;
393 int c = m_uids.count(); 396 int c = m_uids.count();
394 m_uids.resize( c+1 ); 397 m_uids.resize( c+1 );
395 m_uids[c] = t.uid(); 398 m_uids[c] = t.uid();
396 399
397 return true; 400 return true;
398} 401}
399bool OTodoAccessBackendSQL::remove( int uid ) { 402bool OTodoAccessBackendSQL::remove( int uid ) {
400 RemoveQuery rem( uid ); 403 RemoveQuery rem( uid );
401 OSQLResult res = m_driver->query(&rem ); 404 OSQLResult res = m_driver->query(&rem );
402 405
403 if ( res.state() == OSQLResult::Failure ) 406 if ( res.state() == OSQLResult::Failure )
404 return false; 407 return false;
405 408
406 m_dirty = true; 409 m_dirty = true;
407 return true; 410 return true;
408} 411}
409/* 412/*
410 * FIXME better set query 413 * FIXME better set query