-rw-r--r-- | libopie/pim/ocontact.h | 4 | ||||
-rw-r--r-- | libopie/pim/ocontactaccess.cpp | 8 | ||||
-rw-r--r-- | libopie/pim/ocontactaccess.h | 8 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend.h | 7 | ||||
-rw-r--r-- | libopie/pim/ocontactaccessbackend_xml.h | 20 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend.h | 7 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_xml.h | 20 | ||||
-rw-r--r-- | libopie2/opiepim/core/ocontactaccess.cpp | 8 | ||||
-rw-r--r-- | libopie2/opiepim/core/ocontactaccess.h | 8 | ||||
-rw-r--r-- | libopie2/opiepim/ocontact.h | 4 |
10 files changed, 86 insertions, 8 deletions
diff --git a/libopie/pim/ocontact.h b/libopie/pim/ocontact.h index 382ab94..038a59f 100644 --- a/libopie/pim/ocontact.h +++ b/libopie/pim/ocontact.h @@ -1,242 +1,238 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** Copyright (C) 2002 by Stefan Eilers (eilers.stefan@epost.de) ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __OCONTACT_H__ #define __OCONTACT_H__ #include <opie/opimrecord.h> #include <qpe/recordfields.h> #include <qdatetime.h> #include <qstringlist.h> #if defined(QPC_TEMPLATEDLL) // MOC_SKIP_BEGIN QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>; // MOC_SKIP_END #endif class ContactPrivate; // Wozu ist das gut und wo ist das decrariert ? (se) class QPC_EXPORT OContact : public OPimRecord { friend class DataSet; public: OContact(); OContact( const QMap<int, QString> &fromMap ); virtual ~OContact(); static void writeVCard( const QString &filename, const QValueList<OContact> &contacts); static void writeVCard( const QString &filename, const OContact &c ); static QValueList<OContact> readVCard( const QString &filename ); enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; void setTitle( const QString &v ) { replace( Qtopia::Title, v ); } void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); } void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); } void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); } void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); } void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); } void setFileAs(); // default email address void setDefaultEmail( const QString &v ); // inserts email to list and ensure's doesn't already exist void insertEmail( const QString &v ); void removeEmail( const QString &v ); void clearEmails(); void insertEmails( const QStringList &v ); // home void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); } void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); } void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); } void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); } void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); } void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); } void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); } void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); } void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); } // business void setCompany( const QString &v ) { replace( Qtopia::Company, v ); } void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); } void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); } void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); } void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); } void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); } void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); } void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); } void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); } void setOffice( const QString &v ) { replace( Qtopia::Office, v ); } void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); } void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); } void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); } void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); } void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); } void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); } void setManager( const QString &v ) { replace( Qtopia::Manager, v ); } // personal void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); } void setGender( const QString &v ) { replace( Qtopia::Gender, v ); } void setBirthday( const QDate &v ); void setAnniversary( const QDate &v ); void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); } void setChildren( const QString &v ); // other void setNotes( const QString &v ) { replace( Qtopia::Notes, v); } bool match( const QString ®exp ) const; - -// DON'T ATTEMPT TO USE THIS -#ifdef QTOPIA_INTERNAL_CONTACT_MRE bool match( const QRegExp ®exp ) const; -#endif // // custom // void setCustomField( const QString &key, const QString &v ) // { replace(Custom- + key, v ); } // name QString fullName() const; QString title() const { return find( Qtopia::Title ); } QString firstName() const { return find( Qtopia::FirstName ); } QString middleName() const { return find( Qtopia::MiddleName ); } QString lastName() const { return find( Qtopia::LastName ); } QString suffix() const { return find( Qtopia::Suffix ); } QString fileAs() const { return find( Qtopia::FileAs ); } // email QString defaultEmail() const { return find( Qtopia::DefaultEmail ); } QStringList emailList() const; // home QString homeStreet() const { return find( Qtopia::HomeStreet ); } QString homeCity() const { return find( Qtopia::HomeCity ); } QString homeState() const { return find( Qtopia::HomeState ); } QString homeZip() const { return find( Qtopia::HomeZip ); } QString homeCountry() const { return find( Qtopia::HomeCountry ); } QString homePhone() const { return find( Qtopia::HomePhone ); } QString homeFax() const { return find( Qtopia::HomeFax ); } QString homeMobile() const { return find( Qtopia::HomeMobile ); } QString homeWebpage() const { return find( Qtopia::HomeWebPage ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayHomeAddress() const; // business QString company() const { return find( Qtopia::Company ); } QString businessStreet() const { return find( Qtopia::BusinessStreet ); } QString businessCity() const { return find( Qtopia::BusinessCity ); } QString businessState() const { return find( Qtopia::BusinessState ); } QString businessZip() const { return find( Qtopia::BusinessZip ); } QString businessCountry() const { return find( Qtopia::BusinessCountry ); } QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); } QString jobTitle() const { return find( Qtopia::JobTitle ); } QString department() const { return find( Qtopia::Department ); } QString office() const { return find( Qtopia::Office ); } QString businessPhone() const { return find( Qtopia::BusinessPhone ); } QString businessFax() const { return find( Qtopia::BusinessFax ); } QString businessMobile() const { return find( Qtopia::BusinessMobile ); } QString businessPager() const { return find( Qtopia::BusinessPager ); } QString profession() const { return find( Qtopia::Profession ); } QString assistant() const { return find( Qtopia::Assistant ); } QString manager() const { return find( Qtopia::Manager ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayBusinessAddress() const; //personal QString spouse() const { return find( Qtopia::Spouse ); } QString gender() const { return find( Qtopia::Gender ); } QDate birthday() const; QDate anniversary() const; QString nickname() const { return find( Qtopia::Nickname ); } QString children() const { return find( Qtopia::Children ); } QStringList childrenList() const; // other QString notes() const { return find( Qtopia::Notes ); } QString groups() const { return find( Qtopia::Groups ); } QStringList groupList() const; // // custom // const QString &customField( const QString &key ) // { return find( Custom- + key ); } static QStringList fields(); static QStringList trfields(); static QStringList untrfields(); QString toRichText() const; QMap<int, QString> toMap() const; QString field( int key ) const { return find( key ); } // journaling... void saveJournal( journal_action action, const QString &key = QString::null ); void save( QString &buf ) const; void setUid( int i ) { Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); } QString toShortText()const; QString OContact::type()const; QMap<QString,QString> OContact::toExtraMap() const; class QString OContact::recordField(int) const; // Why private ? (eilers,se) QString emailSeparator() const { return " "; } // the emails should be seperated by a comma void setEmails( const QString &v ); QString emails() const { return find( Qtopia::Emails ); } private: friend class AbEditor; friend class AbTable; friend class AddressBookAccessPrivate; friend class XMLIO; void insert( int key, const QString &value ); void replace( int key, const QString &value ); QString find( int key ) const; QString displayAddress( const QString &street, const QString &city, const QString &state, const QString &zip, const QString &country ) const; Qtopia::UidGen &uidGen() { return sUidGen; } static Qtopia::UidGen sUidGen; QMap<int, QString> mMap; ContactPrivate *d; diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp index 2ca0283..f868b53 100644 --- a/libopie/pim/ocontactaccess.cpp +++ b/libopie/pim/ocontactaccess.cpp @@ -1,153 +1,161 @@ /* * 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.6 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.5 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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 ) { /* 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 ) { 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.. */ save(); // delete m_backEnd; is done by template.. } 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 ( OPimAccessTemplate<OContact>::wasChangedExternally() ) reload(); bool status = OPimAccessTemplate<OContact>::save(); if ( !status ) return false; /* Now tell everyone that new data is available. */ QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" ); return true; } +ORecordList<OContact> OContactAccess::matchRegexp( const QRegExp &r ) const{ + QArray<int> matchingContacts = m_backEnd -> matchRegexp( r ); + return ( ORecordList<OContact>(matchingContacts, this) ); +} + const uint OContactAccess::querySettings() { return ( m_backEnd->querySettings() ); } bool OContactAccess::hasQuerySettings ( int querySettings ) const { return ( m_backEnd->hasQuerySettings ( querySettings ) ); } bool OContactAccess::wasChangedExternally()const { return ( m_backEnd->wasChangedExternally() ); } 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/ocontactaccess.h b/libopie/pim/ocontactaccess.h index da9c942..b4921d5 100644 --- a/libopie/pim/ocontactaccess.h +++ b/libopie/pim/ocontactaccess.h @@ -1,131 +1,139 @@ /* * 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.4 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.3 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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. + * @see OPimAccessTemplate */ class OContactAccess: public QObject, public OPimAccessTemplate<OContact> { Q_OBJECT 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 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() */ enum QuerySettings { WildCards = 0x0001, IgnoreCase = 0x0002, RegExp = 0x0004, ExactMatch = 0x0008, + MatchOne = 0x0010 // Only one Entry must match }; + + ORecordList<OContact> matchRegexp( const QRegExp &r )const; + /** 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; /** * 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(); 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; private slots: void copMessage( const QCString &msg, const QByteArray &data ); }; #endif diff --git a/libopie/pim/ocontactaccessbackend.h b/libopie/pim/ocontactaccessbackend.h index a651477..c898f61 100644 --- a/libopie/pim/ocontactaccessbackend.h +++ b/libopie/pim/ocontactaccessbackend.h @@ -1,74 +1,81 @@ /** * 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.3 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * 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" +#include "qregexp.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; + virtual QArray<int> matchRegexp( const QRegExp &r ) const = 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 12a75ba..f7e8207 100644 --- a/libopie/pim/ocontactaccessbackend_xml.h +++ b/libopie/pim/ocontactaccessbackend_xml.h @@ -1,385 +1,405 @@ /* * 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.5 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.4 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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_changed( 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 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; 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(); m_changed = false; 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(); m_changed = false; } 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::IgnoreCase ){ case OContactAccess::RegExp:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::IgnoreCase), false ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::WildCards:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::IgnoreCase), true ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; 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; } + QArray<int> matchRegexp( const QRegExp &r ) const{ + QArray<int> m_currentQuery( m_contactList.count() ); + QValueListConstIterator<OContact> it; + uint arraycounter = 0; + + for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ + if ( (*it).match( r ) ){ + m_currentQuery[arraycounter++] = (*it).uid(); + } + + } + // Shrink to fit.. + m_currentQuery.resize(arraycounter); + + return m_currentQuery; + } + const uint querySettings() { return ( OContactAccess::WildCards & OContactAccess::IgnoreCase & OContactAccess::RegExp & OContactAccess::ExactMatch ); } bool hasQuerySettings (uint querySettings) const { /* 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::IgnoreCase ){ case OContactAccess::RegExp: return ( true ); case OContactAccess::WildCards: return ( true ); 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 ); m_changed = true; return true; } bool replace ( const OContact &contact ) { m_changed = true; 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 ) { m_changed = true; 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) ); diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.h b/libopie2/opiepim/backend/ocontactaccessbackend.h index a651477..c898f61 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend.h +++ b/libopie2/opiepim/backend/ocontactaccessbackend.h @@ -1,74 +1,81 @@ /** * 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.3 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * 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" +#include "qregexp.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; + virtual QArray<int> matchRegexp( const QRegExp &r ) const = 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 12a75ba..f7e8207 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h +++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h @@ -1,385 +1,405 @@ /* * 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.5 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.4 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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_changed( 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 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; 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(); m_changed = false; 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(); m_changed = false; } 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::IgnoreCase ){ case OContactAccess::RegExp:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::IgnoreCase), false ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; case OContactAccess::WildCards:{ QRegExp expr ( query.field(i), !(settings & OContactAccess::IgnoreCase), true ); if ( expr.find ( (*it).field(i), 0 ) == -1 ) allcorrect = false; } break; 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; } + QArray<int> matchRegexp( const QRegExp &r ) const{ + QArray<int> m_currentQuery( m_contactList.count() ); + QValueListConstIterator<OContact> it; + uint arraycounter = 0; + + for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ + if ( (*it).match( r ) ){ + m_currentQuery[arraycounter++] = (*it).uid(); + } + + } + // Shrink to fit.. + m_currentQuery.resize(arraycounter); + + return m_currentQuery; + } + const uint querySettings() { return ( OContactAccess::WildCards & OContactAccess::IgnoreCase & OContactAccess::RegExp & OContactAccess::ExactMatch ); } bool hasQuerySettings (uint querySettings) const { /* 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::IgnoreCase ){ case OContactAccess::RegExp: return ( true ); case OContactAccess::WildCards: return ( true ); 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 ); m_changed = true; return true; } bool replace ( const OContact &contact ) { m_changed = true; 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 ) { m_changed = true; 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) ); diff --git a/libopie2/opiepim/core/ocontactaccess.cpp b/libopie2/opiepim/core/ocontactaccess.cpp index 2ca0283..f868b53 100644 --- a/libopie2/opiepim/core/ocontactaccess.cpp +++ b/libopie2/opiepim/core/ocontactaccess.cpp @@ -1,153 +1,161 @@ /* * 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.6 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.5 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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 ) { /* 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 ) { 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.. */ save(); // delete m_backEnd; is done by template.. } 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 ( OPimAccessTemplate<OContact>::wasChangedExternally() ) reload(); bool status = OPimAccessTemplate<OContact>::save(); if ( !status ) return false; /* Now tell everyone that new data is available. */ QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" ); return true; } +ORecordList<OContact> OContactAccess::matchRegexp( const QRegExp &r ) const{ + QArray<int> matchingContacts = m_backEnd -> matchRegexp( r ); + return ( ORecordList<OContact>(matchingContacts, this) ); +} + const uint OContactAccess::querySettings() { return ( m_backEnd->querySettings() ); } bool OContactAccess::hasQuerySettings ( int querySettings ) const { return ( m_backEnd->hasQuerySettings ( querySettings ) ); } bool OContactAccess::wasChangedExternally()const { return ( m_backEnd->wasChangedExternally() ); } 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/libopie2/opiepim/core/ocontactaccess.h b/libopie2/opiepim/core/ocontactaccess.h index da9c942..b4921d5 100644 --- a/libopie2/opiepim/core/ocontactaccess.h +++ b/libopie2/opiepim/core/ocontactaccess.h @@ -1,131 +1,139 @@ /* * 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.4 2002/11/01 15:10:42 eilers + * Added regExp-search in database for all fields in a contact. + * * Revision 1.3 2002/10/16 10:52:40 eilers * Added some docu to the interface and now using the cache infrastucture by zecke.. :) * * 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. + * @see OPimAccessTemplate */ class OContactAccess: public QObject, public OPimAccessTemplate<OContact> { Q_OBJECT 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 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() */ enum QuerySettings { WildCards = 0x0001, IgnoreCase = 0x0002, RegExp = 0x0004, ExactMatch = 0x0008, + MatchOne = 0x0010 // Only one Entry must match }; + + ORecordList<OContact> matchRegexp( const QRegExp &r )const; + /** 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; /** * 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(); 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; private slots: void copMessage( const QCString &msg, const QByteArray &data ); }; #endif diff --git a/libopie2/opiepim/ocontact.h b/libopie2/opiepim/ocontact.h index 382ab94..038a59f 100644 --- a/libopie2/opiepim/ocontact.h +++ b/libopie2/opiepim/ocontact.h @@ -1,242 +1,238 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** Copyright (C) 2002 by Stefan Eilers (eilers.stefan@epost.de) ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __OCONTACT_H__ #define __OCONTACT_H__ #include <opie/opimrecord.h> #include <qpe/recordfields.h> #include <qdatetime.h> #include <qstringlist.h> #if defined(QPC_TEMPLATEDLL) // MOC_SKIP_BEGIN QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>; // MOC_SKIP_END #endif class ContactPrivate; // Wozu ist das gut und wo ist das decrariert ? (se) class QPC_EXPORT OContact : public OPimRecord { friend class DataSet; public: OContact(); OContact( const QMap<int, QString> &fromMap ); virtual ~OContact(); static void writeVCard( const QString &filename, const QValueList<OContact> &contacts); static void writeVCard( const QString &filename, const OContact &c ); static QValueList<OContact> readVCard( const QString &filename ); enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; void setTitle( const QString &v ) { replace( Qtopia::Title, v ); } void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); } void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); } void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); } void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); } void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); } void setFileAs(); // default email address void setDefaultEmail( const QString &v ); // inserts email to list and ensure's doesn't already exist void insertEmail( const QString &v ); void removeEmail( const QString &v ); void clearEmails(); void insertEmails( const QStringList &v ); // home void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); } void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); } void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); } void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); } void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); } void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); } void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); } void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); } void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); } // business void setCompany( const QString &v ) { replace( Qtopia::Company, v ); } void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); } void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); } void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); } void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); } void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); } void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); } void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); } void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); } void setOffice( const QString &v ) { replace( Qtopia::Office, v ); } void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); } void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); } void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); } void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); } void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); } void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); } void setManager( const QString &v ) { replace( Qtopia::Manager, v ); } // personal void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); } void setGender( const QString &v ) { replace( Qtopia::Gender, v ); } void setBirthday( const QDate &v ); void setAnniversary( const QDate &v ); void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); } void setChildren( const QString &v ); // other void setNotes( const QString &v ) { replace( Qtopia::Notes, v); } bool match( const QString ®exp ) const; - -// DON'T ATTEMPT TO USE THIS -#ifdef QTOPIA_INTERNAL_CONTACT_MRE bool match( const QRegExp ®exp ) const; -#endif // // custom // void setCustomField( const QString &key, const QString &v ) // { replace(Custom- + key, v ); } // name QString fullName() const; QString title() const { return find( Qtopia::Title ); } QString firstName() const { return find( Qtopia::FirstName ); } QString middleName() const { return find( Qtopia::MiddleName ); } QString lastName() const { return find( Qtopia::LastName ); } QString suffix() const { return find( Qtopia::Suffix ); } QString fileAs() const { return find( Qtopia::FileAs ); } // email QString defaultEmail() const { return find( Qtopia::DefaultEmail ); } QStringList emailList() const; // home QString homeStreet() const { return find( Qtopia::HomeStreet ); } QString homeCity() const { return find( Qtopia::HomeCity ); } QString homeState() const { return find( Qtopia::HomeState ); } QString homeZip() const { return find( Qtopia::HomeZip ); } QString homeCountry() const { return find( Qtopia::HomeCountry ); } QString homePhone() const { return find( Qtopia::HomePhone ); } QString homeFax() const { return find( Qtopia::HomeFax ); } QString homeMobile() const { return find( Qtopia::HomeMobile ); } QString homeWebpage() const { return find( Qtopia::HomeWebPage ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayHomeAddress() const; // business QString company() const { return find( Qtopia::Company ); } QString businessStreet() const { return find( Qtopia::BusinessStreet ); } QString businessCity() const { return find( Qtopia::BusinessCity ); } QString businessState() const { return find( Qtopia::BusinessState ); } QString businessZip() const { return find( Qtopia::BusinessZip ); } QString businessCountry() const { return find( Qtopia::BusinessCountry ); } QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); } QString jobTitle() const { return find( Qtopia::JobTitle ); } QString department() const { return find( Qtopia::Department ); } QString office() const { return find( Qtopia::Office ); } QString businessPhone() const { return find( Qtopia::BusinessPhone ); } QString businessFax() const { return find( Qtopia::BusinessFax ); } QString businessMobile() const { return find( Qtopia::BusinessMobile ); } QString businessPager() const { return find( Qtopia::BusinessPager ); } QString profession() const { return find( Qtopia::Profession ); } QString assistant() const { return find( Qtopia::Assistant ); } QString manager() const { return find( Qtopia::Manager ); } /** Multi line string containing all non-empty address info in the form * Street * City, State Zip * Country */ QString displayBusinessAddress() const; //personal QString spouse() const { return find( Qtopia::Spouse ); } QString gender() const { return find( Qtopia::Gender ); } QDate birthday() const; QDate anniversary() const; QString nickname() const { return find( Qtopia::Nickname ); } QString children() const { return find( Qtopia::Children ); } QStringList childrenList() const; // other QString notes() const { return find( Qtopia::Notes ); } QString groups() const { return find( Qtopia::Groups ); } QStringList groupList() const; // // custom // const QString &customField( const QString &key ) // { return find( Custom- + key ); } static QStringList fields(); static QStringList trfields(); static QStringList untrfields(); QString toRichText() const; QMap<int, QString> toMap() const; QString field( int key ) const { return find( key ); } // journaling... void saveJournal( journal_action action, const QString &key = QString::null ); void save( QString &buf ) const; void setUid( int i ) { Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); } QString toShortText()const; QString OContact::type()const; QMap<QString,QString> OContact::toExtraMap() const; class QString OContact::recordField(int) const; // Why private ? (eilers,se) QString emailSeparator() const { return " "; } // the emails should be seperated by a comma void setEmails( const QString &v ); QString emails() const { return find( Qtopia::Emails ); } private: friend class AbEditor; friend class AbTable; friend class AddressBookAccessPrivate; friend class XMLIO; void insert( int key, const QString &value ); void replace( int key, const QString &value ); QString find( int key ) const; QString displayAddress( const QString &street, const QString &city, const QString &state, const QString &zip, const QString &country ) const; Qtopia::UidGen &uidGen() { return sUidGen; } static Qtopia::UidGen sUidGen; QMap<int, QString> mMap; ContactPrivate *d; |