00001
00002 #include <qdatetime.h>
00003
00004 #include <qpe/global.h>
00005
00006 #include <opie2/osqldriver.h>
00007 #include <opie2/osqlresult.h>
00008 #include <opie2/osqlmanager.h>
00009 #include <opie2/osqlquery.h>
00010
00011 #include "otodoaccesssql.h"
00012 #include "opimstate.h"
00013 #include "opimnotifymanager.h"
00014 #include "orecur.h"
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 namespace {
00028 class CreateQuery : public OSQLQuery {
00029 public:
00030 CreateQuery();
00031 ~CreateQuery();
00032 QString query()const;
00033 };
00034
00039 class LoadQuery : public OSQLQuery {
00040 public:
00041 LoadQuery();
00042 ~LoadQuery();
00043 QString query()const;
00044 };
00045
00049 class InsertQuery : public OSQLQuery {
00050 public:
00051 InsertQuery(const OTodo& );
00052 ~InsertQuery();
00053 QString query()const;
00054 private:
00055 OTodo m_todo;
00056 };
00057
00061 class RemoveQuery : public OSQLQuery {
00062 public:
00063 RemoveQuery(int uid );
00064 ~RemoveQuery();
00065 QString query()const;
00066 private:
00067 int m_uid;
00068 };
00069
00073 class ClearQuery : public OSQLQuery {
00074 public:
00075 ClearQuery();
00076 ~ClearQuery();
00077 QString query()const;
00078
00079 };
00080
00084 class FindQuery : public OSQLQuery {
00085 public:
00086 FindQuery(int uid);
00087 FindQuery(const QArray<int>& );
00088 ~FindQuery();
00089 QString query()const;
00090 private:
00091 QString single()const;
00092 QString multi()const;
00093 QArray<int> m_uids;
00094 int m_uid;
00095 };
00096
00100 class OverDueQuery : public OSQLQuery {
00101 public:
00102 OverDueQuery();
00103 ~OverDueQuery();
00104 QString query()const;
00105 };
00106 class EffQuery : public OSQLQuery {
00107 public:
00108 EffQuery( const QDate&, const QDate&, bool inc );
00109 ~EffQuery();
00110 QString query()const;
00111 private:
00112 QString with()const;
00113 QString out()const;
00114 QDate m_start;
00115 QDate m_end;
00116 bool m_inc :1;
00117 };
00118
00119
00120 CreateQuery::CreateQuery() : OSQLQuery() {}
00121 CreateQuery::~CreateQuery() {}
00122 QString CreateQuery::query()const {
00123 QString qu;
00124 qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
00125 qu += "description, summary, priority, DueDate, progress , state, ";
00126
00127 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
00128 qu += "reminders, alarms, maintainer, startdate, completeddate);";
00129 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
00130 return qu;
00131 }
00132
00133 LoadQuery::LoadQuery() : OSQLQuery() {}
00134 LoadQuery::~LoadQuery() {}
00135 QString LoadQuery::query()const {
00136 QString qu;
00137
00138
00139 qu += "select uid from todolist";
00140
00141 return qu;
00142 }
00143
00144 InsertQuery::InsertQuery( const OTodo& todo )
00145 : OSQLQuery(), m_todo( todo ) {
00146 }
00147 InsertQuery::~InsertQuery() {
00148 }
00149
00150
00151
00152
00153 QString InsertQuery::query()const{
00154
00155 int year, month, day;
00156 year = month = day = 0;
00157 if (m_todo.hasDueDate() ) {
00158 QDate date = m_todo.dueDate();
00159 year = date.year();
00160 month = date.month();
00161 day = date.day();
00162 }
00163 int sYear = 0, sMonth = 0, sDay = 0;
00164 if( m_todo.hasStartDate() ){
00165 QDate sDate = m_todo.startDate();
00166 sYear = sDate.year();
00167 sMonth= sDate.month();
00168 sDay = sDate.day();
00169 }
00170
00171 int eYear = 0, eMonth = 0, eDay = 0;
00172 if( m_todo.hasCompletedDate() ){
00173 QDate eDate = m_todo.completedDate();
00174 eYear = eDate.year();
00175 eMonth= eDate.month();
00176 eDay = eDate.day();
00177 }
00178 QString qu;
00179 QMap<int, QString> recMap = m_todo.recurrence().toMap();
00180 qu = "insert into todolist VALUES("
00181 + QString::number( m_todo.uid() ) + ","
00182 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
00183 + QString::number( m_todo.isCompleted() ) + ","
00184 + "'" + m_todo.description() + "'" + ","
00185 + "'" + m_todo.summary() + "'" + ","
00186 + QString::number(m_todo.priority() ) + ","
00187 + "'" + QString::number(year) + "-"
00188 + QString::number(month)
00189 + "-" + QString::number( day ) + "'" + ","
00190 + QString::number( m_todo.progress() ) + ","
00191 + QString::number( m_todo.state().state() ) + ","
00192 + "'" + recMap[ ORecur::RType ] + "'" + ","
00193 + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
00194 + "'" + recMap[ ORecur::RPosition ] + "'" + ","
00195 + "'" + recMap[ ORecur::RFreq ] + "'" + ","
00196 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
00197 + "'" + recMap[ ORecur::EndDate ] + "'" + ","
00198 + "'" + recMap[ ORecur::Created ] + "'" + ","
00199 + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
00200
00201 if ( m_todo.hasNotifiers() ) {
00202 OPimNotifyManager manager = m_todo.notifiers();
00203 qu += "'" + manager.remindersToString() + "'" + ","
00204 + "'" + manager.alarmsToString() + "'" + ",";
00205 }
00206 else{
00207 qu += QString( "''" ) + ","
00208 + "''" + ",";
00209 }
00210
00211 qu += QString( "''" ) + QString( "," )
00212 + "'" + QString::number(sYear) + "-"
00213 + QString::number(sMonth)
00214 + "-" + QString::number(sDay) + "'" + ","
00215 + "'" + QString::number(eYear) + "-"
00216 + QString::number(eMonth)
00217 + "-"+QString::number(eDay) + "'"
00218 + ")";
00219
00220 qWarning("add %s", qu.latin1() );
00221 return qu;
00222 }
00223
00224 RemoveQuery::RemoveQuery(int uid )
00225 : OSQLQuery(), m_uid( uid ) {}
00226 RemoveQuery::~RemoveQuery() {}
00227 QString RemoveQuery::query()const {
00228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
00229 return qu;
00230 }
00231
00232
00233 ClearQuery::ClearQuery()
00234 : OSQLQuery() {}
00235 ClearQuery::~ClearQuery() {}
00236 QString ClearQuery::query()const {
00237 QString qu = "drop table todolist";
00238 return qu;
00239 }
00240 FindQuery::FindQuery(int uid)
00241 : OSQLQuery(), m_uid(uid ) {
00242 }
00243 FindQuery::FindQuery(const QArray<int>& ints)
00244 : OSQLQuery(), m_uids(ints){
00245 }
00246 FindQuery::~FindQuery() {
00247 }
00248 QString FindQuery::query()const{
00249 if (m_uids.count() == 0 )
00250 return single();
00251 else
00252 return multi();
00253 }
00254 QString FindQuery::single()const{
00255 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
00256 return qu;
00257 }
00258 QString FindQuery::multi()const {
00259 QString qu = "select * from todolist where ";
00260 for (uint i = 0; i < m_uids.count(); i++ ) {
00261 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
00262 }
00263 qu.remove( qu.length()-2, 2 );
00264 return qu;
00265 }
00266
00267 OverDueQuery::OverDueQuery(): OSQLQuery() {}
00268 OverDueQuery::~OverDueQuery() {}
00269 QString OverDueQuery::query()const {
00270 QDate date = QDate::currentDate();
00271 QString str;
00272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
00273
00274 return str;
00275 }
00276
00277
00278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
00279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
00280 EffQuery::~EffQuery() {}
00281 QString EffQuery::query()const {
00282 return m_inc ? with() : out();
00283 }
00284 QString EffQuery::with()const {
00285 QString str;
00286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
00287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
00288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
00289 return str;
00290 }
00291 QString EffQuery::out()const {
00292 QString str;
00293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
00294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
00295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
00296
00297 return str;
00298 }
00299 };
00300
00301 OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
00302 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
00303 {
00304 QString fi = file;
00305 if ( fi.isEmpty() )
00306 fi = Global::applicationFileName( "todolist", "todolist.db" );
00307 OSQLManager man;
00308 m_driver = man.standard();
00309 m_driver->setUrl(fi);
00310
00311 }
00312
00313 OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
00314 if( m_driver )
00315 delete m_driver;
00316 }
00317
00318 bool OTodoAccessBackendSQL::load(){
00319 if (!m_driver->open() )
00320 return false;
00321
00322 CreateQuery creat;
00323 OSQLResult res = m_driver->query(&creat );
00324
00325 m_dirty = true;
00326 return true;
00327 }
00328 bool OTodoAccessBackendSQL::reload(){
00329 return load();
00330 }
00331
00332 bool OTodoAccessBackendSQL::save(){
00333 return m_driver->close();
00334 }
00335 QArray<int> OTodoAccessBackendSQL::allRecords()const {
00336 if (m_dirty )
00337 update();
00338
00339 return m_uids;
00340 }
00341 QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
00342 QArray<int> ints(0);
00343 return ints;
00344 }
00345 OTodo OTodoAccessBackendSQL::find(int uid ) const{
00346 FindQuery query( uid );
00347 return todo( m_driver->query(&query) );
00348
00349 }
00350 OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
00351 uint cur, Frontend::CacheDirection dir ) const{
00352 uint CACHE = readAhead();
00353 qWarning("searching for %d", uid );
00354 QArray<int> search( CACHE );
00355 uint size =0;
00356 OTodo to;
00357
00358
00359 switch( dir ) {
00360
00361 case 0:
00362 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
00363 qWarning("size %d %d", size, ints[i] );
00364 search[size] = ints[i];
00365 size++;
00366 }
00367 break;
00368
00369 case 1:
00370 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
00371 search[size] = ints[i];
00372 size++;
00373 }
00374 break;
00375 }
00376 search.resize( size );
00377 FindQuery query( search );
00378 OSQLResult res = m_driver->query( &query );
00379 if ( res.state() != OSQLResult::Success )
00380 return to;
00381
00382 return todo( res );
00383 }
00384 void OTodoAccessBackendSQL::clear() {
00385 ClearQuery cle;
00386 OSQLResult res = m_driver->query( &cle );
00387 CreateQuery qu;
00388 res = m_driver->query(&qu);
00389 }
00390 bool OTodoAccessBackendSQL::add( const OTodo& t) {
00391 InsertQuery ins( t );
00392 OSQLResult res = m_driver->query( &ins );
00393
00394 if ( res.state() == OSQLResult::Failure )
00395 return false;
00396 int c = m_uids.count();
00397 m_uids.resize( c+1 );
00398 m_uids[c] = t.uid();
00399
00400 return true;
00401 }
00402 bool OTodoAccessBackendSQL::remove( int uid ) {
00403 RemoveQuery rem( uid );
00404 OSQLResult res = m_driver->query(&rem );
00405
00406 if ( res.state() == OSQLResult::Failure )
00407 return false;
00408
00409 m_dirty = true;
00410 return true;
00411 }
00412
00413
00414
00415
00416
00417 bool OTodoAccessBackendSQL::replace( const OTodo& t) {
00418 remove( t.uid() );
00419 bool b= add(t);
00420 m_dirty = false;
00421 return b;
00422 }
00423 QArray<int> OTodoAccessBackendSQL::overDue() {
00424 OverDueQuery qu;
00425 return uids( m_driver->query(&qu ) );
00426 }
00427 QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
00428 const QDate& t,
00429 bool u) {
00430 EffQuery ef(s, t, u );
00431 return uids (m_driver->query(&ef) );
00432 }
00433
00434
00435
00436 QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
00437 int sortFilter, int cat ) {
00438 qWarning("sorted %d, %d", asc, sortOrder );
00439 QString query;
00440 query = "select uid from todolist WHERE ";
00441
00442
00443
00444
00445
00446
00447
00448
00449 if ( sortFilter & 1 ) {
00450 QString str;
00451 if (cat != 0 ) str = QString::number( cat );
00452 query += " categories like '%" +str+"%' AND";
00453 }
00454
00455 if ( sortFilter & 2 ) {
00456 QDate date = QDate::currentDate();
00457 QString due;
00458 QString base;
00459 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
00460 query += " " + base + " AND";
00461 }
00462
00463 if ( sortFilter & 4 ) {
00464 query += " completed = 0 AND";
00465 }else{
00466 query += " ( completed = 1 OR completed = 0) AND";
00467 }
00468
00469 query = query.remove( query.length()-3, 3 );
00470
00471
00472
00473
00474
00475
00476 query += "ORDER BY ";
00477 switch( sortOrder ) {
00478
00479 case 0:
00480 query += "completed";
00481 break;
00482 case 1:
00483 query += "priority";
00484 break;
00485 case 2:
00486 query += "summary";
00487 break;
00488 case 3:
00489 query += "DueDate";
00490 break;
00491 }
00492
00493 if ( !asc ) {
00494 qWarning("not ascending!");
00495 query += " DESC";
00496 }
00497
00498 qWarning( query );
00499 OSQLRawQuery raw(query );
00500 return uids( m_driver->query(&raw) );
00501 }
00502 bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
00503 if ( str == "0-0-0" )
00504 return false;
00505 else{
00506 int day, year, month;
00507 QStringList list = QStringList::split("-", str );
00508 year = list[0].toInt();
00509 month = list[1].toInt();
00510 day = list[2].toInt();
00511 da.setYMD( year, month, day );
00512 return true;
00513 }
00514 }
00515 OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
00516 if ( res.state() == OSQLResult::Failure ) {
00517 OTodo to;
00518 return to;
00519 }
00520
00521 OSQLResultItem::ValueList list = res.results();
00522 OSQLResultItem::ValueList::Iterator it = list.begin();
00523 qWarning("todo1");
00524 OTodo to = todo( (*it) );
00525 cache( to );
00526 ++it;
00527
00528 for ( ; it != list.end(); ++it ) {
00529 qWarning("caching");
00530 cache( todo( (*it) ) );
00531 }
00532 return to;
00533 }
00534 OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
00535 qWarning("todo");
00536 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
00537 hasDueDate = date( dueDate, item.data("DueDate") );
00538 QStringList cats = QStringList::split(";", item.data("categories") );
00539
00540 qWarning("Item is completed: %d", item.data("completed").toInt() );
00541
00542 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
00543 cats, item.data("summary"), item.data("description"),
00544 item.data("progress").toUShort(), hasDueDate, dueDate,
00545 item.data("uid").toInt() );
00546
00547 bool isOk;
00548 int prioInt = QString( item.data("priority") ).toInt( &isOk );
00549 if ( isOk )
00550 to.setPriority( prioInt );
00551
00552 bool hasStartDate = false; QDate startDate = QDate::currentDate();
00553 hasStartDate = date( startDate, item.data("startdate") );
00554 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
00555 hasCompletedDate = date( completedDate, item.data("completeddate") );
00556
00557 if ( hasStartDate )
00558 to.setStartDate( startDate );
00559 if ( hasCompletedDate )
00560 to.setCompletedDate( completedDate );
00561
00562 OPimNotifyManager& manager = to.notifiers();
00563 manager.alarmsFromString( item.data("alarms") );
00564 manager.remindersFromString( item.data("reminders") );
00565
00566 OPimState pimState;
00567 pimState.setState( QString( item.data("state") ).toInt() );
00568 to.setState( pimState );
00569
00570 QMap<int, QString> recMap;
00571 recMap.insert( ORecur::RType , item.data("RType") );
00572 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
00573 recMap.insert( ORecur::RPosition , item.data("RPosition") );
00574 recMap.insert( ORecur::RFreq , item.data("RFreq") );
00575 recMap.insert( ORecur::RHasEndDate, item.data("RHasEndDate") );
00576 recMap.insert( ORecur::EndDate , item.data("EndDate") );
00577 recMap.insert( ORecur::Created , item.data("Created") );
00578 recMap.insert( ORecur::Exceptions , item.data("Exceptions") );
00579
00580 ORecur recur;
00581 recur.fromMap( recMap );
00582 to.setRecurrence( recur );
00583
00584 return to;
00585 }
00586 OTodo OTodoAccessBackendSQL::todo( int uid )const {
00587 FindQuery find( uid );
00588 return todo( m_driver->query(&find) );
00589 }
00590
00591
00592
00593 void OTodoAccessBackendSQL::fillDict() {
00594
00595
00596
00597
00598
00599 m_dict.setAutoDelete( TRUE );
00600 m_dict.insert("Categories" , new int(OTodo::Category) );
00601 m_dict.insert("Uid" , new int(OTodo::Uid) );
00602 m_dict.insert("HasDate" , new int(OTodo::HasDate) );
00603 m_dict.insert("Completed" , new int(OTodo::Completed) );
00604 m_dict.insert("Description" , new int(OTodo::Description) );
00605 m_dict.insert("Summary" , new int(OTodo::Summary) );
00606 m_dict.insert("Priority" , new int(OTodo::Priority) );
00607 m_dict.insert("DateDay" , new int(OTodo::DateDay) );
00608 m_dict.insert("DateMonth" , new int(OTodo::DateMonth) );
00609 m_dict.insert("DateYear" , new int(OTodo::DateYear) );
00610 m_dict.insert("Progress" , new int(OTodo::Progress) );
00611 m_dict.insert("Completed", new int(OTodo::Completed) );
00612 m_dict.insert("CrossReference", new int(OTodo::CrossReference) );
00613
00614
00615 }
00616
00617
00618
00619
00620 void OTodoAccessBackendSQL::update()const {
00621 ((OTodoAccessBackendSQL*)this)->m_dirty = false;
00622 LoadQuery lo;
00623 OSQLResult res = m_driver->query(&lo);
00624 if ( res.state() != OSQLResult::Success )
00625 return;
00626
00627 ((OTodoAccessBackendSQL*)this)->m_uids = uids( res );
00628 }
00629 QArray<int> OTodoAccessBackendSQL::uids( const OSQLResult& res) const{
00630
00631 OSQLResultItem::ValueList list = res.results();
00632 OSQLResultItem::ValueList::Iterator it;
00633 QArray<int> ints(list.count() );
00634 qWarning(" count = %d", list.count() );
00635
00636 int i = 0;
00637 for (it = list.begin(); it != list.end(); ++it ) {
00638 ints[i] = (*it).data("uid").toInt();
00639 i++;
00640 }
00641 return ints;
00642 }
00643
00644 QArray<int> OTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
00645 {
00646
00647 #warning OTodoAccessBackendSQL::matchRegexp() not implemented !!
00648
00649 #if 0
00650
00651 Copied from xml-backend by not adapted to sql (eilers)
00652
00653 QArray<int> m_currentQuery( m_events.count() );
00654 uint arraycounter = 0;
00655
00656
00657
00658 QMap<int, OTodo>::ConstIterator it;
00659 for (it = m_events.begin(); it != m_events.end(); ++it ) {
00660 if ( it.data().match( r ) )
00661 m_currentQuery[arraycounter++] = it.data().uid();
00662
00663 }
00664
00665 m_currentQuery.resize(arraycounter);
00666
00667 return m_currentQuery;
00668 #endif
00669 QArray<int> empty;
00670 return empty;
00671 }
00672 QBitArray OTodoAccessBackendSQL::supports()const {
00673
00674 return sup();
00675 }
00676
00677 QBitArray OTodoAccessBackendSQL::sup() const{
00678
00679 QBitArray ar( OTodo::CompletedDate + 1 );
00680 ar.fill( true );
00681 ar[OTodo::CrossReference] = false;
00682 ar[OTodo::State ] = false;
00683 ar[OTodo::Reminders] = false;
00684 ar[OTodo::Notifiers] = false;
00685 ar[OTodo::Maintainer] = false;
00686
00687 return ar;
00688 }
00689
00690 void OTodoAccessBackendSQL::removeAllCompleted(){
00691 #warning OTodoAccessBackendSQL::removeAllCompleted() not implemented !!
00692
00693 }