summaryrefslogtreecommitdiff
path: root/libopie
Side-by-side diff
Diffstat (limited to 'libopie') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/DESIGN6
-rw-r--r--libopie/pim/ocontactaccess.cpp4
-rw-r--r--libopie/pim/ocontactaccess.h49
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h35
-rw-r--r--libopie/pim/opimaccesstemplate.h12
-rw-r--r--libopie/pim/otodoaccessxml.cpp2
-rw-r--r--libopie/pim/otodoaccessxml.h2
7 files changed, 37 insertions, 73 deletions
diff --git a/libopie/pim/DESIGN b/libopie/pim/DESIGN
index 4def7b9..bd92b1b 100644
--- a/libopie/pim/DESIGN
+++ b/libopie/pim/DESIGN
@@ -1,62 +1,56 @@
Hija to the DESIGN of our OPIE PIM stuff
This design was firstly discussed in the train
from Frankfurt to Hannover between me (zecke ) and eilers.
We had a look at our pim implementation and the one from
trolltech and we looked what was missing.
GOALS:
- clean implementation
- share code
- ObjectOriented Design
- Scalable
- Integration into common solutions like STL and Qt
- Addition
- Ease of Use
GENERAL:
- use templates
- have a common base class for all Records OPimRecord
- use references instead of pointers
- make use of QShared internally memory consumption
We've a 'public' and 'private' part in our lib
OPimAccessTemplate is the public part. This will be used
by 3rd party developers to access the PIMs.
OPimAccessBackend is the backend. You could also call it
resource.
Both things need to be implemented for different kind of records.
By using templates we can make sure we share code and the reason
not to use simple inheretance is that we can specialise quite easy.
For example we have OTodoAccess : public OPimAccessTemplate<OTodo>;
the we would do
OTodoAccess::List list = otodoAccess.all();
OTodoAccess::List::Iterator it;
for( it = list.begin(); it != list.end(); ++it );
as you can see from here it just behaves like you expect from Qt or STL.
The kewlest thing is that List and List::Iterator is free to use if you
want to implement your own OPimAccessTemplate.
You just have to sub class it and voila you're done
Hope you enjoy using OPIE PIM
regards Holger 'zecke' Freyther
-Comment by Stefan Eilers:
-
-The opimaccesstemplate defines "SortOrder":
-I think sortorder is the wrong name for the meaning of it and
-it should be defined by the childs of opimaccesstemplate (every
-implementation may use different values for this..)
diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp
index b5f358b..e8c0a45 100644
--- a/libopie/pim/ocontactaccess.cpp
+++ b/libopie/pim/ocontactaccess.cpp
@@ -1,165 +1,167 @@
/*
* Class to manage the Contacts.
*
* Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
*
* =====================================================================
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* =====================================================================
* Info: This class could just work with a change in the header-file
* of the Contact class ! Therefore our libopie only compiles
* with our version of libqpe
* =====================================================================
* ToDo: XML-Backend: Automatic reload if something was changed...
*
*
* =====================================================================
* Version: $Id$
* =====================================================================
* History:
* $Log$
+ * Revision 1.4 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
* Revision 1.3 2002/10/07 17:34:24 eilers
* added OBackendFactory for advanced backend access
*
* Revision 1.2 2002/10/02 16:18:11 eilers
* debugged and seems to work almost perfectly ..
*
* Revision 1.1 2002/09/27 17:11:44 eilers
* Added API for accessing the Contact-Database ! It is compiling, but
* please do not expect that anything is working !
* I will debug that stuff in the next time ..
* Please read README_COMPILE for compiling !
*
*
*/
#include "ocontactaccess.h"
#include "obackendfactory.h"
#include <qasciidict.h>
#include <qdatetime.h>
#include <qfile.h>
#include <qregexp.h>
#include <qlist.h>
#include <qcopchannel_qws.h>
//#include <qpe/qcopenvelope_qws.h>
#include <qpe/global.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "ocontactaccessbackend_xml.h"
OContactAccess::OContactAccess ( const QString appname, const QString ,
OContactAccessBackend* end, bool autosync ):
OPimAccessTemplate<OContact>( end ),
m_changed ( false )
{
/* take care of the backend. If there is no one defined, we
* will use the XML-Backend as default (until we have a cute SQL-Backend..).
*/
if( end == 0 ) {
- // __asm__("int3");
qWarning ("Using BackendFactory !");
end = OBackendFactory<OContactAccessBackend>::Default( "contact", appname );
}
// Set backend locally and in template
m_backEnd = end;
OPimAccessTemplate<OContact>::setBackEnd (end);
/* Connect signal of external db change to function */
QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)),
this, SLOT(copMessage( const QCString &, const QByteArray &)) );
if ( autosync ){
QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)),
this, SLOT(copMessage( const QCString &, const QByteArray &)) );
}
}
OContactAccess::~OContactAccess ()
{
/* The user may forget to save the changed database, therefore try to
* do it for him..
*/
if ( m_changed )
save();
// delete m_backEnd; is done by template..
}
bool OContactAccess::load()
{
return ( m_backEnd->load() );
}
bool OContactAccess::save ()
{
/* If the database was changed externally, we could not save the
* Data. This will remove added items which is unacceptable !
* Therefore: Reload database and merge the data...
*/
if ( m_backEnd->wasChangedExternally() )
reload();
if ( m_changed ){
bool status = m_backEnd->save();
if ( !status ) return false;
m_changed = false;
/* Now tell everyone that new data is available.
*/
QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
}
return true;
}
const uint OContactAccess::querySettings()
{
return ( m_backEnd->querySettings() );
}
bool OContactAccess::hasQuerySettings ( int querySettings ) const
{
return ( m_backEnd->hasQuerySettings ( querySettings ) );
}
bool OContactAccess::add ( const OContact& newcontact )
{
m_changed = true;
return ( m_backEnd->add ( newcontact ) );
}
bool OContactAccess::replace ( const OContact& contact )
{
m_changed = true;
return ( m_backEnd->replace ( contact ) );
}
bool OContactAccess::remove ( const OContact& t )
{
m_changed = true;
return ( m_backEnd->remove ( t.uid() ) );
}
bool OContactAccess::remove ( int uid )
{
m_changed = true;
return ( m_backEnd->remove ( uid ) );
}
bool OContactAccess::wasChangedExternally()const
{
return ( m_backEnd->wasChangedExternally() );
}
diff --git a/libopie/pim/ocontactaccess.h b/libopie/pim/ocontactaccess.h
index 54f7f07..adc66cf 100644
--- a/libopie/pim/ocontactaccess.h
+++ b/libopie/pim/ocontactaccess.h
@@ -1,197 +1,168 @@
/*
* Class to manage the Contacts.
*
* Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
* Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
*
* =====================================================================
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any later
* version.
* =====================================================================
* ToDo: Define enum for query settings
* =====================================================================
* Version: $Id$
* =====================================================================
* History:
* $Log$
+ * Revision 1.2 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
* Revision 1.1 2002/09/27 17:11:44 eilers
* Added API for accessing the Contact-Database ! It is compiling, but
* please do not expect that anything is working !
* I will debug that stuff in the next time ..
* Please read README_COMPILE for compiling !
*
* =====================================================================
*/
#ifndef _OCONTACTACCESS_H
#define _OCONTACTACCESS_H
#include <qobject.h>
#include <qpe/qcopenvelope_qws.h>
#include <qvaluelist.h>
#include <qfileinfo.h>
#include "ocontact.h"
#include "ocontactaccessbackend.h"
#include "opimaccesstemplate.h"
/** Class to access the contacts database.
* This is just a frontend for the real database handling which is
* done by the backend.
*/
class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
{
Q_OBJECT
-
- /* class Iterator{
- friend OContactAccess;
- public:
- Iterator();
- Iterator ( const Iterator& copy );
-
- bool operator== ( const Iterator& it );
- bool operator!= ( const Iterator& it );
- Iterator& operator= ( const Iterator& it );
- Iterator& operator++ (); // prefix
- Iterator operator++ ( int ); // postfix
- Iterator& operator-- (); // prefix
- Iterator operator-- ( int ); // postfix
- Contact operator*() const;
- Contact operator->() const;
-
- Iterator begin();
- Iterator end();
-
- uint count() const;
-
- private:
- QValueList<int> m_uids;
- int m_cur_position;
- bool m_end_reached;
- OContactAccess *m_db;
-
- };
-
- */
-
public:
/** 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 OContactBackend
+ * @see OContactAccessBackend
*/
OContactAccess (const QString appname, const QString filename = 0l,
OContactAccessBackend* backend = 0l, bool handlesync = true);
~OContactAccess ();
/** 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()
- * - why not enum - zecke?
- * -> Had some implementation problems .. Will use enum soon ! .. (se)
*/
- static const int query_WildCards = 0x0001;
- static const int query_IgnoreCase = 0x0002;
- static const int query_RegExp = 0x0004;
- static const int query_ExactMatch = 0x0008;
+ enum QuerySettings {
+ WildCards = 0x0001,
+ IgnoreCase = 0x0002,
+ RegExp = 0x0004,
+ ExactMatch = 0x0008,
+ };
/** Return all possible settings.
* @return All settings provided by the current backend
* (i.e.: query_WildCards & query_IgnoreCase)
*/
const uint querySettings();
/** Check whether settings are correct.
* @return <i>true</i> if the given settings are correct and possible.
*/
bool hasQuerySettings ( int querySettings ) const;
/** Add Contact to database.
* @param newcontact The contact to add.
* @return <i>true</i> if added successfully.
*/
bool add (const OContact& newcontact);
/** Replace contact.
* Replaces given contact with contact with the user id <i>uid</i>.
* @param uid The user ID
* @param contact The new contact
* @return <i>true</i> if successful.
*/
bool replace ( const OContact& contact );
/** Remove contact.
* Removes contact with the user id <i>uid</i>.
* @param The contact to remove
* @return <i>true</i> if successful.
*/
bool remove ( const OContact& t );
/** Remove contact.
* Removes contact with the user id <i>uid</i>.
* @param The user id of the contact to remove
* @return <i>true</i> if successful.
*/
bool remove ( int uid );
/** Load Database *
*/
bool load();
/**
* if the resource was changed externally.
* You should use the signal instead of polling possible changes !
*/
bool wasChangedExternally()const;
/** 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.
*/
bool reload();
/** Save contacts database.
* Save is more a "commit". After calling this function, all changes are public available.
* @return true if successful
*/
bool save();
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 OContactAccess *which );
private:
// class OContactAccessPrivate;
// OContactAccessPrivate* d;
OContactAccessBackend *m_backEnd;
bool m_loading:1;
bool m_changed;
private slots:
void copMessage( const QCString &msg, const QByteArray &data );
};
#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 97ef40f..50ea329 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -1,359 +1,362 @@
/*
* XML Backend for the OPIE-Contact Database.
*
* Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
*
* =====================================================================
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* =====================================================================
* ToDo: XML-Backend: Automatic reload if something was changed...
*
*
* =====================================================================
* Version: $Id$
* =====================================================================
* History:
* $Log$
+ * Revision 1.3 2002/10/14 16:21:54 eilers
+ * Some minor interface updates
+ *
* Revision 1.2 2002/10/07 17:34:24 eilers
* added OBackendFactory for advanced backend access
*
* Revision 1.1 2002/09/27 17:11:44 eilers
* Added API for accessing the Contact-Database ! It is compiling, but
* please do not expect that anything is working !
* I will debug that stuff in the next time ..
* Please read README_COMPILE for compiling !
*
*
*/
#ifndef _OContactAccessBackend_XML_
#define _OContactAccessBackend_XML_
#include <qasciidict.h>
#include <qdatetime.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qregexp.h>
#include <qarray.h>
#include <qpe/global.h>
#include <opie/xmltree.h>
#include "ocontactaccessbackend.h"
#include "ocontactaccess.h"
#include <stdlib.h>
#include <errno.h>
using namespace Opie;
/* the default xml implementation */
class OContactAccessBackend_XML : public OContactAccessBackend {
public:
OContactAccessBackend_XML ( QString appname, QString filename = 0l )
{
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 save() {
QString strNewFile = m_fileName + ".new";
QFile f( strNewFile );
if ( !f.open( IO_WriteOnly|IO_Raw ) )
return false;
int total_written;
QString out;
out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
" <Groups>\n"
" </Groups>\n"
" <Contacts>\n";
//QValueList<Contact>::iterator it;
QValueListConstIterator<OContact> it;
for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
out += "<Contact ";
(*it).save( out );
out += "/>\n";
QCString cstr = out.utf8();
total_written = f.writeBlock( cstr.data(), cstr.length() );
if ( total_written != int(cstr.length()) ) {
f.close();
QFile::remove( strNewFile );
return false;
}
out = "";
}
out += " </Contacts>\n</AddressBook>\n";
QCString 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 ) {
qWarning( "problem renaming file %s to %s, errno: %d",
strNewFile.latin1(), m_journalName.latin1(), errno );
// remove the tmp file...
QFile::remove( strNewFile );
}
/* The journalfile should be removed now... */
removeJournal();
return true;
}
bool load () {
m_contactList.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 clear () {
m_contactList.clear();
}
bool wasChangedExternally()
{
QFileInfo fi( m_fileName );
QDateTime lastmod = fi.lastModified ();
return (lastmod != m_readtime);
}
QArray<int> allRecords() const {
QArray<int> uid_list( m_contactList.count() );
uint counter = 0;
QValueListConstIterator<OContact> it;
for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
uid_list[counter++] = (*it).uid();
}
return ( uid_list );
}
OContact find ( int uid ) const
{
bool found = false;
OContact foundContact; //Create empty contact
QValueListConstIterator<OContact> it;
for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
if ((*it).uid() == uid){
found = true;
break;
}
}
if ( found ){
foundContact = *it;
}
return ( foundContact );
}
QArray<int> queryByExample ( const OContact &query, int settings ){
QArray<int> m_currentQuery( m_contactList.count() );
QValueListConstIterator<OContact> it;
uint arraycounter = 0;
for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
/* Search all fields and compare them with query object. Store them into list
* if all fields matches.
*/
bool allcorrect = true;
for ( int i = 0; i < Qtopia::rid; i++ ) {
/* Just compare fields which are not empty in the query object */
if ( !query.field(i).isEmpty() ){
- switch ( settings & ~OContactAccess::query_IgnoreCase ){
- case OContactAccess::query_RegExp:{
+ switch ( settings & ~OContactAccess::IgnoreCase ){
+ case OContactAccess::RegExp:{
QRegExp expr ( query.field(i),
- !(settings & OContactAccess::query_IgnoreCase),
+ !(settings & OContactAccess::IgnoreCase),
false );
if ( expr.find ( (*it).field(i), 0 ) == -1 )
allcorrect = false;
}
break;
- case OContactAccess::query_WildCards:{
+ case OContactAccess::WildCards:{
QRegExp expr ( query.field(i),
- !(settings & OContactAccess::query_IgnoreCase),
+ !(settings & OContactAccess::IgnoreCase),
true );
if ( expr.find ( (*it).field(i), 0 ) == -1 )
allcorrect = false;
}
break;
- case OContactAccess::query_ExactMatch:{
- if (settings & OContactAccess::query_IgnoreCase){
+ case OContactAccess::ExactMatch:{
+ if (settings & OContactAccess::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;
}
const uint querySettings()
{
- return ( OContactAccess::query_WildCards
- & OContactAccess::query_IgnoreCase
- & OContactAccess::query_RegExp
- & OContactAccess::query_ExactMatch );
+ return ( OContactAccess::WildCards
+ & OContactAccess::IgnoreCase
+ & OContactAccess::RegExp
+ & OContactAccess::ExactMatch );
}
bool hasQuerySettings (uint querySettings) const
{
- /* OContactAccess::query_IgnoreCase may be added with one
+ /* OContactAccess::IgnoreCase may be added with one
* of the other settings, but never used alone.
* The other settings are just valid alone...
*/
- switch ( querySettings & ~OContactAccess::query_IgnoreCase ){
- case OContactAccess::query_RegExp:
+ switch ( querySettings & ~OContactAccess::IgnoreCase ){
+ case OContactAccess::RegExp:
return ( true );
- case OContactAccess::query_WildCards:
+ case OContactAccess::WildCards:
return ( true );
- case OContactAccess::query_ExactMatch:
+ case OContactAccess::ExactMatch:
return ( true );
default:
return ( false );
}
}
bool add ( const OContact &newcontact )
{
//qWarning("odefaultbackend: ACTION::ADD");
updateJournal (newcontact, OContact::ACTION_ADD);
addContact_p( newcontact );
return true;
}
bool replace ( const OContact &contact )
{
bool found = false;
QValueListIterator<OContact> it;
for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
if ( (*it).uid() == contact.uid() ){
found = true;
break;
}
}
if (found) {
updateJournal (contact, OContact::ACTION_REPLACE);
m_contactList.remove (it);
m_contactList.append (contact);
return true;
} else
return false;
}
bool remove ( int uid )
{
bool found = false;
QValueListIterator<OContact> it;
for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
if ((*it).uid() == uid){
found = true;
break;
}
}
if (found) {
updateJournal ( *it, OContact::ACTION_REMOVE);
m_contactList.remove (it);
return true;
} else
return false;
}
bool reload(){
/* Reload is the same as load in this implementation */
return ( load() );
}
private:
void addContact_p( const OContact &newcontact ){
m_contactList.append (newcontact);
}
/* This function loads the xml-database and the journalfile */
bool 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;
OContact::journal_action action = OContact::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) );
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index a0d8f63..3e1f393 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -1,167 +1,161 @@
#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
#define OPIE_PIM_ACCESS_TEMPLATE_H
#include <qarray.h>
#include <opie/opimrecord.h>
#include <opie/opimaccessbackend.h>
#include <opie/orecordlist.h>
#include "opimcache.h"
#include "otemplatebase.h"
/**
* 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 plugins
*/
template <class T = OPimRecord >
class OPimAccessTemplate : public OTemplateBase<T> {
public:
typedef ORecordList<T> List;
typedef OPimAccessBackend<T> BackEnd;
typedef OPimCache<T> Cache;
/**
- * our sort order
- * should be safe explaining
- */
- enum SortOrder { WildCards = 0, IgnoreCase = 1,
- RegExp = 2, ExactMatch = 4 };
-
- /**
* c'tor BackEnd
*/
OPimAccessTemplate( BackEnd* end);
virtual ~OPimAccessTemplate();
/**
* load from the backend
*/
virtual bool load();
/**
* reload from the backend
*/
virtual bool reload();
/**
* save to the backend
*/
virtual bool save();
/**
* if the resource was changed externally
*/
bool wasChangedExternally()const;
/**
* return a List of records
* you can iterate over them
*/
virtual List allRecords()const;
/**
- * queryByExample
+ * queryByExample)
+ * @see otodoaccess, ocontactaccess
*/
- virtual List queryByExample( const T& t, int sortOrder );
+ virtual List queryByExample( const T& t, int querySettings );
/**
* find the OPimRecord uid
*/
virtual T find( int uid )const;
/**
* read ahead cache find method ;)
*/
virtual T find( int uid, const QArray<int>&,
uint current, CacheDirection dir = Forward )const;
/* invalidate cache here */
/**
* clears the backend and invalidates the backend
*/
virtual void clear() ;
/**
* add T to the backend
*/
virtual bool add( const T& t ) ;
/* only the uid matters */
/**
* remove T from the backend
*/
virtual bool remove( const T& t );
/**
* remove the OPimRecord with uid
*/
virtual bool remove( int uid );
/**
* replace T from backend
*/
virtual bool replace( const T& t) ;
/**
* @internal
*/
void cache( const T& )const;
void setSaneCacheSize( int );
protected:
/**
* invalidate the cache
*/
void invalidateCache();
void setBackEnd( BackEnd* end );
/**
* returns the backend
*/
BackEnd* backEnd();
BackEnd* m_backEnd;
Cache m_cache;
};
template <class T>
OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
: OTemplateBase<T>(), m_backEnd( end )
{
if (end )
end->setFrontend( this );
}
template <class T>
OPimAccessTemplate<T>::~OPimAccessTemplate() {
qWarning("~OPimAccessTemplate<T>");
delete m_backEnd;
}
template <class T>
bool OPimAccessTemplate<T>::load() {
invalidateCache();
return m_backEnd->load();
}
template <class T>
bool OPimAccessTemplate<T>::reload() {
return m_backEnd->reload();
}
template <class T>
bool OPimAccessTemplate<T>::save() {
return m_backEnd->save();
}
template <class T>
OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
QArray<int> ints = m_backEnd->allRecords();
List lis(ints, this );
return lis;
}
template <class T>
OPimAccessTemplate<T>::List
OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index f3b0783..3b4cab2 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -94,193 +94,193 @@ bool OTodoAccessXML::load() {
++j;
}
if ( i == j ) {
// empty value
i = j + 1;
continue;
}
QCString value( dt+i, j-i+1 );
i = j + 1;
QString str = (haveUtf ? QString::fromUtf8( value )
: QString::fromLatin1( value ) );
if ( haveEnt )
str = Qtopia::plainString( str );
/*
* add key + value
*/
todo( &dict, ev, attr, str );
}
/*
* now add it
*/
m_events.insert(ev.uid(), ev );
}
qWarning("counts %d", m_events.count() );
return true;
}
bool OTodoAccessXML::reload() {
return load();
}
bool OTodoAccessXML::save() {
// qWarning("saving");
if (!m_opened || !m_changed ) {
// qWarning("not saving");
return true;
}
QString strNewFile = m_file + ".new";
QFile f( strNewFile );
if (!f.open( IO_WriteOnly|IO_Raw ) )
return false;
int written;
QString out;
out = "<!DOCTYPE Tasks>\n<Tasks>\n";
// for all todos
QMap<int, OTodo>::Iterator it;
for (it = m_events.begin(); it != m_events.end(); ++it ) {
out+= "<Task " + toString( (*it) ) + " />\n";
QCString cstr = out.utf8();
written = f.writeBlock( cstr.data(), cstr.length() );
/* less written then we wanted */
if ( written != (int)cstr.length() ) {
f.close();
QFile::remove( strNewFile );
return false;
}
out = QString::null;
}
out += "</Tasks>";
QCString cstr = out.utf8();
written = f.writeBlock( cstr.data(), cstr.length() );
if ( written != (int)cstr.length() ) {
f.close();
QFile::remove( strNewFile );
return false;
}
/* flush before renaming */
f.close();
if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
// qWarning("error renaming");
QFile::remove( strNewFile );
}
m_changed = false;
return true;
}
QArray<int> OTodoAccessXML::allRecords()const {
QArray<int> ids( m_events.count() );
QMap<int, OTodo>::ConstIterator it;
int i = 0;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
ids[i] = it.key();
i++;
}
return ids;
}
-QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int sort ) {
+QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
QArray<int> ids(0);
return ids;
}
OTodo OTodoAccessXML::find( int uid )const {
OTodo todo;
todo.setUid( 0 ); // isEmpty()
QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
if ( it != m_events.end() )
todo = it.data();
return todo;
}
void OTodoAccessXML::clear() {
if (m_opened )
m_changed = true;
m_events.clear();
}
bool OTodoAccessXML::add( const OTodo& todo ) {
// qWarning("add");
m_changed = true;
m_events.insert( todo.uid(), todo );
return true;
}
bool OTodoAccessXML::remove( int uid ) {
m_changed = true;
m_events.remove( uid );
return true;
}
bool OTodoAccessXML::replace( const OTodo& todo) {
m_changed = true;
m_events.replace( todo.uid(), todo );
return true;
}
QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
const QDate& end,
bool includeNoDates ) {
QArray<int> ids( m_events.count() );
QMap<int, OTodo>::Iterator it;
int i = 0;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
if ( !it.data().hasDueDate() ) {
if ( includeNoDates ) {
ids[i] = it.key();
i++;
}
}else if ( it.data().dueDate() >= start &&
it.data().dueDate() <= end ) {
ids[i] = it.key();
i++;
}
}
ids.resize( i );
return ids;
}
QArray<int> OTodoAccessXML::overDue() {
QArray<int> ids( m_events.count() );
int i = 0;
QMap<int, OTodo>::Iterator it;
for ( it = m_events.begin(); it != m_events.end(); ++it ) {
if ( it.data().isOverdue() ) {
ids[i] = it.key();
i++;
}
}
ids.resize( i );
return ids;
}
/* private */
void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
const QCString& attr, const QString& val) {
// qWarning("parse to do from XMLElement" );
int *find=0;
find = (*dict)[ attr.data() ];
if (!find ) {
// qWarning("Unknown option" + it.key() );
ev.setCustomField( attr, val );
return;
}
switch( *find ) {
case OTodo::Uid:
ev.setUid( val.toInt() );
break;
case OTodo::Category:
ev.setCategories( ev.idsFromString( val ) );
break;
diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h
index 1e7e371..dc41c32 100644
--- a/libopie/pim/otodoaccessxml.h
+++ b/libopie/pim/otodoaccessxml.h
@@ -1,56 +1,56 @@
#ifndef OPIE_TODO_ACCESS_XML_H
#define OPIE_TODO_ACCESS_XML_H
#include <qasciidict.h>
#include <qmap.h>
#include "otodoaccessbackend.h"
namespace Opie {
class XMLElement;
};
class OTodoAccessXML : public OTodoAccessBackend {
public:
/**
* fileName if Empty we will use the default path
*/
OTodoAccessXML( const QString& appName,
const QString& fileName = QString::null );
~OTodoAccessXML();
bool load();
bool reload();
bool save();
QArray<int> allRecords()const;
- QArray<int> queryByExample( const OTodo&, int sort );
+ QArray<int> queryByExample( const OTodo&, int querysettings );
OTodo find( int uid )const;
void clear();
bool add( const OTodo& );
bool remove( int uid );
bool replace( const OTodo& );
/* our functions */
QArray<int> effectiveToDos( const QDate& start,
const QDate& end,
bool includeNoDates );
QArray<int> overDue();
QArray<int> sorted( bool asc, int sortOrder,
int sortFilter, int cat );
private:
void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
QString toString( const OTodo& )const;
QString toString( const QArray<int>& ints ) const;
QMap<int, OTodo> m_events;
QString m_file;
QString m_app;
bool m_opened : 1;
bool m_changed : 1;
class OTodoAccessXMLPrivate;
OTodoAccessXMLPrivate* d;
int m_year, m_month, m_day;
};
#endif