#ifndef _KPILOT_PILOTDATABASE_H #define _KPILOT_PILOTDATABASE_H /* KPilot ** ** Copyright (C) 1998-2001 by Dan Pilone ** Copyright (C) 2003-2004 Reinhold Kainhofer ** Copyright (C) 2005-2006 Adriaan de Groot ** */ /* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program in a file called COPYING; if not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ** MA 02110-1301, USA. */ /* ** Bug reports and questions can be sent to kde-pim@kde.org */ #include "pilot.h" /** @file * This is the abstract base class for databases, which is used both * by local databases and by the serial databases held in the Pilot. */ /** * Methods to access a database on the pilot. * * NOTE: It is the users responsibility * to delete PilotRecords returned by * PilotDatabase methods when finished with them! */ class KDE_EXPORT PilotDatabase { public: PilotDatabase(const QString &name = QString::null); virtual ~PilotDatabase(); QString name() const { return fName; } ; /** * Debugging information: tally how many databases are created * or destroyed. Returns the count of currently existing databases. */ static int instanceCount(); /* -------------------- Abstract interface for subclasses ----------------- */ /** * Creates the database with the given creator, type and flags * on the given card (default is RAM). If the database already * exists, this function does nothing. */ virtual bool createDatabase(long creator=0, long type=0, int cardno=0, int flags=0, int version=0) = 0; /** * Deletes the database (by name, as given in the constructor, * the database name is stored depending on the implementation * of PilotLocalDatabase and PilotSerialDatabas) */ virtual int deleteDatabase()=0; /** Reads the application block info, returns size. */ virtual int readAppBlock(unsigned char* buffer, int maxLen) = 0; /** Writes the application block info. */ virtual int writeAppBlock(unsigned char* buffer, int len) = 0; /** Returns the number of records in the database. * If the database is not open, return -1. */ virtual unsigned int recordCount() const=0; /** Returns a QValueList of all record ids in the database. This implementation is really bad. */ virtual Pilot::RecordIDList idList(); /** Returns a list of all record ids that have been modified in the database. This implementation is really bad. */ virtual Pilot::RecordIDList modifiedIDList(); /** Reads a record from database by id, returns record length */ virtual PilotRecord* readRecordById(recordid_t id) = 0; /** Reads a record from database, returns the record length */ virtual PilotRecord* readRecordByIndex(int index) = 0; /** Reads the next record from database in category 'category' */ virtual PilotRecord* readNextRecInCategory(int category) = 0; /** * Reads the next record from database that has the dirty flag set. * If @p ind is non-NULL, *ind is set to the index of the current * record (i.e. before the record pointer moves to the next * modified record). */ virtual PilotRecord* readNextModifiedRec(int *ind=NULL) = 0; /** * Writes a new record to database (if 'id' == 0, one will be * assigned to newRecord) */ virtual recordid_t writeRecord(PilotRecord* newRecord) = 0; /** * Deletes a record with the given recordid_t from the database, * or all records, if @p all is set to true. The recordid_t will * be ignored in this case. * * Return value is negative on error, 0 otherwise. */ virtual int deleteRecord(recordid_t id, bool all=false) = 0; /** Resets all records in the database to not dirty. */ virtual int resetSyncFlags() = 0; /** Resets next record index to beginning */ virtual int resetDBIndex() = 0; /** Purges all Archived/Deleted records from Palm Pilot database */ virtual int cleanup() = 0; bool isOpen() const { return fDBOpen; } /** Returns some sensible human-readable identifier for * the database. Serial databases get Pilot:, local * databases return the full path. */ virtual QString dbPathName() const = 0; /** * Use this instead of RTTI to determine the type of a * PilotDatabase, for those cases where it's important. */ typedef enum { eNone=0, eLocalDB=1, eSerialDB=2 } DBType; virtual DBType dbType() const = 0; static inline bool isResource(struct DBInfo *info) { return (info->flags & dlpDBFlagResource); } protected: virtual void openDatabase() = 0; virtual void closeDatabase() = 0; void setDBOpen(bool yesno) { fDBOpen = yesno; } private: bool fDBOpen; QString fName; }; /** A template class for reading and interpreting a database. This removes * the need for a lot of boilerplate code that does the conversions. * Parameters are two interpretation classes: one for the KDE side of * things (e.g. Event) and one that interprets the Pilot's records into * a more sensible structure (e.g. PilotDatebookEntry). The mapping from * the KDE type to the Pilot type and vice-versa is done by the mapper * class's convert() functions. * * To interpret a database as pilot-link interpretations (e.g. as * PilotDatebookEntry records, not as Events) use the NullMapper class * below in combination with a template instantiation with kdetype==pilottype. * * The database interpreter intentionally has an interface similar to * that of a PilotDatabase, but it isn't one. */ template class DatabaseInterpreter { private: /** Interpret a PilotRecord as an object of type kdetype. */ kdetype *interpret(PilotRecord *r) { // NULL records return NULL kde objects. if (!r) return 0; // Interpret the binary blob as a pilot-link object. pilottype *a = new pilottype(r); // The record is now obsolete. delete r; // Interpretation failed. if (!a) { return 0; } // Now convert to KDE type. kdetype *t = mapper::convert(a); // The NULL mapper just returns the pointer a, so we // need to check if anything has changed before deleting. if ( (void *)t != (void *)a ) { delete a; } return t; } public: /** Constructor. Interpret the database @p d. */ DatabaseInterpreter(PilotDatabase *d) : fDB(d) { } ; /** Reads a record from database by @p id */ kdetype *readRecordById(recordid_t id) { return interpret(fDB->readRecordById(id)); } /** Reads a record from database with index @p index */ kdetype *readRecordByIndex(int index) { return interpret(fDB->readRecordByIndex(index)); } /** Reads the next record from database in category @p category */ kdetype *readNextRecInCategory(int category) { return interpret(fDB->readNextRecInCategory(category)); } /** * Reads the next record from database that has the dirty flag set. * If @p ind is non-NULL, *ind is set to the index of the current * record (i.e. before the record pointer moves to the next * modified record). */ kdetype *readNextModifiedRec(int *ind=NULL) { return interpret(fDB->readNextModifiedRec(ind)); } /** Retrieve the database pointer; this is useful to just pass * around DatabaseInterpreter objects as if they are databases, * and then perform DB operations on the database it wraps. */ PilotDatabase *db() const { return fDB; } protected: PilotDatabase *fDB; } ; /** NULL mapper class; the conversions here don't @em do anything, * so you can use this when you only need 1 conversion step (from * PilotRecord to PilotDatebookEntry, for instance) instead of 2. */ template class NullMapper { public: /** NULL Conversion function. */ static T *convert(T *t) { return t; } } ; #endif