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