author | eilers <eilers> | 2002-10-07 17:34:24 (UTC) |
---|---|---|
committer | eilers <eilers> | 2002-10-07 17:34:24 (UTC) |
commit | 0981af024243b314b45ddaf3ebee08bc184f06e2 (patch) (side-by-side diff) | |
tree | 578c3057b922911010bfbddc373476e3ae3b32f6 | |
parent | ab5b7ba61580bfd3aa20297e67bd9fa6b6c90d41 (diff) | |
download | opie-0981af024243b314b45ddaf3ebee08bc184f06e2.zip opie-0981af024243b314b45ddaf3ebee08bc184f06e2.tar.gz opie-0981af024243b314b45ddaf3ebee08bc184f06e2.tar.bz2 |
added OBackendFactory for advanced backend access
-rw-r--r-- | libopie/pim/obackendfactory.h | 88 | ||||
-rw-r--r-- | libopie/pim/ocontactaccess.cpp | 10 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend_xml.h | 10 | ||||
-rw-r--r-- | libopie2/opiepim/backend/obackendfactory.h | 88 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_xml.h | 10 | ||||
-rw-r--r-- | libopie2/opiepim/core/ocontactaccess.cpp | 10 |
8 files changed, 220 insertions, 4 deletions
diff --git a/libopie/pim/obackendfactory.h b/libopie/pim/obackendfactory.h new file mode 100644 index 0000000..599fbf2 --- a/dev/null +++ b/libopie/pim/obackendfactory.h @@ -0,0 +1,88 @@ +/* + * Class to manage Backends. + * + * 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: Use plugins + * ===================================================================== + * Version: $Id$ + * ===================================================================== + * History: + * $Log$ + * Revision 1.1 2002/10/07 17:35:01 eilers + * added OBackendFactory for advanced backend access + * + * + * ===================================================================== + */ +#ifndef __OPIE_BACKENDFACTORY_H_ +#define __OPIE_BACKENDFACTORY_H_ + +#include <qstring.h> +#include <qasciidict.h> +#include <qpe/config.h> + +#include "otodoaccessxml.h" +#include "ocontactaccessbackend_xml.h" +#include "otodoaccesssql.h" + + +template<class T> +class OBackendFactory +{ + public: + OBackendFactory() {}; + + enum BACKENDS { + TODO, + CONTACT, + DATE + }; + + static T* Default( const QString backendName, const QString& appName ){ + + + Config config( "pimaccess" ); + config.setGroup ( backendName ); + QString backend = config.readEntry( "usebackend" ); + + QAsciiDict<int> dict ( 3 ); + dict.setAutoDelete ( TRUE ); + + dict.insert( "todo", new int (TODO) ); + dict.insert( "contact", new int (CONTACT) ); + + qWarning ("TODO is: %d", TODO); + qWarning ("CONTACT is: %d", CONTACT); + + switch ( *dict.take( backendName ) ){ + case TODO: + if ( backend == "sql" ) + return (T*) new OTodoAccessBackendSQL(""); + + return (T*) new OTodoAccessXML( appName ); + case CONTACT: + if ( backend == "sql" ) + qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); + + return (T*) new OContactAccessBackend_XML( appName ); + case DATE: + qWarning ("OBackendFactory:: DATE-Backend not implemented!"); + return NULL; + default: + return NULL; + } + + + } +}; + + +#endif diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp index 8a8ff08..b5f358b 100644 --- a/libopie/pim/ocontactaccess.cpp +++ b/libopie/pim/ocontactaccess.cpp @@ -1,180 +1,186 @@ /* * 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.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 filename, +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 ) { - end = new OContactAccessBackend_XML( appname, filename ); + // __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() ); } bool OContactAccess::reload() { return ( m_backEnd->reload() ); } void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) { if ( msg == "addressbookUpdated()" ){ qWarning ("OContactAccess: Received addressbokUpdated()"); emit signalChanged ( this ); } else if ( msg == "flush()" ) { qWarning ("OContactAccess: Received flush()"); save (); } else if ( msg == "reload()" ) { qWarning ("OContactAccess: Received reload()"); reload (); emit signalChanged ( this ); } } diff --git a/libopie/pim/ocontactaccessbackend.h b/libopie/pim/ocontactaccessbackend.h index 9469bbc..a651477 100644 --- a/libopie/pim/ocontactaccessbackend.h +++ b/libopie/pim/ocontactaccessbackend.h @@ -1,70 +1,74 @@ /** * 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) * * ===================================================================== * 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/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_H_ #define _OCONTACTACCESSBACKEND_H_ +#include "ocontact.h" #include "opimaccessbackend.h" class OContactAccessBackend: public OPimAccessBackend<OContact> { public: OContactAccessBackend() {} virtual ~OContactAccessBackend() {} /** 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; /** Check whether settings are correct. * @return <i>true</i> if the given settings are correct and possible. */ virtual bool hasQuerySettings (uint querySettings) const = 0; }; #endif diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h index 2cdb45b..97ef40f 100644 --- a/libopie/pim/ocontactaccessbackend_xml.h +++ b/libopie/pim/ocontactaccessbackend_xml.h @@ -1,550 +1,560 @@ /* * 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.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:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::query_IgnoreCase), false ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::query_WildCards:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::query_IgnoreCase), true ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::query_ExactMatch:{ if (settings & OContactAccess::query_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 ); } bool hasQuerySettings (uint querySettings) const { /* OContactAccess::query_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: return ( true ); case OContactAccess::query_WildCards: return ( true ); case OContactAccess::query_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) ); 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) ); dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); dict.insert( "Department", new int(Qtopia::Department) ); dict.insert( "Office", new int(Qtopia::Office) ); dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); dict.insert( "Profession", new int(Qtopia::Profession) ); dict.insert( "Assistant", new int(Qtopia::Assistant) ); dict.insert( "Manager", new int(Qtopia::Manager) ); dict.insert( "Spouse", new int(Qtopia::Spouse) ); dict.insert( "Children", new int(Qtopia::Children) ); dict.insert( "Gender", new int(Qtopia::Gender) ); dict.insert( "Birthday", new int(Qtopia::Birthday) ); dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); dict.insert( "Nickname", new int(Qtopia::Nickname) ); dict.insert( "Notes", new int(Qtopia::Notes) ); dict.insert( "action", new int(JOURNALACTION) ); dict.insert( "actionrow", new int(JOURNALROW) ); //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); XMLElement *root = XMLElement::load( filename ); if(root != 0l ){ // start parsing /* Parse all XML-Elements and put the data into the * Contact-Class */ XMLElement *element = root->firstChild(); //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); element = element->firstChild(); /* Search Tag "Contacts" which is the parent of all Contacts */ while( element && !isJournal ){ if( element->tagName() != QString::fromLatin1("Contacts") ){ //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", // element->tagName().latin1()); element = element->nextChild(); } else { element = element->firstChild(); break; } } /* Parse all Contacts and ignore unknown tags */ while( element ){ if( element->tagName() != QString::fromLatin1("Contact") ){ //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", // element->tagName().latin1()); element = element->nextChild(); continue; } /* Found alement with tagname "contact", now parse and store all * attributes contained */ //qWarning("OContactDefBack::load element tagName() : %s", // element->tagName().latin1() ); QString dummy; foundAction = false; XMLElement::AttributeMap aMap = element->attributes(); XMLElement::AttributeMap::Iterator it; contactMap.clear(); customMap.clear(); for( it = aMap.begin(); it != aMap.end(); ++it ){ // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); int *find = dict[ it.key() ]; /* Unknown attributes will be stored as "Custom" elements */ if ( !find ) { qWarning("Attribute %s not known.", it.key().latin1()); //contact.setCustomField(it.key(), it.data()); customMap.insert( it.key(), it.data() ); continue; } /* Check if special conversion is needed and add attribute * into Contact class */ switch( *find ) { /* case Qtopia::AddressUid: contact.setUid( it.data().toInt() ); break; case Qtopia::AddressCategory: contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); break; */ case JOURNALACTION: action = OContact::journal_action(it.data().toInt()); foundAction = true; qWarning ("ODefBack(journal)::ACTION found: %d", action); break; case JOURNALROW: journalKey = it.data().toInt(); break; default: // no conversion needed add them to the map contactMap.insert( *find, it.data() ); break; } } /* now generate the Contact contact */ OContact contact( contactMap ); for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { contact.setCustomField( customIt.key(), customIt.data() ); } if (foundAction){ foundAction = false; switch ( action ) { case OContact::ACTION_ADD: addContact_p (contact); break; case OContact::ACTION_REMOVE: if ( !remove (contact.uid()) ) qWarning ("ODefBack(journal)::Unable to remove uid: %d", contact.uid() ); break; case OContact::ACTION_REPLACE: if ( !replace ( contact ) ) qWarning ("ODefBack(journal)::Unable to replace uid: %d", contact.uid() ); break; default: qWarning ("Unknown action: ignored !"); break; } }else{ /* Add contact to list */ addContact_p (contact); } /* Move to next element */ element = element->nextChild(); } }else { qWarning("ODefBack::could not load"); } delete root; qWarning("returning from loading" ); return true; } void updateJournal( const OContact& cnt, OContact::journal_action action ) { QFile f( m_journalName ); bool created = !f.exists(); if ( !f.open(IO_WriteOnly|IO_Append) ) return; QString buf; QCString str; // if the file was created, we have to set the Tag "<CONTACTS>" to // get a XML-File which is readable by our parser. // This is just a cheat, but better than rewrite the parser. if ( created ){ buf = "<Contacts>"; QCString cstr = buf.utf8(); f.writeBlock( cstr.data(), cstr.length() ); } buf = "<Contact "; cnt.save( buf ); buf += " action=\"" + QString::number( (int)action ) + "\" "; buf += "/>\n"; QCString cstr = buf.utf8(); f.writeBlock( cstr.data(), cstr.length() ); } void removeJournal() { QFile f ( m_journalName ); if ( f.exists() ) f.remove(); } protected: QString m_journalName; QString m_fileName; QString m_appName; QValueList<OContact> m_contactList; QDateTime m_readtime; }; #endif diff --git a/libopie2/opiepim/backend/obackendfactory.h b/libopie2/opiepim/backend/obackendfactory.h new file mode 100644 index 0000000..599fbf2 --- a/dev/null +++ b/libopie2/opiepim/backend/obackendfactory.h @@ -0,0 +1,88 @@ +/* + * Class to manage Backends. + * + * 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: Use plugins + * ===================================================================== + * Version: $Id$ + * ===================================================================== + * History: + * $Log$ + * Revision 1.1 2002/10/07 17:35:01 eilers + * added OBackendFactory for advanced backend access + * + * + * ===================================================================== + */ +#ifndef __OPIE_BACKENDFACTORY_H_ +#define __OPIE_BACKENDFACTORY_H_ + +#include <qstring.h> +#include <qasciidict.h> +#include <qpe/config.h> + +#include "otodoaccessxml.h" +#include "ocontactaccessbackend_xml.h" +#include "otodoaccesssql.h" + + +template<class T> +class OBackendFactory +{ + public: + OBackendFactory() {}; + + enum BACKENDS { + TODO, + CONTACT, + DATE + }; + + static T* Default( const QString backendName, const QString& appName ){ + + + Config config( "pimaccess" ); + config.setGroup ( backendName ); + QString backend = config.readEntry( "usebackend" ); + + QAsciiDict<int> dict ( 3 ); + dict.setAutoDelete ( TRUE ); + + dict.insert( "todo", new int (TODO) ); + dict.insert( "contact", new int (CONTACT) ); + + qWarning ("TODO is: %d", TODO); + qWarning ("CONTACT is: %d", CONTACT); + + switch ( *dict.take( backendName ) ){ + case TODO: + if ( backend == "sql" ) + return (T*) new OTodoAccessBackendSQL(""); + + return (T*) new OTodoAccessXML( appName ); + case CONTACT: + if ( backend == "sql" ) + qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); + + return (T*) new OContactAccessBackend_XML( appName ); + case DATE: + qWarning ("OBackendFactory:: DATE-Backend not implemented!"); + return NULL; + default: + return NULL; + } + + + } +}; + + +#endif diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.h b/libopie2/opiepim/backend/ocontactaccessbackend.h index 9469bbc..a651477 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend.h +++ b/libopie2/opiepim/backend/ocontactaccessbackend.h @@ -1,70 +1,74 @@ /** * 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) * * ===================================================================== * 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/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_H_ #define _OCONTACTACCESSBACKEND_H_ +#include "ocontact.h" #include "opimaccessbackend.h" class OContactAccessBackend: public OPimAccessBackend<OContact> { public: OContactAccessBackend() {} virtual ~OContactAccessBackend() {} /** 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; /** Check whether settings are correct. * @return <i>true</i> if the given settings are correct and possible. */ virtual bool hasQuerySettings (uint querySettings) const = 0; }; #endif diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h index 2cdb45b..97ef40f 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h +++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h @@ -1,550 +1,560 @@ /* * 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.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:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::query_IgnoreCase), false ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::query_WildCards:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::query_IgnoreCase), true ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::query_ExactMatch:{ if (settings & OContactAccess::query_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 ); } bool hasQuerySettings (uint querySettings) const { /* OContactAccess::query_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: return ( true ); case OContactAccess::query_WildCards: return ( true ); case OContactAccess::query_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) ); 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) ); dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); dict.insert( "Department", new int(Qtopia::Department) ); dict.insert( "Office", new int(Qtopia::Office) ); dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); dict.insert( "Profession", new int(Qtopia::Profession) ); dict.insert( "Assistant", new int(Qtopia::Assistant) ); dict.insert( "Manager", new int(Qtopia::Manager) ); dict.insert( "Spouse", new int(Qtopia::Spouse) ); dict.insert( "Children", new int(Qtopia::Children) ); dict.insert( "Gender", new int(Qtopia::Gender) ); dict.insert( "Birthday", new int(Qtopia::Birthday) ); dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); dict.insert( "Nickname", new int(Qtopia::Nickname) ); dict.insert( "Notes", new int(Qtopia::Notes) ); dict.insert( "action", new int(JOURNALACTION) ); dict.insert( "actionrow", new int(JOURNALROW) ); //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); XMLElement *root = XMLElement::load( filename ); if(root != 0l ){ // start parsing /* Parse all XML-Elements and put the data into the * Contact-Class */ XMLElement *element = root->firstChild(); //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); element = element->firstChild(); /* Search Tag "Contacts" which is the parent of all Contacts */ while( element && !isJournal ){ if( element->tagName() != QString::fromLatin1("Contacts") ){ //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", // element->tagName().latin1()); element = element->nextChild(); } else { element = element->firstChild(); break; } } /* Parse all Contacts and ignore unknown tags */ while( element ){ if( element->tagName() != QString::fromLatin1("Contact") ){ //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", // element->tagName().latin1()); element = element->nextChild(); continue; } /* Found alement with tagname "contact", now parse and store all * attributes contained */ //qWarning("OContactDefBack::load element tagName() : %s", // element->tagName().latin1() ); QString dummy; foundAction = false; XMLElement::AttributeMap aMap = element->attributes(); XMLElement::AttributeMap::Iterator it; contactMap.clear(); customMap.clear(); for( it = aMap.begin(); it != aMap.end(); ++it ){ // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); int *find = dict[ it.key() ]; /* Unknown attributes will be stored as "Custom" elements */ if ( !find ) { qWarning("Attribute %s not known.", it.key().latin1()); //contact.setCustomField(it.key(), it.data()); customMap.insert( it.key(), it.data() ); continue; } /* Check if special conversion is needed and add attribute * into Contact class */ switch( *find ) { /* case Qtopia::AddressUid: contact.setUid( it.data().toInt() ); break; case Qtopia::AddressCategory: contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); break; */ case JOURNALACTION: action = OContact::journal_action(it.data().toInt()); foundAction = true; qWarning ("ODefBack(journal)::ACTION found: %d", action); break; case JOURNALROW: journalKey = it.data().toInt(); break; default: // no conversion needed add them to the map contactMap.insert( *find, it.data() ); break; } } /* now generate the Contact contact */ OContact contact( contactMap ); for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { contact.setCustomField( customIt.key(), customIt.data() ); } if (foundAction){ foundAction = false; switch ( action ) { case OContact::ACTION_ADD: addContact_p (contact); break; case OContact::ACTION_REMOVE: if ( !remove (contact.uid()) ) qWarning ("ODefBack(journal)::Unable to remove uid: %d", contact.uid() ); break; case OContact::ACTION_REPLACE: if ( !replace ( contact ) ) qWarning ("ODefBack(journal)::Unable to replace uid: %d", contact.uid() ); break; default: qWarning ("Unknown action: ignored !"); break; } }else{ /* Add contact to list */ addContact_p (contact); } /* Move to next element */ element = element->nextChild(); } }else { qWarning("ODefBack::could not load"); } delete root; qWarning("returning from loading" ); return true; } void updateJournal( const OContact& cnt, OContact::journal_action action ) { QFile f( m_journalName ); bool created = !f.exists(); if ( !f.open(IO_WriteOnly|IO_Append) ) return; QString buf; QCString str; // if the file was created, we have to set the Tag "<CONTACTS>" to // get a XML-File which is readable by our parser. // This is just a cheat, but better than rewrite the parser. if ( created ){ buf = "<Contacts>"; QCString cstr = buf.utf8(); f.writeBlock( cstr.data(), cstr.length() ); } buf = "<Contact "; cnt.save( buf ); buf += " action=\"" + QString::number( (int)action ) + "\" "; buf += "/>\n"; QCString cstr = buf.utf8(); f.writeBlock( cstr.data(), cstr.length() ); } void removeJournal() { QFile f ( m_journalName ); if ( f.exists() ) f.remove(); } protected: QString m_journalName; QString m_fileName; QString m_appName; QValueList<OContact> m_contactList; QDateTime m_readtime; }; #endif diff --git a/libopie2/opiepim/core/ocontactaccess.cpp b/libopie2/opiepim/core/ocontactaccess.cpp index 8a8ff08..b5f358b 100644 --- a/libopie2/opiepim/core/ocontactaccess.cpp +++ b/libopie2/opiepim/core/ocontactaccess.cpp @@ -1,180 +1,186 @@ /* * 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.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 filename, +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 ) { - end = new OContactAccessBackend_XML( appname, filename ); + // __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() ); } bool OContactAccess::reload() { return ( m_backEnd->reload() ); } void OContactAccess::copMessage( const QCString &msg, const QByteArray & ) { if ( msg == "addressbookUpdated()" ){ qWarning ("OContactAccess: Received addressbokUpdated()"); emit signalChanged ( this ); } else if ( msg == "flush()" ) { qWarning ("OContactAccess: Received flush()"); save (); } else if ( msg == "reload()" ) { qWarning ("OContactAccess: Received reload()"); reload (); emit signalChanged ( this ); } } |