-rw-r--r-- | libopie2/opiepim/backend/obackendfactory.h | 12 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend.h | 14 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp | 22 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp | 3 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp | 6 | ||||
-rw-r--r-- | libopie2/opiepim/backend/opimaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessbackend.h | 4 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessvcal.cpp | 26 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.cpp | 6 |
10 files changed, 90 insertions, 11 deletions
diff --git a/libopie2/opiepim/backend/obackendfactory.h b/libopie2/opiepim/backend/obackendfactory.h index ad6cf5a..f3c339d 100644 --- a/libopie2/opiepim/backend/obackendfactory.h +++ b/libopie2/opiepim/backend/obackendfactory.h @@ -1,154 +1,166 @@ /* * 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.7 2003/08/01 12:30:16 eilers + * Merging changes from BRANCH_1_0 to HEAD + * + * Revision 1.6.4.1 2003/06/30 14:34:19 eilers + * Patches from Zecke: + * Fixing and cleaning up extraMap handling + * Adding d_ptr for binary compatibility in the future + * * Revision 1.6 2003/04/13 18:07:10 zecke * More API doc * QString -> const QString& * QString = 0l -> QString::null * * Revision 1.5 2003/02/21 23:31:52 zecke * Add XML datebookresource * -clean up todoaccessxml header * -implement some more stuff in the oeven tester * -extend DefaultFactory to not crash and to use datebook * * -reading of OEvents is working nicely.. saving will be added * tomorrow * -fix spelling in ODateBookAcces * * Revision 1.4 2002/10/14 15:55:18 eilers * Redeactivate SQL.. ;) * * Revision 1.3 2002/10/10 17:08:58 zecke * The Cache is finally in place * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;) * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster.... * I still have to fully implement read ahead * This change is bic but sc * * Revision 1.2 2002/10/08 09:27:36 eilers * Fixed libopie.pro to include the new pim-API. * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to * compile itself would need to install libsqlite, libopiesql... * Therefore, the backend currently uses XML only.. * * 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 "odatebookaccessbackend_xml.h" #ifdef __USE_SQL #include "otodoaccesssql.h" #endif +class OBackendPrivate; + /** * This class is our factory. It will give us the default implementations * of at least Todolist, Contacts and Datebook. In the future this class will * allow users to switch the backend with ( XML->SQLite ) without the need * to recompile.# * This class as the whole PIM Api is making use of templates * * <pre> * OTodoAccessBackend* backend = OBackEndFactory<OTodoAccessBackend>::Default("todo", QString::null ); * backend->load(); * </pre> * * @author Stefan Eilers * @version 0.1 */ template<class T> class OBackendFactory { public: OBackendFactory() {}; enum BACKENDS { TODO, CONTACT, DATE }; /** * Returns a backend implementation for backendName * @param backendName the type of the backend * @param appName will be passed on to the backend */ static T* Default( const QString backendName, const QString& appName ){ // __asm__("int3"); 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) ); dict.insert( "datebook", new int(DATE) ); qWarning ("TODO is: %d", TODO); qWarning ("CONTACT is: %d", CONTACT); int *find = dict[ backendName ]; if (!find ) return 0; switch ( *find ){ case TODO: #ifdef __USE_SQL if ( backend == "sql" ) return (T*) new OTodoAccessBackendSQL(""); #else if ( backend == "sql" ) qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); #endif 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: if ( backend == "sql" ) qWarning("OBackendFactory:: sql Backend not implemented! Using XML instead!"); return (T*) new ODateBookAccessBackend_XML( appName ); default: return NULL; } } + private: + OBackendPrivate* d; }; #endif diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.h b/libopie2/opiepim/backend/ocontactaccessbackend.h index ebeb42d..280e05c 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend.h +++ b/libopie2/opiepim/backend/ocontactaccessbackend.h @@ -1,107 +1,119 @@ /** * 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.6 2003/08/01 12:30:16 eilers + * Merging changes from BRANCH_1_0 to HEAD + * + * Revision 1.5.4.1 2003/06/30 14:34:19 eilers + * Patches from Zecke: + * Fixing and cleaning up extraMap handling + * Adding d_ptr for binary compatibility in the future + * * Revision 1.5 2003/04/13 18:07:10 zecke * More API doc * QString -> const QString& * QString = 0l -> QString::null * * Revision 1.4 2002/11/13 14:14:51 eilers * Added sorted for Contacts.. * * 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> /** * This class represents the interface of all Contact Backends. * Derivates of this class will be used to access the contacts. * As implementation currently XML and vCard exist. This class needs to be implemented * if you want to provide your own storage. * In all queries a list of uids is passed on instead of loading the actual record! * * @see OContactAccessBackend_VCard * @see OContactAccessBackend_XML */ 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; /** * FIXME!!! * Returns a sorted list of records either ascendinf or descending for a giving criteria and category */ virtual QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ) = 0; - + + +private: + class Private; + Private *d; }; #endif diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp index 270bef3..b60c5be 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp +++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp @@ -1,628 +1,646 @@ /* * VCard Backend for the OPIE-Contact Database. * * Copyright (C) 2000 Trolltech AS. All rights reserved. * 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: * * ===================================================================== * Version: $Id$ * ===================================================================== * History: * $Log$ + * Revision 1.11 2003/08/01 12:30:16 eilers + * Merging changes from BRANCH_1_0 to HEAD + * + * Revision 1.10.4.3 2003/07/23 08:54:37 eilers + * Default email was added to the list of all emails, which already contains + * the default email.. + * This closes bug #1045 + * + * Revision 1.10.4.2 2003/07/23 08:44:45 eilers + * Importing of Notes in vcard files wasn't implemented. + * Closes bug #1044 + * + * Revision 1.10.4.1 2003/06/02 13:37:49 eilers + * Fixing memory leak + * * Revision 1.10 2003/04/13 18:07:10 zecke * More API doc * QString -> const QString& * QString = 0l -> QString::null * * Revision 1.9 2003/03/21 10:33:09 eilers * Merged speed optimized xml backend for contacts to main. * Added QDateTime to querybyexample. For instance, it is now possible to get * all Birthdays/Anniversaries between two dates. This should be used * to show all birthdays in the datebook.. * This change is sourcecode backward compatible but you have to upgrade * the binaries for today-addressbook. * * Revision 1.8 2003/02/21 16:52:49 zecke * -Remove old Todo classes they're deprecated and today I already using the * new API * -Guard against self assignment in OTodo * -Add test apps for OPIM * -Opiefied Event classes * -Added TimeZone handling and pinning of TimeZones to OEvent * -Adjust ORecur and the widget to better timezone behaviour * * Revision 1.7 2003/02/16 22:25:46 zecke * 0000276 Fix for that bug.. or better temp workaround * A Preferred Number is HOME|VOICE * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test * triggers both * and the cell phone number overrides the other entries.. * * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the * number * * The right and final fix would be to reorder the if statement to make it * if else based and the less common thing put to the bottom * * OTodoAccessVcal fix the date for beaming * * Revision 1.6 2003/01/13 15:49:31 eilers * Fixing crash when businesscard.vcf is missing.. * * Revision 1.5 2002/12/07 13:26:22 eilers * Fixing bug in storing anniversary.. * * Revision 1.4 2002/11/13 14:14:51 eilers * Added sorted for Contacts.. * * Revision 1.3 2002/11/11 16:41:09 kergoth * no default arguments in implementation * * Revision 1.2 2002/11/10 15:41:53 eilers * Bugfixes.. * * Revision 1.1 2002/11/09 14:34:52 eilers * Added VCard Backend. * */ #include "ocontactaccessbackend_vcard.h" #include "../../library/backend/vobject_p.h" #include "../../library/backend/qfiledirect_p.h" #include <qpe/timeconversion.h> #include <qfile.h> OContactAccessBackend_VCard::OContactAccessBackend_VCard ( const QString& , const QString& filename ): m_dirty( false ), m_file( filename ) { load(); } bool OContactAccessBackend_VCard::load () { m_map.clear(); m_dirty = false; VObject* obj = 0l; if ( QFile::exists(m_file) ){ obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); if ( !obj ) return false; }else{ qWarning("File \"%s\" not found !", m_file.latin1() ); return false; } while ( obj ) { OContact con = parseVObject( obj ); /* * if uid is 0 assign a new one * this at least happens on * Nokia6210 */ if ( con.uid() == 0 ){ con.setUid( 1 ); qWarning("assigned new uid %d",con.uid() ); } m_map.insert( con.uid(), con ); VObject *t = obj; obj = nextVObjectInList(obj); cleanVObject( t ); } return true; } bool OContactAccessBackend_VCard::reload() { return load(); } bool OContactAccessBackend_VCard::save() { if (!m_dirty ) return true; QFileDirect file( m_file ); if (!file.open(IO_WriteOnly ) ) return false; VObject *obj; obj = newVObject( VCCalProp ); addPropValue( obj, VCVersionProp, "1.0" ); VObject *vo; for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ vo = createVObject( *it ); writeVObject( file.directHandle() , vo ); cleanVObject( vo ); } cleanStrTbl(); + deleteVObject( obj ); m_dirty = false; return true; } void OContactAccessBackend_VCard::clear () { m_map.clear(); m_dirty = true; // ??? sure ? (se) } bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) { m_map.insert( newcontact.uid(), newcontact ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::remove ( int uid ) { m_map.remove( uid ); m_dirty = true; return true; } bool OContactAccessBackend_VCard::replace ( const OContact &contact ) { m_map.replace( contact.uid(), contact ); m_dirty = true; return true; } OContact OContactAccessBackend_VCard::find ( int uid ) const { return m_map[uid]; } QArray<int> OContactAccessBackend_VCard::allRecords() const { QArray<int> ar( m_map.count() ); QMap<int, OContact>::ConstIterator it; int i = 0; for ( it = m_map.begin(); it != m_map.end(); ++it ) { ar[i] = it.key(); i++; } return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& ) { QArray<int> ar(0); return ar; } // Not implemented QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const { QArray<int> ar(0); return ar; } const uint OContactAccessBackend_VCard::querySettings() { return 0; // No search possible } bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const { return false; // No search possible, therefore all settings invalid ;) } bool OContactAccessBackend_VCard::wasChangedExternally() { return false; // Don't expect concurrent access } // Not implemented QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int ) { QArray<int> ar(0); return ar; } // *** Private stuff *** OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) { OContact c; VObjectIterator it; initPropIterator( &it, obj ); while( moreIteration( &it ) ) { VObject *o = nextVObject( &it ); QCString name = vObjectName( o ); QCString value = vObjectStringZValue( o ); if ( name == VCNameProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); QString value = vObjectStringZValue( o ); if ( name == VCNamePrefixesProp ) c.setTitle( value ); else if ( name == VCNameSuffixesProp ) c.setSuffix( value ); else if ( name == VCFamilyNameProp ) c.setLastName( value ); else if ( name == VCGivenNameProp ) c.setFirstName( value ); else if ( name == VCAdditionalNamesProp ) c.setMiddleName( value ); } } else if ( name == VCAdrProp ) { bool work = TRUE; // default address is work address QString street; QString city; QString region; QString postal; QString country; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCHomeProp ) work = FALSE; else if ( name == VCWorkProp ) work = TRUE; else if ( name == VCStreetAddressProp ) street = value; else if ( name == VCCityProp ) city = value; else if ( name == VCRegionProp ) region = value; else if ( name == VCPostalCodeProp ) postal = value; else if ( name == VCCountryNameProp ) country = value; } if ( work ) { c.setBusinessStreet( street ); c.setBusinessCity( city ); c.setBusinessCountry( country ); c.setBusinessZip( postal ); c.setBusinessState( region ); } else { c.setHomeStreet( street ); c.setHomeCity( city ); c.setHomeCountry( country ); c.setHomeZip( postal ); c.setHomeState( region ); } } else if ( name == VCTelephoneProp ) { enum { HOME = 0x01, WORK = 0x02, VOICE = 0x04, CELL = 0x08, FAX = 0x10, PAGER = 0x20, UNKNOWN = 0x80 }; int type = 0; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) type |= HOME; else if ( name == VCWorkProp ) type |= WORK; else if ( name == VCVoiceProp ) type |= VOICE; else if ( name == VCCellularProp ) type |= CELL; else if ( name == VCFaxProp ) type |= FAX; else if ( name == VCPagerProp ) type |= PAGER; else if ( name == VCPreferredProp ) ; else type |= UNKNOWN; } if ( (type & UNKNOWN) != UNKNOWN ) { if ( ( type & (HOME|WORK) ) == 0 ) // default type |= HOME; if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default type |= VOICE; qWarning("value %s %d", value.data(), type ); if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) ) c.setHomePhone( value ); if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) c.setHomeFax( value ); if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) c.setHomeMobile( value ); if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) ) c.setBusinessPhone( value ); if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) c.setBusinessFax( value ); if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) c.setBusinessMobile( value ); if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) c.setBusinessPager( value ); } } else if ( name == VCEmailAddressProp ) { QString email = vObjectStringZValue( o ); bool valid = TRUE; VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name != VCInternetProp && name != VCHomeProp && name != VCWorkProp && name != VCPreferredProp ) // ### preffered should map to default email valid = FALSE; } if ( valid ) { c.insertEmail( email ); } } else if ( name == VCURLProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectTypeInfo( o ); if ( name == VCHomeProp ) c.setHomeWebpage( value ); else if ( name == VCWorkProp ) c.setBusinessWebpage( value ); } } else if ( name == VCOrgProp ) { VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); if ( name == VCOrgNameProp ) c.setCompany( value ); else if ( name == VCOrgUnitProp ) c.setDepartment( value ); else if ( name == VCOrgUnit2Prop ) c.setOffice( value ); } } else if ( name == VCTitleProp ) { c.setJobTitle( value ); } else if ( name == "X-Qtopia-Profession" ) { c.setProfession( value ); } else if ( name == "X-Qtopia-Manager" ) { c.setManager( value ); } else if ( name == "X-Qtopia-Assistant" ) { c.setAssistant( value ); } else if ( name == "X-Qtopia-Spouse" ) { c.setSpouse( value ); } else if ( name == "X-Qtopia-Gender" ) { c.setGender( value ); } else if ( name == "X-Qtopia-Anniversary" ) { c.setAnniversary( convVCardDateToDate( value ) ); } else if ( name == "X-Qtopia-Nickname" ) { c.setNickname( value ); } else if ( name == "X-Qtopia-Children" ) { c.setChildren( value ); } else if ( name == VCBirthDateProp ) { // Reading Birthdate regarding RFC 2425 (5.8.4) c.setBirthday( convVCardDateToDate( value ) ); } - + else if ( name == VCCommentProp ) { + c.setNotes( value ); + } #if 0 else { printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); VObjectIterator nit; initPropIterator( &nit, o ); while( moreIteration( &nit ) ) { VObject *o = nextVObject( &nit ); QCString name = vObjectName( o ); QString value = vObjectStringZValue( o ); printf(" subprop: %s = %s\n", name.data(), value.latin1() ); } } #endif } c.setFileAs(); return c; } VObject* OContactAccessBackend_VCard::createVObject( const OContact &c ) { VObject *vcard = newVObject( VCCardProp ); safeAddPropValue( vcard, VCVersionProp, "2.1" ); safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); // full name safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); // name properties VObject *name = safeAddProp( vcard, VCNameProp ); safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); safeAddPropValue( name, VCGivenNameProp, c.firstName() ); safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); safeAddPropValue( name, VCNamePrefixesProp, c.title() ); safeAddPropValue( name, VCNameSuffixesProp, c.suffix() ); // home properties VObject *home_adr= safeAddProp( vcard, VCAdrProp ); safeAddProp( home_adr, VCHomeProp ); safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() ); safeAddPropValue( home_adr, VCCityProp, c.homeCity() ); safeAddPropValue( home_adr, VCRegionProp, c.homeState() ); safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() ); safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() ); VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() ); safeAddProp( home_phone, VCHomeProp ); home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() ); safeAddProp( home_phone, VCHomeProp ); safeAddProp( home_phone, VCCellularProp ); home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() ); safeAddProp( home_phone, VCHomeProp ); safeAddProp( home_phone, VCFaxProp ); VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() ); safeAddProp( url, VCHomeProp ); // work properties VObject *work_adr= safeAddProp( vcard, VCAdrProp ); safeAddProp( work_adr, VCWorkProp ); safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() ); safeAddPropValue( work_adr, VCCityProp, c.businessCity() ); safeAddPropValue( work_adr, VCRegionProp, c.businessState() ); safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() ); safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() ); VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() ); safeAddProp( work_phone, VCWorkProp ); work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() ); safeAddProp( work_phone, VCWorkProp ); safeAddProp( work_phone, VCCellularProp ); work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() ); safeAddProp( work_phone, VCWorkProp ); safeAddProp( work_phone, VCFaxProp ); work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() ); safeAddProp( work_phone, VCWorkProp ); safeAddProp( work_phone, VCPagerProp ); url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() ); safeAddProp( url, VCWorkProp ); VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() ); safeAddProp( title, VCWorkProp ); QStringList emails = c.emailList(); - emails.prepend( c.defaultEmail() ); + // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) { VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it ); safeAddProp( email, VCInternetProp ); } safeAddPropValue( vcard, VCNoteProp, c.notes() ); // Exporting Birthday regarding RFC 2425 (5.8.4) if ( c.birthday().isValid() ){ qWarning("Exporting birthday as: %s", convDateToVCardDate( c.birthday() ).latin1() ); safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) ); } if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) { VObject *org = safeAddProp( vcard, VCOrgProp ); safeAddPropValue( org, VCOrgNameProp, c.company() ); safeAddPropValue( org, VCOrgUnitProp, c.department() ); safeAddPropValue( org, VCOrgUnit2Prop, c.office() ); } // some values we have to export as custom fields safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() ); safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() ); safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() ); safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() ); safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() ); if ( c.anniversary().isValid() ){ qWarning("Exporting anniversary as: %s", convDateToVCardDate( c.anniversary() ).latin1() ); safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) ); } safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() ); safeAddPropValue( vcard, "X-Qtopia-Children", c.children() ); return vcard; } QString OContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const { QString str_rfc2425 = QString("%1-%2-%3") .arg( d.year() ) .arg( d.month(), 2 ) .arg( d.day(), 2 ); // Now replace spaces with "0"... int pos = 0; while ( ( pos = str_rfc2425.find (' ') ) > 0 ) str_rfc2425.replace( pos, 1, "0" ); return str_rfc2425; } QDate OContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr ) { int monthPos = datestr.find('-'); int dayPos = datestr.find('-', monthPos+1 ); int sep_ignore = 1; if ( monthPos == -1 || dayPos == -1 ) { qDebug("fromString didn't find - in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); // Ok.. No "-" found, therefore we will try to read other format ( YYYYMMDD ) if ( datestr.length() == 8 ){ monthPos = 4; dayPos = 6; sep_ignore = 0; qDebug("Try with follwing positions str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, dayPos ); } else { return QDate(); } } int y = datestr.left( monthPos ).toInt(); int m = datestr.mid( monthPos + sep_ignore, dayPos - monthPos - sep_ignore ).toInt(); int d = datestr.mid( dayPos + sep_ignore ).toInt(); qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, dayPos); QDate date ( y,m,d ); return date; } VObject* OContactAccessBackend_VCard::safeAddPropValue( VObject *o, const char *prop, const QString &value ) { VObject *ret = 0; if ( o && !value.isEmpty() ) ret = addPropValue( o, prop, value.latin1() ); return ret; } VObject* OContactAccessBackend_VCard::safeAddProp( VObject *o, const char *prop) { VObject *ret = 0; if ( o ) ret = addProp( o, prop ); return ret; } diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp index 097142b..1c21619 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp +++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp @@ -1,211 +1,214 @@ /* * 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.7 2003/08/01 12:30:16 eilers + * Merging changes from BRANCH_1_0 to HEAD + * * Revision 1.6 2003/07/07 16:19:47 eilers * Fixing serious bug in hasQuerySettings() * * Revision 1.5 2003/04/13 18:07:10 zecke * More API doc * QString -> const QString& * QString = 0l -> QString::null * * Revision 1.4 2003/03/21 14:32:54 mickeyl * g++ compliance fix: default arguments belong into the declaration, but not the definition * * Revision 1.3 2003/03/21 12:26:28 eilers * Fixing small bug: If we search a birthday from today to today, it returned * every contact .. * * Revision 1.2 2003/03/21 10:33:09 eilers * Merged speed optimized xml backend for contacts to main. * Added QDateTime to querybyexample. For instance, it is now possible to get * all Birthdays/Anniversaries between two dates. This should be used * to show all birthdays in the datebook.. * This change is sourcecode backward compatible but you have to upgrade * the binaries for today-addressbook. * * Revision 1.1.2.2 2003/02/11 12:17:28 eilers * Speed optimization. Removed the sequential search loops. * * Revision 1.1.2.1 2003/02/10 15:31:38 eilers * Writing offsets to debug output.. * * Revision 1.1 2003/02/09 15:05:01 eilers * Nothing happened.. Just some cleanup before I will start.. * * Revision 1.12 2003/01/03 16:58:03 eilers * Reenable debug output * * Revision 1.11 2003/01/03 12:31:28 eilers * Bugfix for calculating data diffs.. * * Revision 1.10 2003/01/02 14:27:12 eilers * Improved query by example: Search by date is possible.. First step * for a today plugin for birthdays.. * * Revision 1.9 2002/12/08 12:48:57 eilers * Moved journal-enum from ocontact into i the xml-backend.. * * Revision 1.8 2002/11/14 17:04:24 eilers * Sorting will now work if fullname is identical on some entries * * Revision 1.7 2002/11/13 15:02:46 eilers * Small Bug in sorted fixed * * Revision 1.6 2002/11/13 14:14:51 eilers * Added sorted for Contacts.. * * 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 ! * * */ #include "ocontactaccessbackend_xml.h" #include <qasciidict.h> #include <qdatetime.h> #include <qfile.h> #include <qfileinfo.h> #include <qregexp.h> #include <qarray.h> #include <qmap.h> #include <qdatetime.h> #include <qpe/global.h> #include <opie/xmltree.h> #include "ocontactaccessbackend.h" #include "ocontactaccess.h" #include <stdlib.h> #include <errno.h> using namespace Opie; OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ): m_changed( false ) { // Just m_contactlist should call delete if an entry // is removed. m_contactList.setAutoDelete( true ); m_uidToContact.setAutoDelete( false ); m_appName = appname; /* Set journalfile name ... */ m_journalName = getenv("HOME"); m_journalName +="/.abjournal" + appname; /* Expecting to access the default filename if nothing else is set */ if ( filename.isEmpty() ){ m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); } else m_fileName = filename; /* Load Database now */ load (); } bool OContactAccessBackend_XML::save() { if ( !m_changed ) return true; QString strNewFile = m_fileName + ".new"; QFile f( strNewFile ); if ( !f.open( IO_WriteOnly|IO_Raw ) ) return false; int total_written; int idx_offset = 0; QString out; // Write Header out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" " <Groups>\n" " </Groups>\n" " <Contacts>\n"; QCString cstr = out.utf8(); f.writeBlock( cstr.data(), cstr.length() ); idx_offset += cstr.length(); out = ""; // Write all contacts QListIterator<OContact> it( m_contactList ); for ( ; it.current(); ++it ) { qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset ); out += "<Contact "; (*it)->save( out ); out += "/>\n"; cstr = out.utf8(); total_written = f.writeBlock( cstr.data(), cstr.length() ); idx_offset += cstr.length(); if ( total_written != int(cstr.length()) ) { f.close(); QFile::remove( strNewFile ); return false; } out = ""; } out += " </Contacts>\n</AddressBook>\n"; // Write Footer cstr = out.utf8(); total_written = f.writeBlock( cstr.data(), cstr.length() ); if ( total_written != int( cstr.length() ) ) { f.close(); QFile::remove( strNewFile ); return false; } f.close(); // move the file over, I'm just going to use the system call // because, I don't feel like using QDir. if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 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; } diff --git a/libopie2/opiepim/backend/odatebookaccessbackend.h b/libopie2/opiepim/backend/odatebookaccessbackend.h index 86ff298..3c02c42 100644 --- a/libopie2/opiepim/backend/odatebookaccessbackend.h +++ b/libopie2/opiepim/backend/odatebookaccessbackend.h @@ -1,73 +1,77 @@ #ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H #define OPIE_DATE_BOOK_ACCESS_BACKEND_H #include <qarray.h> #include "opimaccessbackend.h" #include "oevent.h" /** * This class is the interface to the storage of Events. * @see OPimAccessBackend * */ class ODateBookAccessBackend : public OPimAccessBackend<OEvent> { public: typedef int UID; /** * c'tor without parameter */ ODateBookAccessBackend(); ~ODateBookAccessBackend(); /** * This method should return a list of UIDs containing * all events. No filter should be applied * @return list of events */ virtual QArray<UID> rawEvents()const = 0; /** * This method should return a list of UIDs containing * all repeating events. No filter should be applied * @return list of repeating events */ virtual QArray<UID> rawRepeats()const = 0; /** * This mthod should return a list of UIDs containing all non * repeating events. No filter should be applied * @return list of nonrepeating events */ virtual QArray<UID> nonRepeats() const = 0; /** * If you do not want to implement the effectiveEvents methods below * you need to supply it with directNonRepeats. * This method can return empty lists if effectiveEvents is implememted */ virtual OEvent::ValueList directNonRepeats() = 0; /** * Same as above but return raw repeats! */ virtual OEvent::ValueList directRawRepeats() = 0; /* is implemented by default but you can reimplement it*/ /** * Effective Events are special event occuring during a time frame. This method does calcualte * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method * yourself */ virtual OEffectiveEvent::ValueList effecticeEvents( const QDate& from, const QDate& to ); /** * this is an overloaded member function * @see effecticeEvents */ virtual OEffectiveEvent::ValueList effecticeEvents( const QDateTime& start ); +private: + class Private; + Private *d; + }; #endif diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp index ab2eea4..5ea945c 100644 --- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp +++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp @@ -241,366 +241,366 @@ QArray<int> ODateBookAccessBackend_XML::allRecords()const { ints[i] = it.key(); i++; } return ints; } QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) { return QArray<int>(); } void ODateBookAccessBackend_XML::clear() { m_changed = true; m_raw.clear(); m_rep.clear(); } OEvent ODateBookAccessBackend_XML::find( int uid ) const{ if ( m_raw.contains( uid ) ) return m_raw[uid]; else return m_rep[uid]; } bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { m_changed = true; if (ev.hasRecurrence() ) m_rep.insert( ev.uid(), ev ); else m_raw.insert( ev.uid(), ev ); return true; } bool ODateBookAccessBackend_XML::remove( int uid ) { m_changed = true; m_rep.remove( uid ); m_rep.remove( uid ); return true; } bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { replace( ev.uid() ); return add( ev ); } QArray<int> ODateBookAccessBackend_XML::rawEvents()const { return allRecords(); } QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { QArray<int> ints( m_rep.count() ); uint i = 0; QMap<int, OEvent>::ConstIterator it; for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { ints[i] = it.key(); i++; } return ints; } QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { QArray<int> ints( m_raw.count() ); uint i = 0; QMap<int, OEvent>::ConstIterator it; for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { ints[i] = it.key(); i++; } return ints; } OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { OEvent::ValueList list; QMap<int, OEvent>::ConstIterator it; for (it = m_raw.begin(); it != m_raw.end(); ++it ) list.append( it.data() ); return list; } OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { OEvent::ValueList list; QMap<int, OEvent>::ConstIterator it; for (it = m_rep.begin(); it != m_rep.end(); ++it ) list.append( it.data() ); return list; } bool ODateBookAccessBackend_XML::loadFile() { m_changed = false; int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); if ( fd < 0 ) return false; struct stat attribute; if ( ::fstat(fd, &attribute ) == -1 ) { ::close( fd ); return false; } void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); if ( map_addr == ( (caddr_t)-1) ) { ::close( fd ); return false; } ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); ::close( fd ); QAsciiDict<int> dict(FExceptions+1); dict.setAutoDelete( true ); dict.insert( "description", new int(FDescription) ); dict.insert( "location", new int(FLocation) ); dict.insert( "categories", new int(FCategories) ); dict.insert( "uid", new int(FUid) ); dict.insert( "type", new int(FType) ); dict.insert( "alarm", new int(FAlarm) ); dict.insert( "sound", new int(FSound) ); dict.insert( "rtype", new int(FRType) ); dict.insert( "rweekdays", new int(FRWeekdays) ); dict.insert( "rposition", new int(FRPosition) ); dict.insert( "rfreq", new int(FRFreq) ); dict.insert( "rhasenddate", new int(FRHasEndDate) ); dict.insert( "enddt", new int(FREndDate) ); dict.insert( "start", new int(FRStart) ); dict.insert( "end", new int(FREnd) ); dict.insert( "note", new int(FNote) ); dict.insert( "created", new int(FCreated) ); dict.insert( "recparent", new int(FRecParent) ); dict.insert( "recchildren", new int(FRecChildren) ); dict.insert( "exceptions", new int(FExceptions) ); dict.insert( "timezone", new int(FTimeZone) ); char* dt = (char*)map_addr; int len = attribute.st_size; int i = 0; char* point; const char* collectionString = "<event "; int strLen = ::strlen(collectionString); int *find; while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) { i = point -dt; i+= strLen; alarmTime = -1; snd = 0; // silent OEvent ev; rec = 0; while ( TRUE ) { while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) ++i; if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) break; // we have another attribute, read it. int j = i; while ( j < len && dt[j] != '=' ) ++j; QCString attr( dt+i, j-i+1); i = ++j; // skip = // find the start of quotes while ( i < len && dt[i] != '"' ) ++i; j = ++i; bool haveUtf = FALSE; bool haveEnt = FALSE; while ( j < len && dt[j] != '"' ) { if ( ((unsigned char)dt[j]) > 0x7f ) haveUtf = TRUE; if ( dt[j] == '&' ) haveEnt = TRUE; ++j; } if ( i == j ) { // empty value i = j + 1; continue; } QCString value( dt+i, j-i+1 ); i = j + 1; QString str = (haveUtf ? QString::fromUtf8( value ) : QString::fromLatin1( value ) ); if ( haveEnt ) str = Qtopia::plainString( str ); /* * add key + value */ find = dict[attr.data()]; if (!find) - ev.setCustomField( attr, value ); + ev.setCustomField( attr, str ); else { - setField( ev, *find, value ); + setField( ev, *find, str ); } } /* time to finalize */ finalizeRecord( ev ); delete rec; } ::munmap(map_addr, attribute.st_size ); m_changed = false; // changed during add return true; } void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { /* AllDay is alway in UTC */ if ( ev.isAllDay() ) { OTimeZone utc = OTimeZone::utc(); ev.setStartDateTime( utc.fromUTCDateTime( start ) ); ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); ev.setTimeZone( "UTC"); // make sure it is really utc }else { /* to current date time */ - qWarning(" Start is %d", start ); + // qWarning(" Start is %d", start ); OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); QDateTime date = zone.toDateTime( start ); qWarning(" Start is %s", date.toString().latin1() ); ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); date = zone.toDateTime( end ); ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); } if ( rec && rec->doesRecur() ) { OTimeZone utc = OTimeZone::utc(); ORecur recu( *rec ); // call copy c'tor; recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); recu.setStart( ev.startDateTime().date() ); ev.setRecurrence( recu ); } if (alarmTime != -1 ) { QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); OPimAlarm al( snd , dt ); ev.notifiers().add( al ); } if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { qWarning("already contains assign uid"); ev.setUid( 1 ); } qWarning("addind %d %s", ev.uid(), ev.description().latin1() ); if ( ev.hasRecurrence() ) m_rep.insert( ev.uid(), ev ); else m_raw.insert( ev.uid(), ev ); } void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { // qWarning(" setting %s", value.latin1() ); switch( id ) { case FDescription: e.setDescription( value ); break; case FLocation: e.setLocation( value ); break; case FCategories: e.setCategories( e.idsFromString( value ) ); break; case FUid: e.setUid( value.toInt() ); break; case FType: if ( value == "AllDay" ) { e.setAllDay( true ); e.setTimeZone( "UTC" ); } break; case FAlarm: alarmTime = value.toInt(); break; case FSound: snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; break; // recurrence stuff case FRType: if ( value == "Daily" ) recur()->setType( ORecur::Daily ); else if ( value == "Weekly" ) recur()->setType( ORecur::Weekly); else if ( value == "MonthlyDay" ) recur()->setType( ORecur::MonthlyDay ); else if ( value == "MonthlyDate" ) recur()->setType( ORecur::MonthlyDate ); else if ( value == "Yearly" ) recur()->setType( ORecur::Yearly ); else recur()->setType( ORecur::NoRepeat ); break; case FRWeekdays: recur()->setDays( value.toInt() ); break; case FRPosition: recur()->setPosition( value.toInt() ); break; case FRFreq: recur()->setFrequency( value.toInt() ); break; case FRHasEndDate: recur()->setHasEndDate( value.toInt() ); break; case FREndDate: { rp_end = (time_t) value.toLong(); break; } case FRStart: { start = (time_t) value.toLong(); break; } case FREnd: { end = ( (time_t) value.toLong() ); break; } case FNote: e.setNote( value ); break; case FCreated: created = value.toInt(); break; case FRecParent: e.setParent( value.toInt() ); break; case FRecChildren:{ QStringList list = QStringList::split(' ', value ); for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { e.addChild( (*it).toInt() ); } } break; case FExceptions:{ QStringList list = QStringList::split(' ', value ); for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); qWarning("adding exception %s", date.toString().latin1() ); recur()->exceptions().append( date ); } } break; case FTimeZone: if ( value != "None" ) e.setTimeZone( value ); break; default: break; } } QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const { QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() ); uint arraycounter = 0; QMap<int, OEvent>::ConstIterator it; for ( it = m_raw.begin(); it != m_raw.end(); ++it ) if ( it.data().match( r ) ) m_currentQuery[arraycounter++] = it.data().uid(); for ( it = m_rep.begin(); it != m_rep.end(); ++it ) if ( it.data().match( r ) ) m_currentQuery[arraycounter++] = it.data().uid(); // Shrink to fit.. m_currentQuery.resize(arraycounter); return m_currentQuery; } diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h index f4bbe35..c3d91f7 100644 --- a/libopie2/opiepim/backend/opimaccessbackend.h +++ b/libopie2/opiepim/backend/opimaccessbackend.h @@ -1,159 +1,159 @@ #ifndef OPIE_PIM_ACCESS_BACKEND #define OPIE_PIM_ACCESS_BACKEND #include <qarray.h> #include <opie/otemplatebase.h> #include <opie/opimrecord.h> +class OPimAccessBackendPrivate; /** * OPimAccessBackend is the base class * for all private backends * it operates on OPimRecord as the base class * and it's responsible for fast manipulating * the resource the implementation takes care * of */ template <class T = OPimRecord> class OPimAccessBackend { public: typedef OTemplateBase<T> Frontend; /** The access hint from the frontend */ OPimAccessBackend(int access = 0); virtual ~OPimAccessBackend(); /** * load the resource */ virtual bool load() = 0; /** * reload the resource */ virtual bool reload() = 0; /** * save the resource and * all it's changes */ virtual bool save() = 0; /** * return an array of * all available uids */ virtual QArray<int> allRecords()const = 0; /** * return a List of records * that match the regex */ virtual QArray<int> matchRegexp(const QRegExp &r) const = 0; /** * queryByExample for T with the given Settings * */ virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0; /** * find the OPimRecord with uid @param uid * returns T and T.isEmpty() if nothing was found */ virtual T find(int uid )const = 0; virtual T find(int uid, const QArray<int>& items, uint current, typename Frontend::CacheDirection )const ; /** * clear the back end */ virtual void clear() = 0; /** * add T */ virtual bool add( const T& t ) = 0; /** * remove */ virtual bool remove( int uid ) = 0; /** * replace a record with T.uid() */ virtual bool replace( const T& t ) = 0; /* * setTheFrontEnd!!! */ void setFrontend( Frontend* front ); /** * set the read ahead count */ void setReadAhead( uint count ); protected: int access()const; void cache( const T& t )const; /** * use a prime number here! */ void setSaneCacheSize( int ); uint readAhead()const; private: - class Private; - Private* d; + OPimAccessBackendPrivate *d; Frontend* m_front; uint m_read; int m_acc; }; template <class T> OPimAccessBackend<T>::OPimAccessBackend(int acc) : m_acc( acc ) { m_front = 0l; } template <class T> OPimAccessBackend<T>::~OPimAccessBackend() { } template <class T> void OPimAccessBackend<T>::setFrontend( Frontend* fr ) { m_front = fr; } template <class T> void OPimAccessBackend<T>::cache( const T& t )const { if (m_front ) m_front->cache( t ); } template <class T> void OPimAccessBackend<T>::setSaneCacheSize( int size) { if (m_front ) m_front->setSaneCacheSize( size ); } template <class T> T OPimAccessBackend<T>::find( int uid, const QArray<int>&, uint, typename Frontend::CacheDirection )const { return find( uid ); } template <class T> void OPimAccessBackend<T>::setReadAhead( uint count ) { m_read = count; } template <class T> uint OPimAccessBackend<T>::readAhead()const { return m_read; } template <class T> int OPimAccessBackend<T>::access()const { return m_acc; } #endif diff --git a/libopie2/opiepim/backend/otodoaccessbackend.h b/libopie2/opiepim/backend/otodoaccessbackend.h index 05e8ca9..6be95bc 100644 --- a/libopie2/opiepim/backend/otodoaccessbackend.h +++ b/libopie2/opiepim/backend/otodoaccessbackend.h @@ -1,24 +1,28 @@ #ifndef OPIE_TODO_ACCESS_BACKEND_H #define OPIE_TODO_ACCESS_BACKEND_H #include <qbitarray.h> #include "otodo.h" #include "opimaccessbackend.h" class OTodoAccessBackend : public OPimAccessBackend<OTodo> { public: OTodoAccessBackend(); ~OTodoAccessBackend(); virtual QArray<int> effectiveToDos( const QDate& start, const QDate& end, bool includeNoDates ) = 0; virtual QArray<int> overDue() = 0; virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter, int cat ) = 0; virtual void removeAllCompleted() = 0; virtual QBitArray supports()const = 0; + +private: + class Private; + Private *d; }; #endif diff --git a/libopie2/opiepim/backend/otodoaccessvcal.cpp b/libopie2/opiepim/backend/otodoaccessvcal.cpp index 3577e14..6415952 100644 --- a/libopie2/opiepim/backend/otodoaccessvcal.cpp +++ b/libopie2/opiepim/backend/otodoaccessvcal.cpp @@ -1,225 +1,249 @@ #include <qfile.h> #include <qtopia/private/vobject_p.h> #include <qtopia/timeconversion.h> #include <qtopia/private/qfiledirect_p.h> #include "otodoaccessvcal.h" namespace { static OTodo eventByVObj( VObject *obj ){ OTodo event; VObject *ob; QCString name; // no uid, attendees, ... and no fun // description if( ( ob = isAPropertyOf( obj, VCDescriptionProp )) != 0 ){ name = vObjectStringZValue( ob ); +#if 0 event.setDescription( name ); +#else + event.setSummary( name ); +#endif } // summary if ( ( ob = isAPropertyOf( obj, VCSummaryProp ) ) != 0 ) { name = vObjectStringZValue( ob ); +#if 0 event.setSummary( name ); +#else + event.setDescription( name ); +#endif } // completed if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){ name = vObjectStringZValue( ob ); if( name == "COMPLETED" ){ event.setCompleted( true ); }else{ event.setCompleted( false ); } }else event.setCompleted( false ); // priority if ((ob = isAPropertyOf(obj, VCPriorityProp))) { name = vObjectStringZValue( ob ); bool ok; event.setPriority(name.toInt(&ok) ); } //due date if((ob = isAPropertyOf(obj, VCDueProp)) ){ event.setHasDueDate( true ); name = vObjectStringZValue( ob ); event.setDueDate( TimeConversion::fromISO8601( name).date() ); } // categories if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){ name = vObjectStringZValue( ob ); qWarning("Categories:%s", name.data() ); } event.setUid( 1 ); return event; }; static VObject *vobjByEvent( const OTodo &event ) { VObject *task = newVObject( VCTodoProp ); if( task == 0 ) return 0l; if( event.hasDueDate() ) { QTime time(0, 0, 0); QDateTime date(event.dueDate(), time ); addPropValue( task, VCDueProp, TimeConversion::toISO8601( date ) ); } if( event.isCompleted() ) addPropValue( task, VCStatusProp, "COMPLETED"); QString string = QString::number(event.priority() ); addPropValue( task, VCPriorityProp, string.local8Bit() ); addPropValue( task, VCCategoriesProp, event.idsToString( event.categories() ).local8Bit() ); +#if 0 + + // There seems a misrepresentation between summary in otodoevent + // and summary in vcard. + // The same with description.. + // Description is summary and vice versa.. Argh.. (eilers) + + addPropValue( task, VCDescriptionProp, event.description().local8Bit() ); addPropValue( task, VCSummaryProp, event.summary().local8Bit() ); + +#else + addPropValue( task, VCDescriptionProp, + event.summary().local8Bit() ); + + addPropValue( task, VCSummaryProp, + event.description().local8Bit() ); +#endif return task; }; } OTodoAccessVCal::OTodoAccessVCal( const QString& path ) : m_dirty(false), m_file( path ) { } OTodoAccessVCal::~OTodoAccessVCal() { } bool OTodoAccessVCal::load() { m_map.clear(); m_dirty = false; VObject* vcal = 0l; vcal = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); if (!vcal ) return false; // Iterate over the list VObjectIterator it; VObject* vobj; initPropIterator(&it, vcal); while( moreIteration( &it ) ) { vobj = ::nextVObject( &it ); QCString name = ::vObjectName( vobj ); if( name == VCTodoProp ){ OTodo to = eventByVObj( vobj ); m_map.insert( to.uid(), to ); } } // Should I do a delete vcal? return true; } bool OTodoAccessVCal::reload() { return load(); } bool OTodoAccessVCal::save() { if (!m_dirty ) return true; QFileDirect file( m_file ); if (!file.open(IO_WriteOnly ) ) return false; VObject *obj; obj = newVObject( VCCalProp ); addPropValue( obj, VCVersionProp, "1.0" ); VObject *vo; for(QMap<int, OTodo>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ vo = vobjByEvent( it.data() ); addVObjectProp(obj, vo ); } writeVObject( file.directHandle(), obj ); cleanVObject( obj ); cleanStrTbl(); m_dirty = false; return true; } void OTodoAccessVCal::clear() { m_map.clear(); m_dirty = true; } bool OTodoAccessVCal::add( const OTodo& to ) { m_map.insert( to.uid(), to ); m_dirty = true; return true; } bool OTodoAccessVCal::remove( int uid ) { m_map.remove( uid ); m_dirty = true; return true; } void OTodoAccessVCal::removeAllCompleted() { for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) { if ( (*it).isCompleted() ) m_map.remove( it ); } } bool OTodoAccessVCal::replace( const OTodo& to ) { m_map.replace( to.uid(), to ); m_dirty = true; return true; } OTodo OTodoAccessVCal::find(int uid )const { return m_map[uid]; } QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::allRecords()const { QArray<int> ar( m_map.count() ); QMap<int, OTodo>::ConstIterator it; int i = 0; for ( it = m_map.begin(); it != m_map.end(); ++it ) { ar[i] = it.key(); i++; } return ar; } -QArray<int> OTodoAccessVCal::matchRegexp(const QRegExp &r)const { +QArray<int> OTodoAccessVCal::matchRegexp(const QRegExp& /* r */)const { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& , const QDate& , bool ) { QArray<int> ar(0); return ar; } QArray<int> OTodoAccessVCal::overDue() { QArray<int> ar(0); return ar; } QBitArray OTodoAccessVCal::supports()const { static QBitArray ar = sup(); return ar; } QBitArray OTodoAccessVCal::sup() { QBitArray ar ( OTodo::CompletedDate +1 ); ar.fill( true ); ar[OTodo::CrossReference] = false; ar[OTodo::State ] = false; ar[OTodo::Reminders] = false; ar[OTodo::Notifiers] = false; ar[OTodo::Maintainer] = false; ar[OTodo::Progress] = false; ar[OTodo::Alarms ] = false; ar[OTodo::Recurrence] = false; return ar; } diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index 3d15354..f688735 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp @@ -1,282 +1,282 @@ #include <errno.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <qfile.h> #include <qvector.h> #include <qpe/global.h> #include <qpe/stringutil.h> #include <qpe/timeconversion.h> #include "oconversion.h" #include "opimstate.h" #include "otimezone.h" #include "opimnotifymanager.h" #include "orecur.h" #include "otodoaccessxml.h" namespace { time_t rp_end; ORecur* rec; ORecur *recur() { if (!rec ) rec = new ORecur; return rec; } int snd; enum MoreAttributes { FRType = OTodo::CompletedDate + 2, FRWeekdays, FRPosition, FRFreq, FRHasEndDate, FREndDate, FRStart, FREnd }; // FROM TT again char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) { char needleChar; char haystackChar; if (!needle || !haystack || !hLen || !nLen) return 0; const char* hsearch = haystack; if ((needleChar = *needle++) != 0) { nLen--; //(to make up for needle++) do { do { if ((haystackChar = *hsearch++) == 0) return (0); if (hsearch >= haystack + hLen) return (0); } while (haystackChar != needleChar); } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); hsearch--; } return ((char *)hsearch); } } OTodoAccessXML::OTodoAccessXML( const QString& appName, const QString& fileName ) : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) { if (!fileName.isEmpty() ) m_file = fileName; else m_file = Global::applicationFileName( "todolist", "todolist.xml" ); } OTodoAccessXML::~OTodoAccessXML() { } bool OTodoAccessXML::load() { rec = 0; m_opened = true; m_changed = false; /* initialize dict */ /* * UPDATE dict if you change anything!!! */ - QAsciiDict<int> dict(21); + QAsciiDict<int> dict(26); dict.setAutoDelete( TRUE ); dict.insert("Categories" , new int(OTodo::Category) ); dict.insert("Uid" , new int(OTodo::Uid) ); dict.insert("HasDate" , new int(OTodo::HasDate) ); dict.insert("Completed" , new int(OTodo::Completed) ); dict.insert("Description" , new int(OTodo::Description) ); dict.insert("Summary" , new int(OTodo::Summary) ); dict.insert("Priority" , new int(OTodo::Priority) ); dict.insert("DateDay" , new int(OTodo::DateDay) ); dict.insert("DateMonth" , new int(OTodo::DateMonth) ); dict.insert("DateYear" , new int(OTodo::DateYear) ); dict.insert("Progress" , new int(OTodo::Progress) ); dict.insert("CompletedDate", new int(OTodo::CompletedDate) ); dict.insert("StartDate", new int(OTodo::StartDate) ); dict.insert("CrossReference", new int(OTodo::CrossReference) ); dict.insert("State", new int(OTodo::State) ); dict.insert("Alarms", new int(OTodo::Alarms) ); dict.insert("Reminders", new int(OTodo::Reminders) ); dict.insert("Notifiers", new int(OTodo::Notifiers) ); dict.insert("Maintainer", new int(OTodo::Maintainer) ); dict.insert("rtype", new int(FRType) ); dict.insert("rweekdays", new int(FRWeekdays) ); dict.insert("rposition", new int(FRPosition) ); dict.insert("rfreq", new int(FRFreq) ); dict.insert("start", new int(FRStart) ); dict.insert("rhasenddate", new int(FRHasEndDate) ); dict.insert("enddt", new int(FREndDate) ); // here the custom XML parser from TT it's GPL // but we want to push OpiePIM... to TT..... // mmap part from zecke :) int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); struct stat attribut; if ( fd < 0 ) return false; if ( fstat(fd, &attribut ) == -1 ) { ::close( fd ); return false; } void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); if ( map_addr == ( (caddr_t)-1) ) { ::close(fd ); return false; } /* advise the kernel who we want to read it */ ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); /* we do not the file any more */ ::close( fd ); char* dt = (char*)map_addr; int len = attribut.st_size; int i = 0; char *point; const char* collectionString = "<Task "; int strLen = strlen(collectionString); while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) { i = point -dt; i+= strLen; qWarning("Found a start at %d %d", i, (point-dt) ); OTodo ev; m_year = m_month = m_day = 0; while ( TRUE ) { while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) ++i; if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) break; // we have another attribute, read it. int j = i; while ( j < len && dt[j] != '=' ) ++j; QCString attr( dt+i, j-i+1); i = ++j; // skip = // find the start of quotes while ( i < len && dt[i] != '"' ) ++i; j = ++i; bool haveUtf = FALSE; bool haveEnt = FALSE; while ( j < len && dt[j] != '"' ) { if ( ((unsigned char)dt[j]) > 0x7f ) haveUtf = TRUE; if ( dt[j] == '&' ) haveEnt = TRUE; ++j; } if ( i == j ) { // empty value i = j + 1; continue; } QCString value( dt+i, j-i+1 ); i = j + 1; QString str = (haveUtf ? QString::fromUtf8( value ) : QString::fromLatin1( value ) ); if ( haveEnt ) str = Qtopia::plainString( str ); /* * add key + value */ todo( &dict, ev, attr, str ); } /* * now add it */ qWarning("End at %d", i ); if (m_events.contains( ev.uid() ) || ev.uid() == 0) { ev.setUid( 1 ); m_changed = true; } if ( ev.hasDueDate() ) { ev.setDueDate( QDate(m_year, m_month, m_day) ); } if ( rec && rec->doesRecur() ) { OTimeZone utc = OTimeZone::utc(); ORecur recu( *rec ); // call copy c'tor recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() ); recu.setStart( ev.dueDate() ); ev.setRecurrence( recu ); } m_events.insert(ev.uid(), ev ); m_year = m_month = m_day = -1; delete rec; rec = 0; } munmap(map_addr, attribut.st_size ); qWarning("counts %d records loaded!", m_events.count() ); return true; } bool OTodoAccessXML::reload() { m_events.clear(); return load(); } bool OTodoAccessXML::save() { // qWarning("saving"); if (!m_opened || !m_changed ) { // qWarning("not saving"); return true; } QString strNewFile = m_file + ".new"; QFile f( strNewFile ); if (!f.open( IO_WriteOnly|IO_Raw ) ) return false; int written; QString out; out = "<!DOCTYPE Tasks>\n<Tasks>\n"; // for all todos QMap<int, OTodo>::Iterator it; for (it = m_events.begin(); it != m_events.end(); ++it ) { out+= "<Task " + toString( (*it) ) + " />\n"; QCString cstr = out.utf8(); written = f.writeBlock( cstr.data(), cstr.length() ); /* less written then we wanted */ if ( written != (int)cstr.length() ) { f.close(); QFile::remove( strNewFile ); return false; } out = QString::null; } out += "</Tasks>"; QCString cstr = out.utf8(); written = f.writeBlock( cstr.data(), cstr.length() ); if ( written != (int)cstr.length() ) { f.close(); QFile::remove( strNewFile ); return false; } /* flush before renaming */ f.close(); if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { // qWarning("error renaming"); QFile::remove( strNewFile ); } @@ -647,228 +647,230 @@ namespace { else if ( t1.hasDueDate() ) ret = -1; else if ( t2.hasDueDate() ) ret = 1; else ret = 0; return ret; } }; /* * Returns: * 0 if item1 == item2 * * non-zero if item1 != item2 * * This function returns int rather than bool so that reimplementations * can return one of three values and use it to sort by: * * 0 if item1 == item2 * * > 0 (positive integer) if item1 > item2 * * < 0 (negative integer) if item1 < item2 * */ class OTodoXMLVector : public QVector<OTodoXMLContainer> { public: OTodoXMLVector(int size, bool asc, int sort) : QVector<OTodoXMLContainer>( size ) { setAutoDelete( true ); m_asc = asc; m_sort = sort; } /* return the summary/description */ QString string( const OTodo& todo) { return todo.summary().isEmpty() ? todo.description().left(20 ) : todo.summary(); } /** * we take the sortorder( switch on it ) * */ int compareItems( Item d1, Item d2 ) { bool seComp, sePrio, seDesc, seDeadline; seComp = sePrio = seDeadline = seDesc = false; int ret =0; OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; /* same item */ if ( con1->todo.uid() == con2->todo.uid() ) return 0; switch ( m_sort ) { /* completed */ case 0: { ret = completed( con1->todo, con2->todo ); seComp = TRUE; break; } /* priority */ case 1: { ret = priority( con1->todo, con2->todo ); sePrio = TRUE; break; } /* description */ case 2: { ret = description( con1->todo, con2->todo ); seDesc = TRUE; break; } /* deadline */ case 3: { ret = deadline( con1->todo, con2->todo ); seDeadline = TRUE; break; } default: ret = 0; break; }; /* * FIXME do better sorting if the first sort criteria * ret equals 0 start with complete and so on... */ /* twist it we're not ascending*/ if (!m_asc) ret = ret * -1; if ( ret ) return ret; // default did not gave difference let's try it other way around /* * General try if already checked if not test * and return * 1.Completed * 2.Priority * 3.Description * 4.DueDate */ if (!seComp ) { if ( (ret = completed( con1->todo, con2->todo ) ) ) { if (!m_asc ) ret *= -1; return ret; } } if (!sePrio ) { if ( (ret = priority( con1->todo, con2->todo ) ) ) { if (!m_asc ) ret *= -1; return ret; } } if (!seDesc ) { if ( (ret = description(con1->todo, con2->todo ) ) ) { if (!m_asc) ret *= -1; return ret; } } if (!seDeadline) { if ( (ret = deadline( con1->todo, con2->todo ) ) ) { if (!m_asc) ret *= -1; return ret; } } return 0; } private: bool m_asc; int m_sort; }; QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, int sortFilter, int cat ) { OTodoXMLVector vector(m_events.count(), asc,sortOrder ); QMap<int, OTodo>::Iterator it; int item = 0; bool bCat = sortFilter & 1 ? true : false; bool bOnly = sortFilter & 2 ? true : false; bool comp = sortFilter & 4 ? true : false; for ( it = m_events.begin(); it != m_events.end(); ++it ) { /* show category */ /* -1 == unfiled */ if ( bCat && cat == -1 ) { if(!(*it).categories().isEmpty() ) continue; }else if ( bCat && cat != 0) if (!(*it).categories().contains( cat ) ) { continue; } /* isOverdue but we should not show overdue - why?*/ /* if ( (*it).isOverdue() && !bOnly ) { qWarning("item is overdue but !bOnly"); continue; } */ if ( !(*it).isOverdue() && bOnly ) { continue; } if ((*it).isCompleted() && comp ) { continue; } OTodoXMLContainer* con = new OTodoXMLContainer(); con->todo = (*it); vector.insert(item, con ); item++; } vector.resize( item ); /* sort it now */ vector.sort(); /* now get the uids */ QArray<int> array( vector.count() ); for (uint i= 0; i < vector.count(); i++ ) { array[i] = ( vector.at(i) )->todo.uid(); } return array; }; void OTodoAccessXML::removeAllCompleted() { + QMap<int, OTodo> events = m_events; for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { if ( (*it).isCompleted() ) - m_events.remove( it ); + events.remove( it.key() ); } + m_events = events; } QBitArray OTodoAccessXML::supports()const { static QBitArray ar = sup(); return ar; } QBitArray OTodoAccessXML::sup() { QBitArray ar( OTodo::CompletedDate +1 ); ar.fill( true ); ar[OTodo::CrossReference] = false; ar[OTodo::State ] = false; ar[OTodo::Reminders] = false; ar[OTodo::Notifiers] = false; ar[OTodo::Maintainer] = false; return ar; } QArray<int> OTodoAccessXML::matchRegexp( const QRegExp &r ) const { QArray<int> m_currentQuery( m_events.count() ); uint arraycounter = 0; QMap<int, OTodo>::ConstIterator it; for (it = m_events.begin(); it != m_events.end(); ++it ) { if ( it.data().match( r ) ) m_currentQuery[arraycounter++] = it.data().uid(); } // Shrink to fit.. m_currentQuery.resize(arraycounter); return m_currentQuery; } |