summaryrefslogtreecommitdiff
authoreilers <eilers>2004-12-20 14:14:07 (UTC)
committer eilers <eilers>2004-12-20 14:14:07 (UTC)
commit18e47153532d016d878f47e0ce11cb1a9716218e (patch) (side-by-side diff)
tree52eb6c25258fda0b2f295a29809c4603f5e17b0b
parent876e48baa20213d8265041cfac3034fe92cb0590 (diff)
downloadopie-18e47153532d016d878f47e0ce11cb1a9716218e.zip
opie-18e47153532d016d878f47e0ce11cb1a9716218e.tar.gz
opie-18e47153532d016d878f47e0ce11cb1a9716218e.tar.bz2
Recovery of the following Changes:
* Implement fast and full featured version of sorted() for addressbook * Implement generic queryByExample for all Addressboook backends. It allows incremental search. * Update of API Documentation
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/ChangeLog4
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend.cpp205
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend.h9
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp144
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.h23
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp14
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.h4
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp205
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h9
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h40
-rw-r--r--libopie2/opiepim/core/ocontactaccess.h37
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h53
-rw-r--r--libopie2/opiepim/core/opimtemplatebase.h57
-rw-r--r--libopie2/opiepim/opiepim.pro2
14 files changed, 493 insertions, 313 deletions
diff --git a/libopie2/opiepim/ChangeLog b/libopie2/opiepim/ChangeLog
index 9c85e4b..dd57259 100644
--- a/libopie2/opiepim/ChangeLog
+++ b/libopie2/opiepim/ChangeLog
@@ -1,14 +1,18 @@
+2004-11-23 Stefan Eilers <stefan@eilers-online.net>
+ * Implement fast and full featured version of sorted() for addressbook
+ * Implement generic queryByExample for all Addressboook backends. It allows incremental search.
+ * Update of API Documentation
2004-11-18 Holger Freyther <freyther@handhelds.org>
* Every Access can give a set of Occurrences for a period or a datetime
* QueryByExample, Find, Sort can be generically accessed by OPimBase
pointer interface
* OPimBackendOccurrence gets split up to OPimOccurrences by
OPimTemplateBase
* Add safeCast to various OPimRecords
* Kill memleak in OPimTodo
* Add SortVector implementations for OPimTodo and OPimContact
2004-??-?? The Opie Team <opie@handhelds.org>
* Implemented some important modifications to allow to use OPimRecords as it is, without
have to cast them. This makes it possible to write applications which handling pim
data in a generic manner (see opimconvertion tool) (eilers) \ No newline at end of file
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.cpp b/libopie2/opiepim/backend/ocontactaccessbackend.cpp
index 6ef60eb..b4fdd46 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend.cpp
@@ -1,121 +1,314 @@
/*
This file is part of the Opie Project
Copyright (C) 2004 Holger Freyther <freyther@handhelds.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "ocontactaccessbackend.h"
#include <opie2/private/opimcontactsortvector.h>
#include <opie2/ocontactaccess.h>
#include <opie2/odebug.h>
+#include <qdatetime.h>
+
namespace Opie {
OPimContactAccessBackend::OPimContactAccessBackend() {}
-UIDArray
-OPimContactAccessBackend::queryByExample( const OPimContact&, int,
- const QDateTime& )const {
- return UIDArray();
+UIDArray OPimContactAccessBackend::queryByExample( const UIDArray& uid_array, const OPimContact& query, int settings,
+ const QDateTime& d )const {
+ odebug << "Using Unaccelerated OPimContactAccessBackend implementation of queryByExample!" << oendl;
+
+ UIDArray m_currentQuery( uid_array.count() );
+ uint arraycounter = 0;
+
+ for( uint it = 0; it < uid_array.count(); ++it ){
+ /* Search all fields and compare them with query object. Store them into list
+ * if all fields matches.
+ */
+ QDate* queryDate = 0l;
+ QDate* checkDate = 0l;
+ bool allcorrect = true;
+ for ( int i = 0; i < Qtopia::Groups; i++ ) {
+ // Birthday and anniversary are special nonstring fields and should
+ // be handled specially
+ switch ( i ){
+ case Qtopia::Birthday:
+ queryDate = new QDate( query.birthday() );
+ checkDate = new QDate( find( uid_array[it] ).birthday() );
+ // fall through
+ case Qtopia::Anniversary:
+ if ( queryDate == 0l ){
+ queryDate = new QDate( query.anniversary() );
+ checkDate = new QDate( find( uid_array[it] ).anniversary() );
+ }
+
+ if ( queryDate->isValid() ){
+ if( checkDate->isValid() ){
+ if ( settings & OPimContactAccess::DateYear ){
+ if ( queryDate->year() != checkDate->year() )
+ allcorrect = false;
+ }
+ if ( settings & OPimContactAccess::DateMonth ){
+ if ( queryDate->month() != checkDate->month() )
+ allcorrect = false;
+ }
+ if ( settings & OPimContactAccess::DateDay ){
+ if ( queryDate->day() != checkDate->day() )
+ allcorrect = false;
+ }
+ if ( settings & OPimContactAccess::DateDiff ) {
+ QDate current;
+ // If we get an additional date, we
+ // will take this date instead of
+ // the current one..
+ if ( !d.date().isValid() )
+ current = QDate::currentDate();
+ else
+ current = d.date();
+
+ // We have to equalize the year, otherwise
+ // the search will fail..
+ checkDate->setYMD( current.year(),
+ checkDate->month(),
+ checkDate->day() );
+ if ( *checkDate < current )
+ checkDate->setYMD( current.year()+1,
+ checkDate->month(),
+ checkDate->day() );
+
+ // Check whether the birthday/anniversary date is between
+ // the current/given date and the maximum date
+ // ( maximum time range ) !
+ if ( current.daysTo( *queryDate ) >= 0 ){
+ if ( !( ( *checkDate >= current ) &&
+ ( *checkDate <= *queryDate ) ) ){
+ allcorrect = false;
+ }
+ }
+ }
+ } else{
+ // checkDate is invalid. Therefore this entry is always rejected
+ allcorrect = false;
+ }
+ }
+
+ delete queryDate;
+ queryDate = 0l;
+ delete checkDate;
+ checkDate = 0l;
+ break;
+ default:
+ /* Just compare fields which are not empty in the query object */
+ if ( !query.field(i).isEmpty() ){
+ switch ( settings & ~( OPimContactAccess::IgnoreCase
+ | OPimContactAccess::DateDiff
+ | OPimContactAccess::DateYear
+ | OPimContactAccess::DateMonth
+ | OPimContactAccess::DateDay
+ | OPimContactAccess::MatchOne
+ ) ){
+
+ case OPimContactAccess::RegExp:{
+ QRegExp expr ( query.field(i),
+ !(settings & OPimContactAccess::IgnoreCase),
+ false );
+ if ( expr.find ( find( uid_array[it] ).field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OPimContactAccess::WildCards:{
+ QRegExp expr ( query.field(i),
+ !(settings & OPimContactAccess::IgnoreCase),
+ true );
+ if ( expr.find ( find( uid_array[it] ).field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OPimContactAccess::ExactMatch:{
+ if (settings & OPimContactAccess::IgnoreCase){
+ if ( query.field(i).upper() !=
+ find( uid_array[it] ).field(i).upper() )
+ allcorrect = false;
+ }else{
+ if ( query.field(i) != find( uid_array[it] ).field(i) )
+ allcorrect = false;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if ( allcorrect ){
+ m_currentQuery[arraycounter++] = uid_array[it];
+ }
+ }
+
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+
}
-UIDArray
-OPimContactAccessBackend::sorted( const UIDArray& ar, bool asc, int sortOrder,
+const uint OPimContactAccessBackend::querySettings() const
+{
+ return ( OPimContactAccess::WildCards
+ | OPimContactAccess::IgnoreCase
+ | OPimContactAccess::RegExp
+ | OPimContactAccess::ExactMatch
+ | OPimContactAccess::DateDiff
+ | OPimContactAccess::DateYear
+ | OPimContactAccess::DateMonth
+ | OPimContactAccess::DateDay
+ );
+}
+
+bool OPimContactAccessBackend::hasQuerySettings (uint querySettings) const
+{
+ /* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
+ * may be added with any of the other settings. IgnoreCase should never used alone.
+ * Wildcards, RegExp, ExactMatch should never used at the same time...
+ */
+
+ // Step 1: Check whether the given settings are supported by this backend
+ if ( ( querySettings & (
+ OPimContactAccess::IgnoreCase
+ | OPimContactAccess::WildCards
+ | OPimContactAccess::DateDiff
+ | OPimContactAccess::DateYear
+ | OPimContactAccess::DateMonth
+ | OPimContactAccess::DateDay
+ | OPimContactAccess::RegExp
+ | OPimContactAccess::ExactMatch
+ ) ) != querySettings )
+ return false;
+
+ // Step 2: Check whether the given combinations are ok..
+
+ // IngoreCase alone is invalid
+ if ( querySettings == OPimContactAccess::IgnoreCase )
+ return false;
+
+ // WildCards, RegExp and ExactMatch should never used at the same time
+ switch ( querySettings & ~( OPimContactAccess::IgnoreCase
+ | OPimContactAccess::DateDiff
+ | OPimContactAccess::DateYear
+ | OPimContactAccess::DateMonth
+ | OPimContactAccess::DateDay
+ )
+ ){
+ case OPimContactAccess::RegExp:
+ return ( true );
+ case OPimContactAccess::WildCards:
+ return ( true );
+ case OPimContactAccess::ExactMatch:
+ return ( true );
+ case 0: // one of the upper removed bits were set..
+ return ( true );
+ default:
+ return ( false );
+ }
+}
+
+
+UIDArray OPimContactAccessBackend::sorted( const UIDArray& ar, bool asc, int sortOrder,
int filter, const QArray<int>& categories)const {
odebug << "Using Unaccelerated OPimContactAccessBackend sorted Implementation" << oendl;
Internal::OPimContactSortVector vector(ar.count(), asc, sortOrder );
int item = 0;
uint cat_count = categories.count();
uint eve_count = ar.count();
bool bCat = filter & OPimContactAccess::FilterCategory ? true : false;
bool catPassed = false;
int cat;
for ( uint i = 0; i < eve_count; ++i ) {
OPimContact contact = find( ar[i], ar, i, Frontend::Forward );
if ( contact.isEmpty() )
continue;
/* show category */
/* -1 == unfiled */
catPassed = false;
for ( uint cat_nu = 0; cat_nu < cat_count; ++cat_nu ) {
cat = categories[cat_nu];
if ( bCat && cat == -1 ) {
if(!contact.categories().isEmpty() )
continue;
} else if ( bCat && cat != 0)
if (!contact.categories().contains( cat ) )
continue;
catPassed = true;
break;
}
/*
* If none of the Categories matched
* continue
*/
if ( !catPassed )
continue;
vector.insert(item++, contact );
}
vector.resize( item );
/* sort it now */
vector.sort();
/* now get the uids */
UIDArray array( vector.count() );
for (uint i= 0; i < vector.count(); i++ )
array[i] = vector.uidAt( i );
return array;
}
OPimBackendOccurrence::List OPimContactAccessBackend::occurrences( const QDate& start,
const QDate& end)const {
OPimBackendOccurrence::List lst;
UIDArray records = allRecords();
const uint count = records.count();
int uid;
for ( uint i = 0; i < count; ++i ) {
uid = records[i];
OPimContact contact = find(uid, records, i, Frontend::Forward );
QDate date = contact.anniversary();
date = QDate( start.year(), date.month(),date.day() );
// if ( date.isValid() && date.) {
// }
}
return lst;
}
}
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.h b/libopie2/opiepim/backend/ocontactaccessbackend.h
index efb04c7..ee6dbc2 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend.h
@@ -1,108 +1,111 @@
/*
This file is part of the Opie Project
Copyright (C) The Main Author <main-author@whereever.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/**
* The class responsible for managing a backend.
* The implementation of this abstract class contains
* the complete database handling.
*
* Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
* Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
*
*/
#ifndef _OCONTACTACCESSBACKEND_H_
#define _OCONTACTACCESSBACKEND_H_
#include <opie2/opimcontact.h>
#include <opie2/opimaccessbackend.h>
#include <qregexp.h>
namespace Opie {
/**
* This class represents the interface of all Contact Backends.
* Derivates of this class will be used to access the contacts.
* As implementation currently XML and vCard exist. This class needs to be implemented
* if you want to provide your own storage.
* In all queries a list of uids is passed on instead of loading the actual record!
*
* @see OPimContactAccessBackend_VCard
* @see OPimContactAccessBackend_XML
*/
class OPimContactAccessBackend: public OPimAccessBackend<OPimContact> {
public:
OPimContactAccessBackend();
/**
* Return if database was changed externally.
* This may just make sense on file based databases like a XML-File.
* It is used to prevent to overwrite the current database content
* if the file was already changed by something else !
* If this happens, we have to reload before save our data.
* If we use real databases, this should be handled by the database
* management system themselve, therefore this function should always return false in
* this case. It is not our problem to handle this conflict ...
* @return <i>true</i> if the database was changed and if save without reload will
* be dangerous. <i>false</i> if the database was not changed or it is save to write
* in this situation.
*/
virtual bool wasChangedExternally() = 0;
/**
* Return all possible settings.
* @return All settings provided by the current backend
* (i.e.: query_WildCards & query_IgnoreCase)
*/
- virtual const uint querySettings() = 0;
+ virtual const uint querySettings() const;
/**
* Check whether settings are correct.
* @return <i>true</i> if the given settings are correct and possible.
*/
- virtual bool hasQuerySettings (uint querySettings) const = 0;
+ virtual bool hasQuerySettings (uint querySettings) const;
+ /**
+ * Advanced search mechanism.
+ */
+ UIDArray queryByExample( const UIDArray& uidlist, const OPimContact&, int settings, const QDateTime &d = QDateTime() ) const;
/**
* Slow and inefficent default implementation
*/
//@{
- UIDArray queryByExample( const OPimContact&, int settings, const QDateTime& d = QDateTime() )const;
UIDArray sorted( const UIDArray&, bool asc, int, int, const QArray<int>& )const;
OPimBackendOccurrence::List occurrences( const QDate&, const QDate& )const;
//@}
private:
class Private;
Private *d;
};
}
#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
index 3d284f7..9375f43 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
@@ -2,954 +2,1050 @@
This file is part of the Opie Project
Copyright (C) Stefan Eilers <eilers.stefan@epost.de>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* SQL Backend for the OPIE-Contact Database.
*/
#include "ocontactaccessbackend_sql.h"
/* OPIE */
#include <opie2/opimcontact.h>
#include <opie2/opimcontactfields.h>
#include <opie2/opimdateconversion.h>
#include <opie2/osqldriver.h>
#include <opie2/osqlresult.h>
#include <opie2/osqlmanager.h>
#include <opie2/osqlquery.h>
#include <opie2/odebug.h>
#include <qpe/global.h>
#include <qpe/recordfields.h>
/* QT */
#include <qarray.h>
#include <qdatetime.h>
#include <qstringlist.h>
using namespace Opie;
using namespace Opie::DB;
/*
* Implementation of used query types * CREATE query
* LOAD query
* INSERT
* REMOVE
* CLEAR
*/
namespace {
/**
* CreateQuery for the Todolist Table
*/
class CreateQuery : public OSQLQuery {
public:
CreateQuery();
~CreateQuery();
QString query()const;
};
/**
* Clears (delete) a Table
*/
class ClearQuery : public OSQLQuery {
public:
ClearQuery();
~ClearQuery();
QString query()const;
};
/**
* LoadQuery
* this one queries for all uids
*/
class LoadQuery : public OSQLQuery {
public:
LoadQuery();
~LoadQuery();
QString query()const;
};
/**
* inserts/adds a OPimContact to the table
*/
class InsertQuery : public OSQLQuery {
public:
InsertQuery(const OPimContact& );
~InsertQuery();
QString query()const;
private:
OPimContact m_contact;
};
/**
* removes one from the table
*/
class RemoveQuery : public OSQLQuery {
public:
RemoveQuery(int uid );
~RemoveQuery();
QString query()const;
private:
int m_uid;
};
/**
* a find query for noncustom elements
*/
class FindQuery : public OSQLQuery {
public:
FindQuery(int uid);
- FindQuery(const QArray<int>& );
+ FindQuery(const UIDArray& );
~FindQuery();
QString query()const;
private:
QString single()const;
QString multi()const;
- QArray<int> m_uids;
+ UIDArray m_uids;
int m_uid;
};
/**
* a find query for custom elements
*/
class FindCustomQuery : public OSQLQuery {
public:
FindCustomQuery(int uid);
- FindCustomQuery(const QArray<int>& );
+ FindCustomQuery(const UIDArray& );
~FindCustomQuery();
QString query()const;
private:
QString single()const;
QString multi()const;
- QArray<int> m_uids;
+ UIDArray m_uids;
int m_uid;
};
// We using two tables to store the information:
// 1. addressbook : It contains General information about the contact (non custom)
// 2. custom_data : Not official supported entries
// All tables are connected by the uid of the contact.
// Maybe I should add a table for meta-information ?
CreateQuery::CreateQuery() : OSQLQuery() {}
CreateQuery::~CreateQuery() {}
QString CreateQuery::query()const {
QString qu;
qu += "create table addressbook( uid PRIMARY KEY ";
QStringList fieldList = OPimContactFields::untrfields( false );
for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
}
qu += " );";
qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), priority INTEGER, value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
return qu;
}
ClearQuery::ClearQuery()
: OSQLQuery() {}
ClearQuery::~ClearQuery() {}
QString ClearQuery::query()const {
QString qu = "drop table addressbook;";
qu += "drop table custom_data;";
// qu += "drop table dates;";
return qu;
}
LoadQuery::LoadQuery() : OSQLQuery() {}
LoadQuery::~LoadQuery() {}
QString LoadQuery::query()const {
QString qu;
qu += "select uid from addressbook";
return qu;
}
InsertQuery::InsertQuery( const OPimContact& contact )
: OSQLQuery(), m_contact( contact ) {
}
InsertQuery::~InsertQuery() {
}
/*
* converts from a OPimContact to a query
*/
QString InsertQuery::query()const{
QString qu;
qu += "insert into addressbook VALUES( " +
QString::number( m_contact.uid() );
// Get all information out of the contact-class
// Remember: The category is stored in contactMap, too !
QMap<int, QString> contactMap = m_contact.toMap();
QStringList fieldList = OPimContactFields::untrfields( false );
QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
// Convert Column-String to Id and get value for this id..
// Hmmm.. Maybe not very cute solution..
int id = translate[*it];
switch ( id ){
case Qtopia::Birthday:
case Qtopia::Anniversary:{
QDate day;
if ( id == Qtopia::Birthday ){
day = m_contact.birthday();
} else {
day = m_contact.anniversary();
}
// These entries should stored in a special format
// year-month-day
if ( day.isValid() ){
qu += QString(",\"%1-%2-%3\"")
.arg( QString::number( day.year() ).rightJustify( 4, '0' ) )
.arg( QString::number( day.month() ).rightJustify( 2, '0' ) )
.arg( QString::number( day.day() ).rightJustify( 2, '0' ) );
} else {
qu += ",\"\"";
}
}
break;
default:
qu += QString( ",\"%1\"" ).arg( contactMap[id] );
}
}
qu += " );";
// Now add custom data..
int id = 0;
id = 0;
QMap<QString, QString> customMap = m_contact.toExtraMap();
for( QMap<QString, QString>::Iterator it = customMap.begin();
it != customMap.end(); ++it ){
qu += "insert into custom_data VALUES("
+ QString::number( m_contact.uid() )
+ ","
+ QString::number( id++ )
+ ",'"
+ it.key()
+ "',"
+ "0" // Priority for future enhancements
+ ",'"
+ it.data()
+ "');";
}
// qu += "commit;";
odebug << "add " << qu << "" << oendl;
return qu;
}
RemoveQuery::RemoveQuery(int uid )
: OSQLQuery(), m_uid( uid ) {}
RemoveQuery::~RemoveQuery() {}
QString RemoveQuery::query()const {
QString qu = "DELETE from addressbook where uid = "
+ QString::number(m_uid) + ";";
qu += "DELETE from custom_data where uid = "
+ QString::number(m_uid) + ";";
return qu;
}
FindQuery::FindQuery(int uid)
: OSQLQuery(), m_uid( uid ) {
}
- FindQuery::FindQuery(const QArray<int>& ints)
+ FindQuery::FindQuery(const UIDArray& ints)
: OSQLQuery(), m_uids( ints ){
}
FindQuery::~FindQuery() {
}
QString FindQuery::query()const{
if ( m_uids.count() == 0 )
return single();
else
return multi();
}
QString FindQuery::multi()const {
QString qu = "select * from addressbook where";
for (uint i = 0; i < m_uids.count(); i++ ) {
qu += " uid = " + QString::number( m_uids[i] ) + " OR";
}
qu.remove( qu.length()-2, 2 ); // Hmmmm..
odebug << "find query: " << qu << "" << oendl;
return qu;
}
QString FindQuery::single()const{
QString qu = "select *";
qu += " from addressbook where uid = " + QString::number(m_uid);
// owarn << "find query: " << qu << "" << oendl;
return qu;
}
FindCustomQuery::FindCustomQuery(int uid)
: OSQLQuery(), m_uid( uid ) {
}
- FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
+ FindCustomQuery::FindCustomQuery(const UIDArray& ints)
: OSQLQuery(), m_uids( ints ){
}
FindCustomQuery::~FindCustomQuery() {
}
QString FindCustomQuery::query()const{
// if ( m_uids.count() == 0 )
return single();
}
QString FindCustomQuery::single()const{
QString qu = "select uid, type, value from custom_data where uid = ";
qu += QString::number(m_uid);
return qu;
}
};
/* --------------------------------------------------------------------------- */
namespace Opie {
OPimContactAccessBackend_SQL::OPimContactAccessBackend_SQL ( const QString& /* appname */,
const QString& filename ):
OPimContactAccessBackend(), m_changed(false), m_driver( NULL )
{
odebug << "C'tor OPimContactAccessBackend_SQL starts" << oendl;
QTime t;
t.start();
/* Expecting to access the default filename if nothing else is set */
if ( filename.isEmpty() ){
m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
} else
m_fileName = filename;
// Get the standart sql-driver from the OSQLManager..
OSQLManager man;
m_driver = man.standard();
m_driver->setUrl( m_fileName );
load();
odebug << "C'tor OPimContactAccessBackend_SQL ends: " << t.elapsed() << " ms" << oendl;
}
OPimContactAccessBackend_SQL::~OPimContactAccessBackend_SQL ()
{
if( m_driver )
delete m_driver;
}
bool OPimContactAccessBackend_SQL::load ()
{
if (!m_driver->open() )
return false;
// Don't expect that the database exists.
// It is save here to create the table, even if it
// do exist. ( Is that correct for all databases ?? )
CreateQuery creat;
OSQLResult res = m_driver->query( &creat );
update();
return true;
}
bool OPimContactAccessBackend_SQL::reload()
{
return load();
}
bool OPimContactAccessBackend_SQL::save()
{
return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
}
void OPimContactAccessBackend_SQL::clear ()
{
ClearQuery cle;
OSQLResult res = m_driver->query( &cle );
reload();
}
bool OPimContactAccessBackend_SQL::wasChangedExternally()
{
return false;
}
-QArray<int> OPimContactAccessBackend_SQL::allRecords() const
+UIDArray OPimContactAccessBackend_SQL::allRecords() const
{
// FIXME: Think about cute handling of changed tables..
// Thus, we don't have to call update here...
if ( m_changed )
((OPimContactAccessBackend_SQL*)this)->update();
return m_uids;
}
bool OPimContactAccessBackend_SQL::add ( const OPimContact &newcontact )
{
odebug << "add in contact SQL-Backend" << oendl;
InsertQuery ins( newcontact );
OSQLResult res = m_driver->query( &ins );
if ( res.state() == OSQLResult::Failure )
return false;
int c = m_uids.count();
m_uids.resize( c+1 );
m_uids[c] = newcontact.uid();
return true;
}
bool OPimContactAccessBackend_SQL::remove ( int uid )
{
RemoveQuery rem( uid );
OSQLResult res = m_driver->query(&rem );
if ( res.state() == OSQLResult::Failure )
return false;
m_changed = true;
return true;
}
bool OPimContactAccessBackend_SQL::replace ( const OPimContact &contact )
{
if ( !remove( contact.uid() ) )
return false;
return add( contact );
}
OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const
{
odebug << "OPimContactAccessBackend_SQL::find(" << uid << ")" << oendl;
QTime t;
t.start();
OPimContact retContact( requestNonCustom( uid ) );
retContact.setExtraMap( requestCustom( uid ) );
odebug << "OPimContactAccessBackend_SQL::find() needed: " << t.elapsed() << " ms" << oendl;
return retContact;
}
-OPimContact OPimContactAccessBackend_SQL::find( int uid, const QArray<int>& queryUids, uint current, Frontend::CacheDirection direction ) const
+OPimContact OPimContactAccessBackend_SQL::find( int uid, const UIDArray& queryUids, uint current, Frontend::CacheDirection direction ) const
{
odebug << "OPimContactAccessBackend_SQL::find( ..multi.. )" << oendl;
odebug << "searching for " << uid << "" << oendl;
QTime t;
t.start();
uint numReadAhead = readAhead();
QArray<int> searchList( numReadAhead );
uint size =0;
// Build an array with all elements which should be requested and cached
// We will just request "numReadAhead" elements, starting from "current" position in
// the list of many uids !
switch( direction ) {
/* forward */
case Frontend::Forward:
for ( uint i = current; i < queryUids.count() && size < numReadAhead; i++ ) {
searchList[size] = queryUids[i];
size++;
}
break;
/* reverse */
case Frontend::Reverse:
for ( uint i = current; i != 0 && size < numReadAhead; i-- ) {
searchList[size] = queryUids[i];
size++;
}
break;
}
//Shrink to real size..
searchList.resize( size );
OPimContact retContact( requestContactsAndCache( uid, searchList ) );
odebug << "OPimContactAccessBackend_SQL::find( ..multi.. ) needed: " << t.elapsed() << " ms" << oendl;
return retContact;
}
-QArray<int> OPimContactAccessBackend_SQL::queryByExample ( const OPimContact &query, int settings, const QDateTime& qd )
+UIDArray OPimContactAccessBackend_SQL::queryByExample ( const OPimContact &query, int settings,
+ const QDateTime& qd ) const
{
QString qu = "SELECT uid FROM addressbook WHERE";
QString searchQuery ="";
QDate startDate;
if ( qd.isValid() )
startDate = qd.date();
else
startDate = QDate::currentDate();
QMap<int, QString> queryFields = query.toMap();
QStringList fieldList = OPimContactFields::untrfields( false );
QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
// Convert every filled field to a SQL-Query
// bool isAnyFieldSelected = false;
for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
int id = translate[*it];
QString queryStr = queryFields[id];
QDate* endDate = 0l;
if ( !queryStr.isEmpty() ){
// If something is alredy stored in the query, add an "AND"
// to the end of the string to prepare for the next ..
if ( !searchQuery.isEmpty() )
searchQuery += " AND";
// isAnyFieldSelected = true;
switch( id ){
case Qtopia::Birthday:
endDate = new QDate( query.birthday() );
// Fall through !
case Qtopia::Anniversary:
if ( endDate == 0l )
endDate = new QDate( query.anniversary() );
if ( settings & OPimContactAccess::DateDiff ) {
searchQuery += QString( " (\"%1\" <= '%2-%3-%4\' AND \"%5\" >= '%6-%7-%8')" )
.arg( *it )
.arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) )
.arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) )
.arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) )
.arg( *it )
.arg( QString::number( startDate.year() ).rightJustify( 4, '0' ) )
.arg( QString::number( startDate.month() ).rightJustify( 2, '0' ) )
.arg( QString::number( startDate.day() ).rightJustify( 2, '0' ) ) ;
}
if ( settings & OPimContactAccess::DateYear ){
if ( settings & OPimContactAccess::DateDiff )
searchQuery += " AND";
searchQuery += QString( " (\"%1\" LIKE '%2-%')" )
.arg( *it )
.arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) );
}
if ( settings & OPimContactAccess::DateMonth ){
if ( ( settings & OPimContactAccess::DateDiff )
|| ( settings & OPimContactAccess::DateYear ) )
searchQuery += " AND";
searchQuery += QString( " (\"%1\" LIKE '%-%2-%')" )
.arg( *it )
.arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) );
}
if ( settings & OPimContactAccess::DateDay ){
if ( ( settings & OPimContactAccess::DateDiff )
|| ( settings & OPimContactAccess::DateYear )
|| ( settings & OPimContactAccess::DateMonth ) )
searchQuery += " AND";
searchQuery += QString( " (\"%1\" LIKE '%-%-%2')" )
.arg( *it )
.arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) );
}
break;
default:
// Switching between case sensitive and insensitive...
// LIKE is not case sensitive, GLOB is case sensitive
// Do exist a better solution to switch this ?
if ( settings & OPimContactAccess::IgnoreCase )
searchQuery += "(\"" + *it + "\"" + " LIKE " + "'"
+ queryStr.replace(QRegExp("\\*"),"%") + "'" + ")";
else
searchQuery += "(\"" + *it + "\"" + " GLOB " + "'"
+ queryStr + "'" + ")";
}
}
delete endDate;
}
// Skip trailing "AND"
// if ( isAnyFieldSelected )
// qu = qu.left( qu.length() - 4 );
qu += searchQuery;
odebug << "queryByExample query: " << qu << "" << oendl;
// Execute query and return the received uid's
OSQLRawQuery raw( qu );
OSQLResult res = m_driver->query( &raw );
if ( res.state() != OSQLResult::Success ){
- QArray<int> empty;
+ UIDArray empty;
return empty;
}
- QArray<int> list = extractUids( res );
+ UIDArray list = extractUids( res );
return list;
}
-QArray<int> OPimContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
+UIDArray OPimContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
{
#if 0
QArray<int> nix(0);
return nix;
#else
QString qu = "SELECT uid FROM addressbook WHERE (";
QString searchlist;
QStringList fieldList = OPimContactFields::untrfields( false );
// QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
if ( !searchlist.isEmpty() )
searchlist += " OR ";
searchlist += " rlike(\""+ r.pattern() + "\",\"" + *it + "\") ";
}
qu = qu + searchlist + ")";
odebug << "query: " << qu << "" << oendl;
OSQLRawQuery raw( qu );
OSQLResult res = m_driver->query( &raw );
return extractUids( res );
#endif
}
-const uint OPimContactAccessBackend_SQL::querySettings()
+const uint OPimContactAccessBackend_SQL::querySettings() const
{
return OPimContactAccess::IgnoreCase
| OPimContactAccess::WildCards
| OPimContactAccess::DateDiff
| OPimContactAccess::DateYear
| OPimContactAccess::DateMonth
| OPimContactAccess::DateDay
;
}
bool OPimContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
{
/* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
* may be added with any of the other settings. IgnoreCase should never used alone.
* Wildcards, RegExp, ExactMatch should never used at the same time...
*/
// Step 1: Check whether the given settings are supported by this backend
if ( ( querySettings & (
OPimContactAccess::IgnoreCase
| OPimContactAccess::WildCards
| OPimContactAccess::DateDiff
| OPimContactAccess::DateYear
| OPimContactAccess::DateMonth
| OPimContactAccess::DateDay
// | OPimContactAccess::RegExp
// | OPimContactAccess::ExactMatch
) ) != querySettings )
return false;
// Step 2: Check whether the given combinations are ok..
// IngoreCase alone is invalid
if ( querySettings == OPimContactAccess::IgnoreCase )
return false;
// WildCards, RegExp and ExactMatch should never used at the same time
switch ( querySettings & ~( OPimContactAccess::IgnoreCase
| OPimContactAccess::DateDiff
| OPimContactAccess::DateYear
| OPimContactAccess::DateMonth
| OPimContactAccess::DateDay
)
){
case OPimContactAccess::RegExp:
return ( true );
case OPimContactAccess::WildCards:
return ( true );
case OPimContactAccess::ExactMatch:
return ( true );
case 0: // one of the upper removed bits were set..
return ( true );
default:
return ( false );
}
}
-QArray<int> OPimContactAccessBackend_SQL::sorted( bool asc, int , int , int )
+UIDArray OPimContactAccessBackend_SQL::sorted( const UIDArray& ar, bool asc, int sortOrder,
+ int filter, const QArray<int>& categories )const
{
QTime t;
t.start();
- QString query = "SELECT uid FROM addressbook ";
- query += "ORDER BY \"Last Name\" ";
+ QString query = "SELECT uid FROM addressbook";
+
+ query += " WHERE (";
+ for ( uint i = 0; i < ar.count(); i++ ) {
+ query += " uid = " + QString::number( ar[i] ) + " OR";
+ }
+ query.remove( query.length()-2, 2 ); // Hmmmm..
+ query += ")";
+
+
+ if ( filter != OPimBase::FilterOff ){
+ if ( filter & OPimContactAccess::DoNotShowWithCategory ){
+ query += " AND ( \"Categories\" == '' )";
+ } else if ( filter & OPimBase::FilterCategory ){
+ query += " AND (";
+ for ( uint i = 0; i < categories.count(); i++ ){
+ query += "\"Categories\" LIKE";
+ query += QString( " '%" ) + QString::number( categories[i] ) + "%' OR";
+ }
+ query.remove( query.length()-2, 2 ); // Hmmmm..
+ query += ")";
+ }
+
+ if ( filter & OPimContactAccess::DoNotShowWithoutChildren ){
+ query += " AND ( \"Children\" != '' )";
+ }
+
+ if ( filter & OPimContactAccess::DoNotShowWithoutAnniversary ){
+ query += " AND ( \"Anniversary\" != '' )";
+ }
+
+ if ( filter & OPimContactAccess::DoNotShowWithoutBirthday ){
+ query += " AND ( \"Birthday\" != '' )";
+ }
+
+ if ( filter & OPimContactAccess::DoNotShowWithoutHomeAddress ){
+ // Expect that no Street means no Address, too! (eilers)
+ query += " AND ( \"Home Street\" != '' )";
+ }
+
+ if ( filter & OPimContactAccess::DoNotShowWithoutBusinessAddress ){
+ // Expect that no Street means no Address, too! (eilers)
+ query += " AND ( \"Business Street\" != '' )";
+ }
+
+ }
+
+ query += " ORDER BY";
+
+ switch ( sortOrder ) {
+ case OPimContactAccess::SortSummary:
+ query += " \"Notes\"";
+ break;
+ case OPimContactAccess::SortByCategory:
+ query += " \"Categories\"";
+ break;
+ case OPimContactAccess::SortByDate:
+ query += " \"\"";
+ break;
+ case OPimContactAccess::SortTitle:
+ query += " \"Name Title\"";
+ break;
+ case OPimContactAccess::SortFirstName:
+ query += " \"First Name\"";
+ break;
+ case OPimContactAccess::SortMiddleName:
+ query += " \"Middle Name\"";
+ break;
+ case OPimContactAccess::SortLastName:
+ query += " \"Last Name\"";
+ break;
+ case OPimContactAccess::SortFileAsName:
+ query += " \"File As\"";
+ break;
+ case OPimContactAccess::SortSuffix:
+ query += " \"Suffix\"";
+ break;
+ case OPimContactAccess::SortEmail:
+ query += " \"Default Email\"";
+ break;
+ case OPimContactAccess::SortNickname:
+ query += " \"Nickname\"";
+ break;
+ case OPimContactAccess::SortAnniversary:
+ query += " \"Anniversary\"";
+ break;
+ case OPimContactAccess::SortBirthday:
+ query += " \"Birthday\"";
+ break;
+ case OPimContactAccess::SortGender:
+ query += " \"Gender\"";
+ break;
+ default:
+ query += " \"Last Name\"";
+ }
if ( !asc )
- query += "DESC";
+ query += " DESC";
+
- // odebug << "sorted query is: " << query << "" << oendl;
+ odebug << "sorted query is: " << query << "" << oendl;
OSQLRawQuery raw( query );
OSQLResult res = m_driver->query( &raw );
if ( res.state() != OSQLResult::Success ){
- QArray<int> empty;
+ UIDArray empty;
return empty;
}
- QArray<int> list = extractUids( res );
+ UIDArray list = extractUids( res );
odebug << "sorted needed " << t.elapsed() << " ms!" << oendl;
return list;
}
void OPimContactAccessBackend_SQL::update()
{
odebug << "Update starts" << oendl;
QTime t;
t.start();
// Now load the database set and extract the uid's
// which will be held locally
LoadQuery lo;
OSQLResult res = m_driver->query(&lo);
if ( res.state() != OSQLResult::Success )
return;
m_uids = extractUids( res );
m_changed = false;
odebug << "Update ends " << t.elapsed() << " ms" << oendl;
}
-QArray<int> OPimContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
+UIDArray OPimContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
{
odebug << "extractUids" << oendl;
QTime t;
t.start();
OSQLResultItem::ValueList list = res.results();
OSQLResultItem::ValueList::Iterator it;
- QArray<int> ints(list.count() );
+ UIDArray ints(list.count() );
odebug << " count = " << list.count() << "" << oendl;
int i = 0;
for (it = list.begin(); it != list.end(); ++it ) {
ints[i] = (*it).data("uid").toInt();
i++;
}
odebug << "extractUids ready: count2 = " << i << " needs " << t.elapsed() << " ms" << oendl;
return ints;
}
QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) const
{
QTime t;
t.start();
int t2needed = 0;
int t3needed = 0;
QTime t2;
t2.start();
FindQuery query( uid );
OSQLResult res_noncustom = m_driver->query( &query );
t2needed = t2.elapsed();
OSQLResultItem resItem = res_noncustom.first();
QMap<int, QString> nonCustomMap;
QTime t3;
t3.start();
nonCustomMap = fillNonCustomMap( resItem );
t3needed = t3.elapsed();
// odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
odebug << "RequestNonCustom needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
<< " ms, mapping: " << t3needed << " ms" << oendl;
return nonCustomMap;
}
/* Returns contact requested by uid and fills cache with contacts requested by uids in the cachelist */
-OPimContact OPimContactAccessBackend_SQL::requestContactsAndCache( int uid, const QArray<int>& uidlist )const
+OPimContact OPimContactAccessBackend_SQL::requestContactsAndCache( int uid, const UIDArray& uidlist )const
{
// We want to get all contacts with one query.
// We don't have to add the given uid to the uidlist, it is expected to be there already (see opimrecordlist.h).
// All contacts will be stored in the cache, afterwards the contact with the user id "uid" will be returned
// by using the cache..
- QArray<int> cachelist = uidlist;
+ UIDArray cachelist = uidlist;
OPimContact retContact;
odebug << "Reqest and cache" << cachelist.size() << "elements !" << oendl;
QTime t;
t.start();
int t2needed = 0;
int t3needed = 0;
QTime t2;
t2.start();
FindQuery query( cachelist );
OSQLResult res_noncustom = m_driver->query( &query );
t2needed = t2.elapsed();
QMap<int, QString> nonCustomMap;
QTime t3;
t3.start();
OSQLResultItem resItem = res_noncustom.first();
do {
OPimContact contact( fillNonCustomMap( resItem ) );
contact.setExtraMap( requestCustom( contact.uid() ) );
odebug << "Caching uid: " << contact.uid() << oendl;
cache( contact );
if ( contact.uid() == uid )
retContact = contact;
resItem = res_noncustom.next();
} while ( ! res_noncustom.atEnd() ); //atEnd() is true if we are past(!) the list !!
t3needed = t3.elapsed();
// odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
odebug << "RequestContactsAndCache needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
<< " ms, mapping: " << t3needed << " ms" << oendl;
return retContact;
}
QMap<int, QString> OPimContactAccessBackend_SQL::fillNonCustomMap( const OSQLResultItem& resultItem ) const
{
QMap<int, QString> nonCustomMap;
// Now loop through all columns
QStringList fieldList = OPimContactFields::untrfields( false );
QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
// Get data for the selected column and store it with the
// corresponding id into the map..
int id = translate[*it];
QString value = resultItem.data( (*it) );
// odebug << "Reading " << (*it) << "... found: " << value << "" << oendl;
switch( id ){
case Qtopia::Birthday:
case Qtopia::Anniversary:{
// Birthday and Anniversary are encoded special ( yyyy-mm-dd )
QStringList list = QStringList::split( '-', value );
QStringList::Iterator lit = list.begin();
int year = (*lit).toInt();
int month = (*(++lit)).toInt();
int day = (*(++lit)).toInt();
if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){
QDate date( year, month, day );
nonCustomMap.insert( id, OPimDateConversion::dateToString( date ) );
}
}
break;
case Qtopia::AddressCategory:
odebug << "Category is: " << value << "" << oendl;
default:
nonCustomMap.insert( id, value );
}
}
nonCustomMap.insert( Qtopia::AddressUid, resultItem.data( "uid" ) );
return nonCustomMap;
}
QMap<QString, QString> OPimContactAccessBackend_SQL::requestCustom( int uid ) const
{
QTime t;
t.start();
QMap<QString, QString> customMap;
FindCustomQuery query( uid );
OSQLResult res_custom = m_driver->query( &query );
if ( res_custom.state() == OSQLResult::Failure ) {
owarn << "OSQLResult::Failure in find query !!" << oendl;
QMap<QString, QString> empty;
return empty;
}
OSQLResultItem::ValueList list = res_custom.results();
OSQLResultItem::ValueList::Iterator it = list.begin();
for ( ; it != list.end(); ++it ) {
customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
}
odebug << "RequestCustom needed: " << t.elapsed() << " ms" << oendl;
return customMap;
}
}
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
index 28d9746..299c175 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
@@ -1,114 +1,115 @@
/*
This file is part of the Opie Project
Copyright (C) Stefan Eilers (Eilers.Stefan@epost.de)
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* SQL Backend for the OPIE-Contact Database.
*/
#ifndef _OPimContactAccessBackend_SQL_
#define _OPimContactAccessBackend_SQL_
#include <opie2/ocontactaccessbackend.h>
#include <opie2/ocontactaccess.h>
#include <qlist.h>
#include <qdict.h>
/* aren't in namespace Opie yet - alwin */
namespace Opie {
namespace DB {
class OSQLDriver;
class OSQLResult;
class OSQLResultItem;
}
}
namespace Opie {
/* the default xml implementation */
/**
* This class is the SQL implementation of a Contact backend
* it does implement everything available for OPimContact.
* @see OPimAccessBackend for more information of available methods
*/
class OPimContactAccessBackend_SQL : public OPimContactAccessBackend {
public:
OPimContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
~OPimContactAccessBackend_SQL ();
bool save();
bool load ();
void clear ();
bool wasChangedExternally();
- QArray<int> allRecords() const;
+ UIDArray allRecords() const;
OPimContact find( int uid ) const;
- OPimContact find( int uid, const QArray<int>& items, uint cur, Frontend::CacheDirection ) const;
+ OPimContact find( int uid, const UIDArray& items, uint cur, Frontend::CacheDirection ) const;
- QArray<int> queryByExample ( const OPimContact &query, int settings,
- const QDateTime& d );
+ UIDArray queryByExample ( const OPimContact &query, int settings,
+ const QDateTime& d ) const;
- QArray<int> matchRegexp( const QRegExp &r ) const;
+ UIDArray matchRegexp( const QRegExp &r ) const;
- const uint querySettings();
+ const uint querySettings() const;
bool hasQuerySettings (uint querySettings) const;
- // Currently only asc implemented..
- QArray<int> sorted( bool asc, int , int , int );
- bool add ( const OPimContact &newcontact );
+ UIDArray sorted( const UIDArray& ar, bool asc, int sortOrder,
+ int filter, const QArray<int>& categories)const;
+
+ bool add ( const OPimContact &newcontact );
bool replace ( const OPimContact &contact );
bool remove ( int uid );
bool reload();
private:
- QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
+ UIDArray extractUids( Opie::DB::OSQLResult& res ) const;
QMap<int, QString> requestNonCustom( int uid ) const;
QMap<QString, QString> requestCustom( int uid ) const;
QMap<int, QString> fillNonCustomMap( const Opie::DB::OSQLResultItem& resultItem ) const;
OPimContact requestContactsAndCache( int uid, const QArray<int>& cachelist ) const;
void update();
protected:
bool m_changed;
QString m_fileName;
- QArray<int> m_uids;
+ UIDArray m_uids;
Opie::DB::OSQLDriver* m_driver;
};
}
#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
index 5bb21c7..f3b6d56 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
@@ -32,278 +32,268 @@
#include <opie2/private/vobject_p.h>
/* OPIE */
#include <opie2/ocontactaccessbackend_vcard.h>
#include <opie2/odebug.h>
#include <qpe/timeconversion.h>
//FIXME: Hack to allow direct access to FILE* fh. Rewrite this!
#define protected public
#include <qfile.h>
#undef protected
namespace Opie {
OPimContactAccessBackend_VCard::OPimContactAccessBackend_VCard ( const QString& , const QString& filename ):
m_dirty( false ),
m_file( filename ),
version_major( 1 ),
version_minor( 0 )
{
load();
}
bool OPimContactAccessBackend_VCard::load ()
{
m_map.clear();
m_dirty = false;
VObject* obj = 0l;
if ( QFile::exists(m_file) ){
obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
if ( !obj )
return false;
}else{
odebug << "File \"" << m_file << "\" not found !" << oendl;
return false;
}
while ( obj ) {
OPimContact con = parseVObject( obj );
/*
* if uid is 0 assign a new one
* this at least happens on
* Nokia6210
*/
if ( con.uid() == 0 ){
con.setUid( 1 );
owarn << "assigned new uid " << con.uid() << "" << oendl;
}
m_map.insert( con.uid(), con );
VObject *t = obj;
obj = nextVObjectInList(obj);
cleanVObject( t );
}
return true;
}
bool OPimContactAccessBackend_VCard::reload()
{
return load();
}
bool OPimContactAccessBackend_VCard::save()
{
if (!m_dirty )
return true;
QFile file( m_file );
if (!file.open(IO_WriteOnly ) )
return false;
VObject *obj;
obj = newVObject( VCCalProp );
addPropValue( obj, VCVersionProp, "1.0" );
VObject *vo;
for(QMap<int, OPimContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
vo = createVObject( *it );
writeVObject( file.fh, vo ); //FIXME: HACK!!!
cleanVObject( vo );
}
cleanStrTbl();
deleteVObject( obj );
m_dirty = false;
return true;
}
void OPimContactAccessBackend_VCard::clear ()
{
m_map.clear();
m_dirty = true; // ??? sure ? (se)
}
bool OPimContactAccessBackend_VCard::add ( const OPimContact& newcontact )
{
m_map.insert( newcontact.uid(), newcontact );
m_dirty = true;
return true;
}
bool OPimContactAccessBackend_VCard::remove ( int uid )
{
m_map.remove( uid );
m_dirty = true;
return true;
}
bool OPimContactAccessBackend_VCard::replace ( const OPimContact &contact )
{
m_map.replace( contact.uid(), contact );
m_dirty = true;
return true;
}
OPimContact OPimContactAccessBackend_VCard::find ( int uid ) const
{
return m_map[uid];
}
-QArray<int> OPimContactAccessBackend_VCard::allRecords() const
+UIDArray OPimContactAccessBackend_VCard::allRecords() const
{
- QArray<int> ar( m_map.count() );
+ UIDArray ar( m_map.count() );
QMap<int, OPimContact>::ConstIterator it;
int i = 0;
for ( it = m_map.begin(); it != m_map.end(); ++it ) {
ar[i] = it.key();
i++;
}
return ar;
}
-const uint OPimContactAccessBackend_VCard::querySettings()
-{
- return 0; // No search possible
-}
-
-bool OPimContactAccessBackend_VCard::hasQuerySettings (uint ) const
-{
- return false; // No search possible, therefore all settings invalid ;)
-}
-
bool OPimContactAccessBackend_VCard::wasChangedExternally()
{
return false; // Don't expect concurrent access
}
// *** Private stuff ***
OPimContact OPimContactAccessBackend_VCard::parseVObject( VObject *obj )
{
OPimContact c;
VObjectIterator it;
initPropIterator( &it, obj );
while( moreIteration( &it ) ) {
VObject *o = nextVObject( &it );
QCString name = vObjectName( o );
QString value = QString::fromUtf8( vObjectStringZValue( o ) );
odebug << "(1)Read: " << name << " " << QString( value ).latin1() << oendl;
if ( name == VCVersionProp ) {
odebug << "Version: " << value << oendl;
QStringList version = QStringList::split( ".", value );
version_major = version[0].toUInt();
version_minor = version[1].toUInt();
odebug << "Major: "<< version_major << " Minor: " << version_minor << oendl;
}
else if ( name == VCNameProp ) {
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectTypeInfo( o );
QString value = QString::fromUtf8( vObjectStringZValue( o ) );
odebug << "Nametype is: "<< name << " Value: " << value.latin1() << oendl;
if ( name == VCNamePrefixesProp )
c.setTitle( value );
else if ( name == VCNameSuffixesProp )
c.setSuffix( value );
else if ( name == VCFamilyNameProp )
c.setLastName( value );
else if ( name == VCGivenNameProp )
c.setFirstName( value );
else if ( name == VCAdditionalNamesProp )
c.setMiddleName( value );
}
}
else if ( name == VCAdrProp ) {
bool work = TRUE; // default address is work address
QString street;
QString city;
QString region;
QString postal;
QString country;
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectTypeInfo( o );
QString value = QString::fromUtf8( vObjectStringZValue( o ) );
odebug << "AddressType is: "<< name << " Value: " << value.latin1() << oendl;
if ( name == VCHomeProp )
work = FALSE;
else if ( name == VCWorkProp )
work = TRUE;
else if ( name == VCStreetAddressProp )
street = value;
else if ( name == VCCityProp )
city = value;
else if ( name == VCRegionProp )
region = value;
else if ( name == VCPostalCodeProp )
postal = value;
else if ( name == VCCountryNameProp )
country = value;
}
if ( work ) {
c.setBusinessStreet( street );
c.setBusinessCity( city );
c.setBusinessCountry( country );
c.setBusinessZip( postal );
c.setBusinessState( region );
} else {
c.setHomeStreet( street );
c.setHomeCity( city );
c.setHomeCountry( country );
c.setHomeZip( postal );
c.setHomeState( region );
}
}
else if ( name == VCTelephoneProp ) {
enum {
HOME = 0x01,
WORK = 0x02,
VOICE = 0x04,
CELL = 0x08,
FAX = 0x10,
PAGER = 0x20,
UNKNOWN = 0x80
};
int type = 0;
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectTypeInfo( o );
odebug << "Telephonetype is: "<< name << " Value: " << value.latin1() << oendl;
if ( name == VCHomeProp )
type |= HOME;
else if ( name == VCWorkProp )
type |= WORK;
else if ( name == VCVoiceProp )
type |= VOICE;
else if ( name == VCCellularProp )
type |= CELL;
else if ( name == VCFaxProp )
type |= FAX;
else if ( name == VCPagerProp )
type |= PAGER;
else if ( name == VCPreferredProp )
;
else if ( name.left( 2 ) == "X-" || name.left( 2 ) == "x-" )
; // Ignore
else
type |= UNKNOWN;
}
if ( (type & UNKNOWN) != UNKNOWN ) {
if ( ( type & (HOME|WORK) ) == 0 ) // default
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
index b734530..3591988 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
@@ -1,89 +1,87 @@
/*
This file is part of the Opie Project
Copyright (C) The Main Author <main-author@whereever.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* VCard Backend for the OPIE-Contact Database.
*/
#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
#define __OCONTACTACCESSBACKEND_VCARD_H_
#include <opie2/opimcontact.h>
#include <opie2/ocontactaccessbackend.h>
class VObject;
namespace Opie {
/**
* This is the vCard 2.1 implementation of the Contact Storage
* @see OPimContactAccessBackend_XML
* @see OPimAccessBackend
*/
class OPimContactAccessBackend_VCard : public OPimContactAccessBackend {
public:
OPimContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null );
bool load ();
bool reload();
bool save();
void clear ();
bool add ( const OPimContact& newcontact );
bool remove ( int uid );
bool replace ( const OPimContact& contact );
OPimContact find ( int uid ) const;
- QArray<int> allRecords() const;
+ UIDArray allRecords() const;
- const uint querySettings();
- bool hasQuerySettings (uint querySettings) const;
bool wasChangedExternally();
private:
OPimContact parseVObject( VObject* obj );
VObject* createVObject( const OPimContact& c );
QString convDateToVCardDate( const QDate& c ) const;
QDate convVCardDateToDate( const QString& datestr );
VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
VObject *safeAddProp( VObject* o, const char* prop);
bool m_dirty : 1;
QString m_file;
QMap<int, OPimContact> m_map;
/**
* Version of parsed VCard
*/
uint version_major;
uint version_minor;
};
}
#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
index 5df7253..f96f1bf 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
@@ -58,503 +58,310 @@ using namespace Opie::Core;
namespace Opie {
OPimContactAccessBackend_XML::OPimContactAccessBackend_XML ( const QString& appname, const QString& filename ):
m_changed( false )
{
// Just m_contactlist should call delete if an entry
// is removed.
m_contactList.setAutoDelete( true );
m_uidToContact.setAutoDelete( false );
m_appName = appname;
/* Set journalfile name ... */
m_journalName = getenv("HOME");
m_journalName +="/.abjournal" + appname;
/* Expecting to access the default filename if nothing else is set */
if ( filename.isEmpty() ){
m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
} else
m_fileName = filename;
/* Load Database now */
load ();
}
bool OPimContactAccessBackend_XML::save()
{
if ( !m_changed )
return true;
QString strNewFile = m_fileName + ".new";
QFile f( strNewFile );
if ( !f.open( IO_WriteOnly|IO_Raw ) )
return false;
int total_written;
int idx_offset = 0;
QString out;
// Write Header
out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
" <Groups>\n"
" </Groups>\n"
" <Contacts>\n";
QCString cstr = out.utf8();
f.writeBlock( cstr.data(), cstr.length() );
idx_offset += cstr.length();
out = "";
// Write all contacts
QListIterator<OPimContact> it( m_contactList );
for ( ; it.current(); ++it ) {
out += "<Contact ";
(*it)->save( out );
out += "/>\n";
cstr = out.utf8();
total_written = f.writeBlock( cstr.data(), cstr.length() );
idx_offset += cstr.length();
if ( total_written != int(cstr.length()) ) {
f.close();
QFile::remove( strNewFile );
return false;
}
out = "";
}
out += " </Contacts>\n</AddressBook>\n";
// Write Footer
cstr = out.utf8();
total_written = f.writeBlock( cstr.data(), cstr.length() );
if ( total_written != int( cstr.length() ) ) {
f.close();
QFile::remove( strNewFile );
return false;
}
f.close();
// move the file over, I'm just going to use the system call
// because, I don't feel like using QDir.
if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
// remove the tmp file...
QFile::remove( strNewFile );
}
/* The journalfile should be removed now... */
removeJournal();
m_changed = false;
return true;
}
bool OPimContactAccessBackend_XML::load ()
{
m_contactList.clear();
m_uidToContact.clear();
/* Load XML-File and journal if it exists */
if ( !load ( m_fileName, false ) )
return false;
/* The returncode of the journalfile is ignored due to the
* fact that it does not exist when this class is instantiated !
* But there may such a file exist, if the application crashed.
* Therefore we try to load it to get the changes before the #
* crash happened...
*/
load (m_journalName, true);
return true;
}
void OPimContactAccessBackend_XML::clear ()
{
m_contactList.clear();
m_uidToContact.clear();
m_changed = false;
}
bool OPimContactAccessBackend_XML::wasChangedExternally()
{
QFileInfo fi( m_fileName );
QDateTime lastmod = fi.lastModified ();
return (lastmod != m_readtime);
}
-QArray<int> OPimContactAccessBackend_XML::allRecords() const
+UIDArray OPimContactAccessBackend_XML::allRecords() const
{
- QArray<int> uid_list( m_contactList.count() );
+ UIDArray uid_list( m_contactList.count() );
uint counter = 0;
QListIterator<OPimContact> it( m_contactList );
for( ; it.current(); ++it ){
uid_list[counter++] = (*it)->uid();
}
return ( uid_list );
}
OPimContact OPimContactAccessBackend_XML::find ( int uid ) const
{
OPimContact foundContact; //Create empty contact
OPimContact* found = m_uidToContact.find( QString().setNum( uid ) );
if ( found ){
foundContact = *found;
}
return ( foundContact );
}
-QArray<int> OPimContactAccessBackend_XML::queryByExample ( const OPimContact &query, int settings,
- const QDateTime& d )const
-{
- QArray<int> m_currentQuery( m_contactList.count() );
- QListIterator<OPimContact> it( m_contactList );
- uint arraycounter = 0;
-
- for( ; it.current(); ++it ){
- /* Search all fields and compare them with query object. Store them into list
- * if all fields matches.
- */
- QDate* queryDate = 0l;
- QDate* checkDate = 0l;
- bool allcorrect = true;
- for ( int i = 0; i < Qtopia::Groups; i++ ) {
- // Birthday and anniversary are special nonstring fields and should
- // be handled specially
- switch ( i ){
- case Qtopia::Birthday:
- queryDate = new QDate( query.birthday() );
- checkDate = new QDate( (*it)->birthday() );
- // fall through
- case Qtopia::Anniversary:
- if ( queryDate == 0l ){
- queryDate = new QDate( query.anniversary() );
- checkDate = new QDate( (*it)->anniversary() );
- }
-
- if ( queryDate->isValid() ){
- if( checkDate->isValid() ){
- if ( settings & OPimContactAccess::DateYear ){
- if ( queryDate->year() != checkDate->year() )
- allcorrect = false;
- }
- if ( settings & OPimContactAccess::DateMonth ){
- if ( queryDate->month() != checkDate->month() )
- allcorrect = false;
- }
- if ( settings & OPimContactAccess::DateDay ){
- if ( queryDate->day() != checkDate->day() )
- allcorrect = false;
- }
- if ( settings & OPimContactAccess::DateDiff ) {
- QDate current;
- // If we get an additional date, we
- // will take this date instead of
- // the current one..
- if ( !d.date().isValid() )
- current = QDate::currentDate();
- else
- current = d.date();
-
- // We have to equalize the year, otherwise
- // the search will fail..
- checkDate->setYMD( current.year(),
- checkDate->month(),
- checkDate->day() );
- if ( *checkDate < current )
- checkDate->setYMD( current.year()+1,
- checkDate->month(),
- checkDate->day() );
-
- // Check whether the birthday/anniversary date is between
- // the current/given date and the maximum date
- // ( maximum time range ) !
- if ( current.daysTo( *queryDate ) >= 0 ){
- if ( !( ( *checkDate >= current ) &&
- ( *checkDate <= *queryDate ) ) ){
- allcorrect = false;
- }
- }
- }
- } else{
- // checkDate is invalid. Therefore this entry is always rejected
- allcorrect = false;
- }
- }
- delete queryDate;
- queryDate = 0l;
- delete checkDate;
- checkDate = 0l;
- break;
- default:
- /* Just compare fields which are not empty in the query object */
- if ( !query.field(i).isEmpty() ){
- switch ( settings & ~( OPimContactAccess::IgnoreCase
- | OPimContactAccess::DateDiff
- | OPimContactAccess::DateYear
- | OPimContactAccess::DateMonth
- | OPimContactAccess::DateDay
- | OPimContactAccess::MatchOne
- ) ){
-
- case OPimContactAccess::RegExp:{
- QRegExp expr ( query.field(i),
- !(settings & OPimContactAccess::IgnoreCase),
- false );
- if ( expr.find ( (*it)->field(i), 0 ) == -1 )
- allcorrect = false;
- }
- break;
- case OPimContactAccess::WildCards:{
- QRegExp expr ( query.field(i),
- !(settings & OPimContactAccess::IgnoreCase),
- true );
- if ( expr.find ( (*it)->field(i), 0 ) == -1 )
- allcorrect = false;
- }
- break;
- case OPimContactAccess::ExactMatch:{
- if (settings & OPimContactAccess::IgnoreCase){
- if ( query.field(i).upper() !=
- (*it)->field(i).upper() )
- allcorrect = false;
- }else{
- if ( query.field(i) != (*it)->field(i) )
- allcorrect = false;
- }
- }
- break;
- }
- }
- }
- }
- if ( allcorrect ){
- m_currentQuery[arraycounter++] = (*it)->uid();
- }
- }
-
- // Shrink to fit..
- m_currentQuery.resize(arraycounter);
-
- return m_currentQuery;
-}
-
-QArray<int> OPimContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
+UIDArray OPimContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
{
- QArray<int> m_currentQuery( m_contactList.count() );
+ UIDArray m_currentQuery( m_contactList.count() );
QListIterator<OPimContact> it( m_contactList );
uint arraycounter = 0;
for( ; it.current(); ++it ){
if ( (*it)->match( r ) ){
m_currentQuery[arraycounter++] = (*it)->uid();
}
}
// Shrink to fit..
m_currentQuery.resize(arraycounter);
return m_currentQuery;
}
-const uint OPimContactAccessBackend_XML::querySettings()
-{
- return ( OPimContactAccess::WildCards
- | OPimContactAccess::IgnoreCase
- | OPimContactAccess::RegExp
- | OPimContactAccess::ExactMatch
- | OPimContactAccess::DateDiff
- | OPimContactAccess::DateYear
- | OPimContactAccess::DateMonth
- | OPimContactAccess::DateDay
- );
-}
-bool OPimContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
-{
- /* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
- * may be added with any of the other settings. IgnoreCase should never used alone.
- * Wildcards, RegExp, ExactMatch should never used at the same time...
- */
-
- // Step 1: Check whether the given settings are supported by this backend
- if ( ( querySettings & (
- OPimContactAccess::IgnoreCase
- | OPimContactAccess::WildCards
- | OPimContactAccess::DateDiff
- | OPimContactAccess::DateYear
- | OPimContactAccess::DateMonth
- | OPimContactAccess::DateDay
- | OPimContactAccess::RegExp
- | OPimContactAccess::ExactMatch
- ) ) != querySettings )
- return false;
-
- // Step 2: Check whether the given combinations are ok..
-
- // IngoreCase alone is invalid
- if ( querySettings == OPimContactAccess::IgnoreCase )
- return false;
-
- // WildCards, RegExp and ExactMatch should never used at the same time
- switch ( querySettings & ~( OPimContactAccess::IgnoreCase
- | OPimContactAccess::DateDiff
- | OPimContactAccess::DateYear
- | OPimContactAccess::DateMonth
- | OPimContactAccess::DateDay
- )
- ){
- case OPimContactAccess::RegExp:
- return ( true );
- case OPimContactAccess::WildCards:
- return ( true );
- case OPimContactAccess::ExactMatch:
- return ( true );
- case 0: // one of the upper removed bits were set..
- return ( true );
- default:
- return ( false );
- }
-}
#if 0
// Currently only asc implemented..
-QArray<int> OPimContactAccessBackend_XML::sorted( bool asc, int , int , int )
+UIDArray OPimContactAccessBackend_XML::sorted( bool asc, int , int , int )
{
QMap<QString, int> nameToUid;
QStringList names;
- QArray<int> m_currentQuery( m_contactList.count() );
+ UIDArray m_currentQuery( m_contactList.count() );
// First fill map and StringList with all Names
// Afterwards sort namelist and use map to fill array to return..
QListIterator<OPimContact> it( m_contactList );
for( ; it.current(); ++it ){
names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
}
names.sort();
int i = 0;
if ( asc ){
for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
m_currentQuery[i++] = nameToUid[ (*it) ];
}else{
for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
m_currentQuery[i++] = nameToUid[ (*it) ];
}
return m_currentQuery;
}
#endif
bool OPimContactAccessBackend_XML::add ( const OPimContact &newcontact )
{
updateJournal (newcontact, ACTION_ADD);
addContact_p( newcontact );
m_changed = true;
return true;
}
bool OPimContactAccessBackend_XML::replace ( const OPimContact &contact )
{
m_changed = true;
OPimContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
if ( found ) {
OPimContact* newCont = new OPimContact( contact );
updateJournal ( *newCont, ACTION_REPLACE);
m_contactList.removeRef ( found );
m_contactList.append ( newCont );
m_uidToContact.remove( QString().setNum( contact.uid() ) );
m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
return true;
} else
return false;
}
bool OPimContactAccessBackend_XML::remove ( int uid )
{
m_changed = true;
OPimContact* found = m_uidToContact.find ( QString().setNum( uid ) );
if ( found ) {
updateJournal ( *found, ACTION_REMOVE);
m_contactList.removeRef ( found );
m_uidToContact.remove( QString().setNum( uid ) );
return true;
} else
return false;
}
bool OPimContactAccessBackend_XML::reload(){
/* Reload is the same as load in this implementation */
return ( load() );
}
void OPimContactAccessBackend_XML::addContact_p( const OPimContact &newcontact )
{
OPimContact* contRef = new OPimContact( newcontact );
m_contactList.append ( contRef );
m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
}
/* This function loads the xml-database and the journalfile */
bool OPimContactAccessBackend_XML::load( const QString filename, bool isJournal )
{
/* We use the time of the last read to check if the file was
* changed externally.
*/
if ( !isJournal ){
QFileInfo fi( filename );
m_readtime = fi.lastModified ();
}
const int JOURNALACTION = Qtopia::Notes + 1;
const int JOURNALROW = JOURNALACTION + 1;
bool foundAction = false;
journal_action action = ACTION_ADD;
int journalKey = 0;
QMap<int, QString> contactMap;
QMap<QString, QString> customMap;
QMap<QString, QString>::Iterator customIt;
QAsciiDict<int> dict( 47 );
dict.setAutoDelete( TRUE );
dict.insert( "Uid", new int(Qtopia::AddressUid) );
dict.insert( "Title", new int(Qtopia::Title) );
dict.insert( "FirstName", new int(Qtopia::FirstName) );
dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
dict.insert( "LastName", new int(Qtopia::LastName) );
dict.insert( "Suffix", new int(Qtopia::Suffix) );
dict.insert( "FileAs", new int(Qtopia::FileAs) );
dict.insert( "Categories", new int(Qtopia::AddressCategory) );
dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
dict.insert( "Emails", new int(Qtopia::Emails) );
dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
dict.insert( "HomeState", new int(Qtopia::HomeState) );
dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
dict.insert( "Company", new int(Qtopia::Company) );
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
index 3e4f1e1..39378ec 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
@@ -1,105 +1,100 @@
/*
This file is part of the Opie Project
Copyright (C) Stefan Eilers (Eilers.Stefan@epost.de)
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* XML Backend for the OPIE-Contact Database.
*/
#ifndef _OPimContactAccessBackend_XML_
#define _OPimContactAccessBackend_XML_
#include <opie2/ocontactaccessbackend.h>
#include <opie2/ocontactaccess.h>
#include <qlist.h>
#include <qdict.h>
namespace Opie {
/* the default xml implementation */
/**
* This class is the XML implementation of a Contact backend
* it does implement everything available for OPimContact.
* @see OPimAccessBackend for more information of available methods
*/
class OPimContactAccessBackend_XML : public OPimContactAccessBackend {
public:
OPimContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
bool save();
bool load ();
void clear ();
bool wasChangedExternally();
- QArray<int> allRecords() const;
+ UIDArray allRecords() const;
OPimContact find ( int uid ) const;
- QArray<int> queryByExample ( const OPimContact &query, int settings, const QDateTime& d )const;
- QArray<int> matchRegexp( const QRegExp &r ) const;
-
- const uint querySettings();
-
- bool hasQuerySettings (uint querySettings) const;
+ UIDArray matchRegexp( const QRegExp &r ) const;
bool add ( const OPimContact &newcontact );
bool replace ( const OPimContact &contact );
bool remove ( int uid );
bool reload();
private:
enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
void addContact_p( const OPimContact &newcontact );
/* This function loads the xml-database and the journalfile */
bool load( const QString filename, bool isJournal );
void updateJournal( const OPimContact& cnt, journal_action action );
void removeJournal();
protected:
bool m_changed;
QString m_journalName;
QString m_fileName;
QString m_appName;
QList<OPimContact> m_contactList;
QDateTime m_readtime;
QDict<OPimContact> m_uidToContact;
};
}
#endif
diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h
index 0d112c9..7321758 100644
--- a/libopie2/opiepim/backend/opimaccessbackend.h
+++ b/libopie2/opiepim/backend/opimaccessbackend.h
@@ -1,297 +1,319 @@
/*
This file is part of the Opie Project
Copyright (C) The Main Author <main-author@whereever.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef OPIE_PIM_ACCESS_BACKEND
#define OPIE_PIM_ACCESS_BACKEND
#include <qarray.h>
#include <qdatetime.h>
#include <opie2/opimtemplatebase.h>
#include <opie2/opimrecord.h>
#include <opie2/opimbackendoccurrence.h>
namespace Opie {
class OPimAccessBackendPrivate;
/**
* OPimAccessBackend is the Backend Interface to be used
* by OTemplateBase based Frontends.
* For efficency reasons and to support delayed loading
* most of the Frontend functions can be implemented
* by this backend.
* This allows to utilise the best method on each backend.
* For example we can use SQL queries instead of self made
* query which is first more efficent and also uses less memory.
*/
template <class T = OPimRecord>
class OPimAccessBackend {
public:
typedef OTemplateBase<T> Frontend;
//@{
OPimAccessBackend(int access = 0);
virtual ~OPimAccessBackend();
//@}
//@{
virtual bool load() = 0;
virtual bool reload() = 0;
virtual bool save() = 0;
virtual void clear() = 0;
//@}
+ //@{
+ // FIXME: Uncommented some of the abstract functions below. This should be removed as they are implemented in
+ // all typespecifc backenends (eilers)
+ /**
+ * Return all possible settings for queryByExample()
+ * @return All settings provided by the current backend
+ * (i.e.: query_WildCards & query_IgnoreCase)
+ * See implementation in the specific backends for contacts, todo and dates.
+ */
+ virtual const uint querySettings() const { return 0; } /* FIXME: Make Abstrakt !! = 0; */
+
+ /**
+ * Check whether settings are correct for queryByExample()
+ * See implementation in the specific backends for OPimContactAccess, OPimTodoAccess and ODateBookAccess.
+ * @return <i>true</i> if the given settings are correct and possible.
+ */
+ virtual bool hasQuerySettings (uint querySettings) const { return false; } /* FIXME: Make Abstrakt !! = 0; */
+ //@}
+
//@{
virtual UIDArray allRecords()const = 0;
virtual UIDArray matchRegexp(const QRegExp &r) const;
- virtual UIDArray queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() )const = 0;
- virtual UIDArray queryByExample( const OPimRecord* rec, int, const QDateTime& d = QDateTime() )const;
- virtual UIDArray sorted( const UIDArray&, bool asc, int sortOrder, int sortFilter, const QArray<int>& cats )const;
+ virtual UIDArray queryByExample( const UIDArray&, const T& t,
+ int settings, const QDateTime& d = QDateTime() )const { return UIDArray(); } /* FIXME: Make Abstrakt !! = 0; */
+ virtual UIDArray queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() )const;
+ virtual UIDArray queryByExample( const OPimRecord* rec, int settings, const QDateTime& d = QDateTime() )const;
+ virtual UIDArray sorted( const UIDArray&, bool asc, int sortOrder, int sortFilter, const QArray<int>& cats )const = 0;
virtual UIDArray sorted( bool asc, int sortOrder, int sortFilter, const QArray<int>& cats )const;
virtual OPimBackendOccurrence::List occurrences( const QDate& start, const QDate& end)const;
virtual OPimBackendOccurrence::List occurrences( const QDateTime& dt )const;
//@}
//@{
virtual T find(UID uid )const = 0;
virtual T find(UID uid, const QArray<UID>& items,
uint current, typename Frontend::CacheDirection )const ;
//@}
//@{
virtual bool add( const T& t ) = 0;
virtual bool remove( UID uid ) = 0;
virtual bool replace( const T& t ) = 0;
//@}
void setFrontend( Frontend* front );
/**
* set the read ahead count
*/
void setReadAhead( uint count );
protected:
//@{
int access()const;
void cache( const T& t )const;
void setSaneCacheSize( int );
uint readAhead()const;
//@}
private:
OPimAccessBackendPrivate *d;
Frontend* m_front;
uint m_read;
int m_acc;
};
template <class T>
OPimAccessBackend<T>::OPimAccessBackend(int acc)
: m_acc( acc )
{
m_front = 0l;
}
template <class T>
OPimAccessBackend<T>::~OPimAccessBackend() {
}
/*
* Slow but default matchRegexp Implementation
* Create a Big Enough QArray and then iterate
* over all Records and matchRegexp them.
* At the end we will resize the array to the actual
* number of items
*/
template <class T>
UIDArray OPimAccessBackend<T>::matchRegexp( const QRegExp& reg )const {
UIDArray all_rec = allRecords();
UIDArray result( all_rec.count() );
uint used_records = 0, all_rec_count = all_rec.count();
for ( uint i = 0; i < all_rec_count; ++i )
if (find( all_rec[i], all_rec, i, Frontend::Forward ).match( reg ) )
result[used_records++] = all_rec[i];
/* shrink to fit */
result.resize( used_records );
return result;
}
template <class T>
+UIDArray OPimAccessBackend<T>::queryByExample( const T& rec, int settings,
+ const QDateTime& datetime )const {
+
+ return queryByExample( allRecords(), rec, settings, datetime );
+}
+
+template <class T>
UIDArray OPimAccessBackend<T>::queryByExample( const OPimRecord* rec, int settings,
const QDateTime& datetime )const {
T* tmp_rec = T::safeCast( rec );
UIDArray ar;
if ( tmp_rec )
ar = queryByExample( *tmp_rec, settings, datetime );
return ar;
}
template <class T>
-UIDArray OPimAccessBackend<T>::sorted( const UIDArray& ids, bool,
- int, int, const QArray<int>& ) const {
- return ids;
-}
-
-template <class T>
UIDArray OPimAccessBackend<T>::sorted( bool asc, int order, int filter,
const QArray<int>& cats )const {
return sorted( allRecords(), asc, order, filter, cats );
}
template<class T>
OPimBackendOccurrence::List OPimAccessBackend<T>::occurrences( const QDate&,
const QDate& )const {
return OPimBackendOccurrence::List();
}
template<class T>
OPimBackendOccurrence::List OPimAccessBackend<T>::occurrences( const QDateTime& dt )const {
QDate date = dt.date();
return occurrences( date, date );
}
template <class T>
void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
m_front = fr;
}
template <class T>
void OPimAccessBackend<T>::cache( const T& t )const {
if ( m_front )
m_front->cache( t );
}
template <class T>
void OPimAccessBackend<T>::setSaneCacheSize( int size) {
if ( m_front )
m_front->setSaneCacheSize( size );
}
template <class T>
T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
uint, typename Frontend::CacheDirection ) const{
qDebug( "*** Lookahead feature not supported. Fallback to default find!!" );
return find( uid );
}
template <class T>
void OPimAccessBackend<T>::setReadAhead( uint count ) {
m_read = count;
}
template <class T>
uint OPimAccessBackend<T>::readAhead()const {
return m_read;
}
template <class T>
int OPimAccessBackend<T>::access()const {
return m_acc;
}
}
/**
* \fn template <class T> OPimAccessBackend<T>::OPimAccessBackend(int hint )
* @param hint The access hint from the frontend
*/
/**
* \fn template <class T> bool OPimAccessBackend<T>::load()
* Opens the DataBase and does necessary
* initialisation of internal structures.
*
* @return true If the DataBase could be opened and
* Information was successfully loaded
*/
/**
* \fn template <class T> bool OPimAccessBackend<T>::reload()
* Reinitialise the DataBase and merges the external changes
* with your local changes.
*
* @return True if the DataBase was reloaded.
*
*/
/**
* \fn template <class T> bool OPimAccessBackend<T>::save()
*
* Save the changes to storage. In case of memory or
* disk shortage, return false.
*
*
* @return True if the DataBase could be saved to storage.
*/
/**
* \fn template <class T> bool OPimAccessBackend<T>::clear()
* Until a \sa save() changes shouldn't be comitted
*
*
* @return True if the DataBase could be cleared
* @todo Introduce a 'Commit'
*/
/**
* \fn template <class T> QArray<UID> OPimAccessBackend<T>::allRecords()const
* Return an array of all available uids in the loaded
* DataBase.
* @see load
*/
/**
* \fn template <class T> QArray<UID> OPimAccessBackend<T>::matchRegexp(const QRegExp& r)const
* Return a List of records that match the regex \par r.
*
* @param r The QRegExp to match.
*/
/**
* \fn template <class T> QArray<UID> OPimAccessBackend<T>::queryByExample(const T& t, int settings, const QDateTime& d = QDateTime() )
*
* Implement QueryByExample. An Example record is filled and with the
* settings and QDateTime it is determined how the query should be executed.
* Return a list of UIDs that match the Example
*
* @param t The Example record
* @param settings Gives
*
*/
/**
* \fn template<class T> QArray<UID> OPimAccessBackend<T>::sorted(const QArray<UID>& ids, bool asc, int sortOrder, int sortFilter, int cat)
* \brief Sort the List of records according to the preference
*
* Implement sorting in your backend. The default implementation is
* to return the list as it was passed.
* The default Backend Implementation should do unaccelerated filtering
diff --git a/libopie2/opiepim/core/ocontactaccess.h b/libopie2/opiepim/core/ocontactaccess.h
index 691ece2..bd85b4e 100644
--- a/libopie2/opiepim/core/ocontactaccess.h
+++ b/libopie2/opiepim/core/ocontactaccess.h
@@ -1,156 +1,177 @@
/*
This file is part of the Opie Project
Copyright (C) The Main Author <main-author@whereever.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* =====================================================================
* ToDo: Define enum for query settings
* =====================================================================
*/
#ifndef _OCONTACTACCESS_H
#define _OCONTACTACCESS_H
#include <qobject.h>
#include <qpe/qcopenvelope_qws.h>
#include <qvaluelist.h>
#include <qfileinfo.h>
#include <opie2/opimcontact.h>
#include <opie2/ocontactaccessbackend.h>
#include <opie2/opimaccesstemplate.h>
namespace Opie {
/**
* Class to access the contacts database.
* This is just a frontend for the real database handling which is
* done by the backend.
* This class is used to access the Contacts on a system. This class as any OPIE PIM
* class is backend independent.
* @author Stefan Eilers, Holger Freyther
* @see OPimAccessTemplate
*/
class OPimContactAccess: public QObject, public OPimAccessTemplate<OPimContact>
{
Q_OBJECT
public:
+ /**
+ * Filter for sorted()
+ * @see SortFilterBase in OPimBase
+ */
enum SortFilter {
- DoNotShowNoneChildren = FilterCustom<<1,
- DoNotShowNoneAnniversary = FilterCustom<<2,
- DoNotShowNoneBirthday = FilterCustom<<3,
- DoNotShowNoHomeAddress = FilterCustom<<4,
- DoNotShowNoBusinessAddress = FilterCustom<<5
+ /** Don't return entries who don't have children */
+ DoNotShowWithoutChildren = FilterCustom<<1,
+ /** Don't return entries who don't have an anniversary */
+ DoNotShowWithoutAnniversary = FilterCustom<<2,
+ /** Don't return entries who don't have a birthday */
+ DoNotShowWithoutBirthday = FilterCustom<<3,
+ /** Don't return entries who don't have a home address */
+ DoNotShowWithoutHomeAddress = FilterCustom<<4,
+ /** Don't return entries who don't have a business address */
+ DoNotShowWithoutBusinessAddress = FilterCustom<<5,
+ /** Don't return entries which hava any category */
+ DoNotShowWithCategory = FilterCustom << 6
};
+ /**
+ * Sort order for sorted()
+ * @see SortOrderBase in OPimBase
+ */
enum SortOrder {
SortTitle = SortCustom,
SortFirstName,
SortMiddleName,
+ SortLastName,
SortSuffix,
SortEmail,
SortNickname,
+ SortFileAsName,
SortAnniversary,
SortBirthday,
SortGender
};
/**
* Create Database with contacts (addressbook).
* @param appname Name of application which wants access to the database
* (i.e. "todolist")
* @param filename The name of the database file. If not set, the default one
* is used.
* @param backend Pointer to an alternative Backend. If not set, we will use
* the default backend.
* @param handlesync If <b>true</b> the database stores the current state
* automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
* which are used before and after synchronisation. If the application wants
* to react itself, it should be disabled by setting it to <b>false</b>
* @see OPimContactAccessBackend
*/
OPimContactAccess (const QString appname, const QString filename = 0l,
OPimContactAccessBackend* backend = 0l, bool handlesync = true);
~OPimContactAccess ();
- /** Return all possible settings.
+ /**
+ * Return all possible settings for queryByExample().
* @return All settings provided by the current backend
- * (i.e.: query_WildCards & query_IgnoreCase)
+ * (i.e.: WildCards & IgnoreCase)
+ * @see QuerySettings in OPimBase for details of the parameter
*/
const uint querySettings();
- /** Check whether settings are correct.
+ /**
+ * Check whether settings are correct for queryByExample().
* @return <i>true</i> if the given settings are correct and possible.
+ * @see QuerySettings in OPimBase for details of the parameter
*/
bool hasQuerySettings ( int querySettings ) const;
/**
* if the resource was changed externally.
* You should use the signal instead of polling possible changes !
*/
bool wasChangedExternally()const;
/** Save contacts database.
* Save is more a "commit". After calling this function, all changes are public available.
* @return true if successful
*/
bool save();
/**
* Return identification of used records
*/
int rtti() const;
signals:
/* Signal is emitted if the database was changed. Therefore
* we may need to reload to stay consistent.
* @param which Pointer to the database who created this event. This pointer
* is useful if an application has to handle multiple databases at the same time.
* @see reload()
*/
void signalChanged ( const OPimContactAccess *which );
private:
OPimContactAccessBackend *m_backEnd;
bool m_loading:1;
private slots:
void copMessage( const QCString &msg, const QByteArray &data );
private:
class Private;
Private *d;
};
}
#endif
diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h
index 2deb92a..073d5f9 100644
--- a/libopie2/opiepim/core/opimaccesstemplate.h
+++ b/libopie2/opiepim/core/opimaccesstemplate.h
@@ -1,393 +1,424 @@
/*
This file is part of the Opie Project
Copyright (C) Holger Freyther <zecke@handhelds.org>
Copyright (C) Stefan Eilers <eilers.stefan@epost.de>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
#define OPIE_PIM_ACCESS_TEMPLATE_H
/* OPIE */
#include <opie2/opimrecord.h>
#include <opie2/opimaccessbackend.h>
#include <opie2/opimrecordlist.h>
#include <opie2/opimtemplatebase.h>
#include <opie2/odebug.h>
/* QT */
#include <qarray.h>
#include <qdatetime.h>
namespace Opie {
class OPimAccessTemplatePrivate;
/**
* Thats the frontend to our OPIE PIM
* Library. Either you want to use it's
* interface or you want to implement
* your own Access lib
* Just create a OPimRecord and inherit from
* the templates
*/
template <class T = OPimRecord >
class OPimAccessTemplate : public OTemplateBase<T> {
public:
/**
*
*/
enum Access {
Random = 0,
SortedAccess
};
typedef OPimRecordList<T> List;
typedef OPimAccessBackend<T> BackEnd;
typedef OPimCache<T> Cache;
//@{
OPimAccessTemplate( BackEnd* end);
virtual ~OPimAccessTemplate();
//@}
//@{
bool load();
virtual bool reload();
bool save();
void clear() ;
//@}
bool wasChangedExternally()const;
//@{
virtual List allRecords()const;
virtual List matchRegexp( const QRegExp &r ) const;
virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
virtual T find( UID uid )const;
virtual T find( UID uid, const QArray<int>&,
uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
- virtual List sorted( const List&, bool ascending, int sortOrder,
+ //@}
+
+ /**
+ * Get sorted lists..
+ * @see OPimContactAccess, OPimTodoAccess and ODateBookAccess regarding more info for the following params:
+ * @param list of UID's received by allRecords() or others...
+ * @param sortOrder Setting the sort order defined by enum SortOrder
+ * @param ascending Sort in ascending order if true, otherwise descending
+ * @param sortFilter Setting the sort filter defined by enum SortFilter
+ * @param cat number of category.
+ */
+ virtual List sorted( const List& list, bool ascending, int sortOrder,
int sortFilter, int cat )const;
- virtual List sorted( const List&, bool ascending, int sortOrder,
+
+ /**
+ * Get sorted lists..
+ * @see OPimContactAccess, OPimTodoAccess and ODateBookAccess regarding more info for the following params:
+ * @param list of UID's received by allRecords() or others...
+ * @param sortOrder Setting the sort order defined by enum SortOrder
+ * @param ascending Sort in ascending order if true, otherwise descending
+ * @param sortFilter Setting the sort filter defined by enum SortFilter
+ * @param cats List of categories.
+ */
+ virtual List sorted( const List& list, bool ascending, int sortOrder,
int sortFilter, const QArray<UID>& cats )const;
+
+ /**
+ * Get sorted lists..
+ * @see OPimContactAccess, OPimTodoAccess and ODateBookAccess regarding more info for the following params:
+ * @param ascending Sort in ascending order if true, otherwise descending
+ * @param sortOrder Setting the sort order defined by enum SortOrder
+ * @param sortFilter Setting the sort filter defined by enum SortFilter
+ * @param cat number of category.
+ */
virtual List sorted( bool ascending, int sortOrder, int sortFilter, int cat )const;
- virtual List sorted( bool ascending, int sortOrder, int sortOrder,
- const QArray<UID>& cats )const;
- //@}
+ /**
+ * Get sorted lists..
+ * @see OPimContactAccess, OPimTodoAccess and ODateBookAccess regarding more info for the following params:
+ * @param ascending Sort in ascending order if true, otherwise descending
+ * @param sortOrder Setting the sort order defined by enum SortOrder
+ * @param sortFilter Setting the sort filter defined by enum SortFilter
+ * @param cats List of categories.
+ */
+ virtual List sorted( bool ascending, int sortOrder, int sortFilter,
+ const QArray<UID>& cats )const;
/**
* (Re)Implementation
*/
//@{
UIDArray matchRegexpSimple( const QRegExp& r )const;
UIDArray queryByExampleSimple( const OPimRecord*, int, const QDateTime& )const;
UIDArray sortedSimple( const UIDArray&, bool asc, int sortOrder,
int sortFilter, int cat )const;
UIDArray sortedSimple( const UIDArray&, bool asc, int sortOrder,
int sortFilter, const QArray<int>& )const;
UIDArray sortedSimple( bool ascending, int sortOrder, int sortFilter,
int cat )const;
UIDArray sortedSimple( bool ascending, int sortOrder, int sortFilter,
const QArray<int>& )const;
OPimOccurrence::List occurrences( const QDate& start, const QDate& end )const;
OPimOccurrence::List occurrences( const QDateTime& dt )const;
//@}
//@{
virtual bool add( const T& t ) ;
bool add( const OPimRecord& );
bool add( const OPimRecord* );
virtual bool remove( const T& t );
bool remove( UID uid );
bool remove( const OPimRecord& );
virtual bool replace( const T& t) ;
//@}
void setReadAhead( uint count );
- virtual T cacheFind( int uid )const;
void cache( const T& )const;
void setSaneCacheSize( int );
QArray<UID> records()const;
protected:
/**
* invalidate the cache
*/
void invalidateCache();
void setBackEnd( BackEnd* end );
/**
* returns the backend
*/
BackEnd* backEnd();
BackEnd* m_backEnd;
Cache m_cache;
private:
OPimAccessTemplatePrivate *d;
};
/**
* c'tor BackEnd
* enum Access a small hint on how to handle the backend
*/
template <class T>
OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
: OTemplateBase<T>(), m_backEnd( end )
{
if (end )
end->setFrontend( this );
}
template <class T>
OPimAccessTemplate<T>::~OPimAccessTemplate() {
delete m_backEnd;
}
/**
* load from the backend
*/
template <class T>
bool OPimAccessTemplate<T>::load() {
invalidateCache();
return m_backEnd->load();
}
/** Reload database.
* You should execute this function if the external database
* was changed.
* This function will load the external database and afterwards
* rejoin the local changes. Therefore the local database will be set consistent.
*/
template <class T>
bool OPimAccessTemplate<T>::reload() {
invalidateCache();
return m_backEnd->reload();
}
/**
* Save contacts database.
* Save is more a "commit". After calling this function, all changes are public available.
* @return true if successful
*/
template <class T>
bool OPimAccessTemplate<T>::save() {
return m_backEnd->save();
}
/**
* return a List of records
* you can iterate over them
*/
template <class T>
typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
QArray<int> ints = m_backEnd->allRecords();
List lis(ints, this );
return lis;
}
/**
* return a List of records
* that match the regex
*/
template <class T>
typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::matchRegexp( const QRegExp &r )const {
QArray<int> ints = m_backEnd->matchRegexp( r );
List lis(ints, this );
return lis;
}
/**
* find the OPimRecord uid
*/
template <class T>
QArray<int> OPimAccessTemplate<T>::records()const {
return m_backEnd->allRecords();
}
/**
* queryByExample.
* @see otodoaccess, ocontactaccess
*/
template <class T>
typename OPimAccessTemplate<T>::List
OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
List lis(ints, this );
return lis;
}
template <class T>
T OPimAccessTemplate<T>::find( UID uid ) const{
// First search in cache..
if ( m_cache.contains( uid ) )
return m_cache.find( uid );
T t = m_backEnd->find( uid );
cache( t );
return t;
}
-template <class T>
-T OPimAccessTemplate<T>::cacheFind( int uid ) const
-{
- return m_cache.find( uid );
-}
/**
* read ahead cache find method ;)
*/
template <class T>
T OPimAccessTemplate<T>::find( UID uid, const QArray<int>& ar,
uint current, typename OTemplateBase<T>::CacheDirection dir )const {
/*
* better do T.isEmpty()
* after a find this way we would
* avoid two finds in QCache...
*/
if (m_cache.contains( uid ) )
return m_cache.find( uid );
T t = m_backEnd->find( uid, ar, current, dir );
cache( t );
return t;
}
/**
* clears the backend and invalidates the backend
*/
template <class T>
void OPimAccessTemplate<T>::clear() {
invalidateCache();
m_backEnd->clear();
}
/**
* add T to the backend
* @param t The item to add.
* @return <i>true</i> if added successfully.
*/
template <class T>
bool OPimAccessTemplate<T>::add( const T& t ) {
cache( t );
return m_backEnd->add( t );
}
template <class T>
bool OPimAccessTemplate<T>::add( const OPimRecord& rec ) {
/* same type */
T tempInstance;
if ( rec.rtti() == tempInstance.rtti() ) {
const T& t = static_cast<const T&>(rec);
return add(t);
} else {
owarn << "Adding not possible: Objecttype mismatch" << oendl;
}
return false;
}
/**
* Add an Opie PimRecord.
* Info: Take this if you are working with OPimRecords and you need to add it into any database.
* But take care that the accessing database is compatible to the real type of OPimRecord !!
* Otherwise this access will be rejected !
*/
template <class T>
bool OPimAccessTemplate<T>::add( const OPimRecord* rec) {
/* same type, but pointer */
T tempInstance;
if ( rec -> rtti() == tempInstance.rtti() ) {
const T* t = static_cast<const T*>(rec);
return add( *t );
} else {
owarn << "Adding not possible: Objecttype mismatch" << oendl;
}
return false;
}
/**
* remove T from the backend
* @param t The item to remove
* @return <i>true</i> if successful.
*/
template <class T>
bool OPimAccessTemplate<T>::remove( const T& t ) {
return remove( t.uid() );
}
/**
* remove the OPimRecord with uid
* @param uid The ID of the item to remove
* @return <i>true</i> if successful.
*/
template <class T>
bool OPimAccessTemplate<T>::remove( UID uid ) {
m_cache.remove( uid );
return m_backEnd->remove( uid );
}
template <class T>
bool OPimAccessTemplate<T>::remove( const OPimRecord& rec) {
return remove( rec.uid() );
}
/**
* replace T from backend
* @param t The item to replace
* @return <i>true</i> if successful.
*/
template <class T>
bool OPimAccessTemplate<T>::replace( const T& t ) {
m_cache.replace( t );
return m_backEnd->replace( t );
}
/**
* @internal
*/
template <class T>
void OPimAccessTemplate<T>::invalidateCache() {
m_cache.invalidate();
}
template <class T>
typename OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
return m_backEnd;
}
/**
* if the resource was changed externally
* You should use the signal handling instead of polling possible changes !
* zecke: Do you implement a signal for otodoaccess ?
*/
template <class T>
diff --git a/libopie2/opiepim/core/opimtemplatebase.h b/libopie2/opiepim/core/opimtemplatebase.h
index b238a68..c8abab4 100644
--- a/libopie2/opiepim/core/opimtemplatebase.h
+++ b/libopie2/opiepim/core/opimtemplatebase.h
@@ -1,223 +1,242 @@
/*
This file is part of the Opie Project
Copyright (C) Holger Freyther <zecke@handhelds.org>
=. Copyright (C) The Opie Team <opie-devel@handhelds.org>
.=l.
.>+-=
_;:, .> :=|. This program is free software; you can
.> <`_, > . <= redistribute it and/or modify it under
:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
.="- .-=="i, .._ License as published by the Free Software
- . .-<_> .<> Foundation; either version 2 of the License,
._= =} : or (at your option) any later version.
.%`+i> _;_.
.i_,=:_. -<s. This program is distributed in the hope that
+ . -:. = it will be useful, but WITHOUT ANY WARRANTY;
: .. .:, . . . without even the implied warranty of
=_ + =;=|` MERCHANTABILITY or FITNESS FOR A
_.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.= = ; Library General Public License for more
++= -. .` .: details.
: = ...= . :.=-
-. .:....=;==+<; You should have received a copy of the GNU
-_. . . )=. = Library General Public License along with
-- :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef OTEMPLATEBASE_H
#define OTEMPLATEBASE_H
/* OPIE */
#include <opie2/opimrecord.h>
#include <opie2/opimcache.h>
#include <opie2/opimoccurrence.h>
#include <opie2/opimbackendoccurrence.h>
/* QT */
#include <qarray.h>
#include <qdatetime.h>
namespace Opie {
class OPimBasePrivate;
/**
* This is the base class for all our Interfaces to the
* PIM Records. It is pointer based and can be used
* generically for all types of Records.
*
*/
struct OPimBase {
//@{
OPimBase();
virtual ~OPimBase();
//@}
//@{
/**
* return the rtti
*/
virtual int rtti() const = 0;
virtual OPimRecord* record()const = 0;
virtual OPimRecord* record(int uid)const = 0;
//@}
//@{
virtual bool add( const OPimRecord& ) = 0;
virtual bool add( const OPimRecord* ) = 0;
virtual bool remove( int uid ) = 0;
virtual bool remove( const OPimRecord& ) = 0;
//@}
//@{
virtual void clear() = 0;
virtual bool load() = 0;
virtual bool save() = 0;
//@}
//@{
virtual QArray<UID> records()const = 0;
+ //@}
/** Constants for query.
* Use this constants to set the query parameters.
* Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
* @see queryByExample()
*/
enum QuerySettings {
- WildCards = 0x0001, /** Use Wildcards */
- IgnoreCase = 0x0002, /** Ignore the Case */
- RegExp = 0x0004, /** Do a Regular Expression match */
- ExactMatch = 0x0008, /** It needs to exactly match */
- MatchOne = 0x0010, /** Only one Entry must match */
- DateDiff = 0x0020, /** Find all entries from today until given date */
- DateYear = 0x0040, /** The year matches */
- DateMonth = 0x0080, /** The month matches */
- DateDay = 0x0100, /** The day matches */
- LastItem = 0xffff /** the last possible name */
+ /** Use Wildcards */
+ WildCards = 0x0001,
+ /** Ignore the Case */
+ IgnoreCase = 0x0002,
+ /** Do a Regular Expression match */
+ RegExp = 0x0004,
+ /** It needs to exactly match */
+ ExactMatch = 0x0008,
+ /** Only one Entry must match */
+ MatchOne = 0x0010,
+ /** Find all entries from today until given date */
+ DateDiff = 0x0020,
+ /** The year matches */
+ DateYear = 0x0040,
+ /** The month matches */
+ DateMonth = 0x0080,
+ /** The day matches */
+ DateDay = 0x0100,
+ /** The last possible name matches */
+ LastItem = 0xffff
};
/**
* Common Attributes for the Sort Order
*/
enum SortOrderBase {
- SortSummary = 0, /** Sort by a Summary of the records */
- SortByCategory = 1, /** Sort by Category */
- SortByDate = 2, /** Sort by Date */
- SortCustom = 10, /** The First available sort number for the OPimAccessTemplates */
- LastSortOrderBase = 0xffff /** make this enum 16bit large */
+ /** Sort by a Summary of the records */
+ SortSummary = 0,
+ /** Sort by Category */
+ SortByCategory = 1,
+ /** Sort by Date */
+ SortByDate = 2,
+ /** The First available sort number for the OPimAccessTemplates */
+ SortCustom = 10,
+ /** make this enum 16bit large */
+ LastSortOrderBase = 0xffff
};
/**
- * Sort with the help of the \sa sorted function
- * a list of Items.
+ * Sort a list of Items with the help of the sorted() function.
* The Item you provide in SortOrder will be used
* for sorting.
*
- * @see sorted
+ * @see OPimAccessTemplate<>::sorted()
*/
enum SortFilterBase {
+ /** Do not filter anything. */
+ FilterOff = 0,
+ /** Use given Categories for filter */
FilterCategory = 1,
- FilterCustom = 1024,
+ /** The first available custom filter defined in the specialized frontends */
+ FilterCustom = 1024,
LastSortFilterBase = 0xffffffff
};
virtual UIDArray matchRegexpSimple( const QRegExp& r )const = 0;
virtual UIDArray queryByExampleSimple( const OPimRecord*, int settings,
const QDateTime& d = QDateTime() )const = 0;
virtual UIDArray sortedSimple( const UIDArray& uid, bool ascending,
int sortOrder, int sortFilter, int cat)const = 0;
virtual UIDArray sortedSimple( const UIDArray& uid, bool ascending,
int sortOrder, int sortFilter, const QArray<UID>& cats )const = 0;
virtual UIDArray sortedSimple( bool ascending, int sortOrder, int sortFilter, int cat)const = 0;
virtual UIDArray sortedSimple( bool ascending, int sortOrder, int sortFilter, const QArray<UID>& cats )const = 0;
virtual OPimOccurrence::List occurrences( const QDate& start, const QDate& end )const = 0;
virtual OPimOccurrence::List occurrences( const QDateTime& dt )const = 0;
//@}
protected:
OPimOccurrence::List convertOccurrenceFromBackend( const OPimBackendOccurrence::List& )const;
private:
OPimBasePrivate* d;
};
/**
* internal template base
* Attention: T needs to implement the copy c'tor!!!
*/
class OTemplateBasePrivate;
template <class T = OPimRecord>
class OTemplateBase : public OPimBase {
public:
/**
* The Direction for ReadAhead/ReadBehind which will
* be used by the backends to Cache Items in
* advance.
* For example if you know that you will access the
* next ten items you can give the backend a hint
* to read ahead or read before.
*/
enum CacheDirection {
Forward=0, /** Go forward when caching (++ to the index) */
Reverse /** Go backward when caching (-- to the index) */
};
//@{
OTemplateBase() {};
virtual ~OTemplateBase() {}
//@}
//@{
virtual T find( int uid )const = 0;
/**
* read ahead find
*/
virtual T find( int uid, const QArray<int>& items,
uint current, CacheDirection dir = Forward )const = 0;
//@}
//@{
/**
* Put element into Cache
*/
virtual void cache( const T& )const = 0;
virtual void setSaneCacheSize( int ) = 0;
OPimRecord* record()const;
OPimRecord* record(int uid )const;
static T* rec();
//@}
private:
OTemplateBasePrivate *d;
};
template <class T>
OPimRecord* OTemplateBase<T>::record()const {
T* t = new T;
return t;
}
template <class T>
OPimRecord* OTemplateBase<T>::record(int uid )const {
T t2 = find(uid );
T* t1 = new T(t2);
return t1;
}
template <class T>
T* OTemplateBase<T>::rec() {
return new T;
}
}
#endif
diff --git a/libopie2/opiepim/opiepim.pro b/libopie2/opiepim/opiepim.pro
index 47ec6da..992fb8b 100644
--- a/libopie2/opiepim/opiepim.pro
+++ b/libopie2/opiepim/opiepim.pro
@@ -1,26 +1,26 @@
TEMPLATE = lib
CONFIG += qt warn_on
DESTDIR = $(OPIEDIR)/lib
INTERFACES =
TARGET = opiepim2
-VERSION = 1.9.1
+VERSION = 1.8.6
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
LIBS += -lopiecore2
include ( $(OPIEDIR)/gen.pro )
include ( core/core.pro )
include ( backend/backends.pro )
include ( ui/ui.pro )
include ( private/private.pro )
PRECOMPILED_HEADER = stable_pch.h
!contains( platform, x11 ) {
include ( $(OPIEDIR)/include.pro )
}
contains( platform, x11 ) {
LIBS = -L$(OPIEDIR)/lib -Wl,-rpath,$(OPIEDIR)/lib
}