/***************************************************************************
copyright : (C) 1999 by Edwin Glaser
email : edwin@pannenleiter.de
version : $Id: dbdatasource.h,v 1.1.1.1 2000/02/07 21:41:55 ege Exp $
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef DBDATASOURCE_H
#define DBDATASOURCE_H
#include <qobject.h>
#include <qdatetime.h>
class DBRecord;
class DBLabel;
class DBLabelFactory;
class DBLineEdit;
class DBLineEditFactory;
class DBMultiLineEdit;
class DBMultiLineEditFactory;
class DBListBox;
class DBListBoxFactory;
class DBComboBox;
class DBComboBoxFactory;
class DBEditComboBoxFactory;
class DBGrid;
class DBNavigator;
class DBValueAdaptor;
class DBLookupAdaptor;
class DBPainter;
class DBWidgetFactory;
class DBField;
class DBColumnDescription;
class DBTableDescription;
class DBMasterDescription;
/** General part of the manager.
*
* The manager consists of two classes.
* DBDatasource keeps track of the state and emits the signals.
* A class derrived from DBRecord handles the database connection.
*
* @author Edwin Glaser
* @version $Name: $ $Date: 2000/02/07 21:41:55 $
*/
class DBDataSource : public QObject
{
Q_OBJECT
public:
enum state { Inactive, Error, Browse, Edit, Insert, CalcFields, DontChange};
static char *stateNames[6];
bool inCascadingRemove;
protected:
DBRecord *record;
state currentState;
long prevCursor;
long calcCursor;
long browseCursor;
int widgetsDisabled;
state saveState;
DBDataSource *master;
DBMasterDescription *masterDef;
bool autoEdit;
bool autoPost;
bool autoRefresh;
bool userReadOnly;
bool suspendUpdate;
bool isAborted;
bool userEnabled;
void setState(state newState, bool force = false);
void setCursor(state newState = DontChange, bool forceState = false, bool force = false, bool isCopy = false);
bool setEditable(bool force = false);
bool checkPost(bool force = false);
bool openIt(bool forceReopen);
void closeIt();
bool moveWithoutCheck(state newState, bool forceState, long pos);
public:
/** The constructor expects a record created with new. The destructor will delete the record.
*/
DBDataSource(DBRecord *rec);
/** Destructor.
*/
virtual ~DBDataSource();
/** Thin wrapper for DBRecord::setQuery
*
* @see DBRecord
*/
virtual void setQuery(const QString query, bool removeTables = false);
/** Thin wrapper for DBRecord::setTable
*
* @see DBRecord
*/
virtual void addTable(const char *table, const char *primaries, const char *columns);
/** Restricts the dataset to the correspontin detail-recors of the master-record.
* You have to call setQuery with a proper select statement.
* It must include parameters for the foreign keys eg. "select * from order where custid = ?"
*
* @param master The master of this detail datasource.
* @param join This string describes the foreign keys of the select statement.
* Pairs of index=index seperated by blanks eg. "1=0 2=1".
* The first one is the index of the field of the master datasource.
* The second is the index of the parameter.
* @param init Appending a new record will initialize the foreign keys from the corresonding fields.
* Pairs of index=index seperated by blanks eg. "1=0 2=1".
* The first one is the index of the field of the master datasource.
* The second is the index of the field of this source.
* @param cascadeRemove If true, removeing a master record also removes the detail records.
*/
virtual void setMaster(DBDataSource *master, const char *join, const char *init = 0, bool cascadeRemove = false);
/** Thin wrapper for DBRecord::getNumCols
*/
int getNumCols();
/** Thin wrapper for DBRecord::getColumnName
*/
const char *getColumnName(int col);
/** Thin wrapper for DBRecord::getColumnQualifierName
*/
const char *getColumnQualifierName(int col);
/** Thin wrapper for DBRecord::getColumnType
*
* @return DBTypes::TypeLong DBTypes::TypeDouble DBTypes::TypeDate DBTypes::TypeTime DBTypes::TypeDateTime DBTypes::TypeBinary DBTypes::TypeString
*/
int getColumnType(int col);
int getColumnType(char *column) { return getColumnType(getColumnIdx(column)); };
int getColumnType(char *table, char *column) { return getColumnType(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnTypeName
*/
const char *getColumnTypeName(int col);
const char *getColumnTypeName(char *column) { return getColumnTypeName(getColumnIdx(column)); };
const char *getColumnTypeName(char *table, char *column) { return getColumnTypeName(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnLength
*/
long getColumnLength(int col);
long getColumnLength(char *column) { return getColumnLength(getColumnIdx(column)); };
long getColumnLength(char *table, char *column) { return getColumnLength(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnPrecision
*/
int getColumnPrecision(int col);
int getColumnPrecision(char *column) { return getColumnPrecision(getColumnIdx(column)); };
int getColumnPrecision(char *table, char *column) { return getColumnPrecision(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnScale
*/
int getColumnScale(int col);
int getColumnScale(char *column) { return getColumnScale(getColumnIdx(column)); };
int getColumnScale(char *table, char *column) { return getColumnScale(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnDisplaySize
*/
long getColumnDisplaySize(int col);
long getColumnDisplaySize(char *column) { return getColumnDisplaySize(getColumnIdx(column)); };
long getColumnDisplaySize(char *table, char *column) { return getColumnDisplaySize(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnNullable
*/
int getColumnNullable(int col);
int getColumnNullable(char *column) { return getColumnNullable(getColumnIdx(column)); };
int getColumnNullable(char *table, char *column) { return getColumnNullable(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnUnsigned
*/
int getColumnUnsigned(int col);
int getColumnUnsigned(char *column) { return getColumnUnsigned(getColumnIdx(column)); };
int getColumnUnsigned(char *table, char *column) { return getColumnUnsigned(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnMoney
*/
int getColumnMoney(int col);
int getColumnMoney(char *column) { return getColumnMoney(getColumnIdx(column)); };
int getColumnMoney(char *table, char *column) { return getColumnMoney(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnUpdatable
*/
int getColumnUpdatable(int col);
int getColumnUpdatable(char *column) { return getColumnUpdatable(getColumnIdx(column)); };
int getColumnUpdatable(char *table, char *column) { return getColumnUpdatable(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getColumnAutoIncrement
*/
int getColumnAutoIncrement(int col);
int getColumnAutoIncrement(char *column) { return getColumnAutoIncrement(getColumnIdx(column)); };
int getColumnAutoIncrement(char *table, char *column) { return getColumnAutoIncrement(getColumnIdx(table, column)); };
/** Thin wrapper for DBRecord::getNumRows
*/
long getNumRows();
/** The datasource is active.
*/
bool isActive() { return currentState != Inactive && currentState != Error && currentState != CalcFields; };
/** An error occured.
*/
bool isError() { return currentState == Error; };
/** A value of the record was changed but not posted to the database.
*/
bool isEditMode() { return currentState == Edit; };
/** A record was appended but not posted to the database.
*/
bool isInsertMode() { return currentState == Insert; };
/** You can call setValue / getValue.
*/
bool hasRecord() { return currentState != Inactive && currentState != Error && !isBOF() && !isEOF(); };
/** You cal call post
*/
bool isReadOnly();
/** A widget may offer editing.
*/
bool isEditable() { return hasRecord() && !isReadOnly() && (autoEdit || currentState == Edit || currentState == Insert); };
/** SetValue will switch to edit mode.
*/
bool isAutoEdit() { return autoEdit; };
/** Changed fields will be written to the database before changing the database cursor.
*/
bool isAutoPost() { return autoPost; };
/** Returns the state: Inactive, Error, Browse, Edit, Insert, CalcFields
*/
state getState() { return currentState; };
/** Translates the state id to a string representation.
*/
const char *getStateName(state s) { return stateNames[s]; };
/** Thin wrapper for DBRecord::getErrorInfo
*/
const QString &getErrorInfo();
/** Thin wrapper for DBRecord::getCursor
*/
long getCursor();
/** Is the cursor before th first record ?
*/
bool isBOF();
/** Is the cursor behind the last record ?
*/
bool isEOF();
/** Wrapper for DBRecord::getValue
*
* @param col the column index, 0 based
* @param format A printf or strftime format string. WARNING the resust string must not exeed 8000 bytes!
* The format must correspond to getColumnType()
* <table>
* <tr><td>type</td><td>called by</td></tr>
* <tr><td>DBTypes::TypeLong</td><td>sprintf(buf, format, *(long *)buffer);</td></tr>
* <tr><td>DBTypes::TypeDouble</td><td>sprintf(buf, format, *(double*)buffer);</td></tr>
* <tr><td>DBTypes::TypeDate</td><td>strftime(buf, 99, format &t);</td></tr>
* <tr><td>DBTypes::TypeTime</td><td>strftime(buf, 99, format &t);</td></tr>
* <tr><td>DBTypes::TypeDateTime</td><td>strftime(buf, 99, format &t);</td></tr>
* <tr><td>DBTypes::TypeBinary</td><td>sprintf(buf, format, (char *)buffer);</td></tr>
* <tr><td>DBTypes::TypeString</td><td>sprintf(buf, format, (char *)buffer);</td></tr>
* </table>
*/
QString getQString(int col, const char *format = 0);
QString getQString(char *column) { return getQString(getColumnIdx(column)); };
QString getQString(char *table, char *column) { return getQString(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::getValue
*/
QDate getQDate(int col);
QDate getQDate(char *column) { return getQDate(getColumnIdx(column)); };
QDate getQDate(char *table, char *column) { return getQDate(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::getValue
*/
QTime getQTime(int col);
QTime getQTime(char *column) { return getQTime(getColumnIdx(column)); };
QTime getQTime(char *table, char *column) { return getQTime(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::getValue
*/
QDateTime getQDateTime(int col);
QDateTime getQDateTime(char *column) { return getQDateTime(getColumnIdx(column)); };
QDateTime getQDateTime(char *table, char *column) { return getQDateTime(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::getValue
*/
double getDouble(int col);
double getDouble(char *column) { return getDouble(getColumnIdx(column)); };
double getDouble(char *table, char *column) { return getDouble(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::getValue
*/
long getLong(int col);
long getLong(char *column) { return getLong(getColumnIdx(column)); };
long getLong(char *table, char *column) { return getLong(getColumnIdx(table, column)); };
/** Has column a null value
*/
bool isNull(int col);
bool isNull(char *column) { return getLong(getColumnIdx(column)); };
bool isNull(char *table, char *column) { return getLong(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(const QString &str, int column);
bool setValue(const QString &str, char *column) { return setValue(str, getColumnIdx(column)); };
bool setValue(const QString &str, char *table, char *column) { return setValue(str, getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(const QDate &val, int column);
bool setValue(const QDate &val, char *column) { return setValue(val, getColumnIdx(column)); };
bool setValue(const QDate &val, char *table, char *column) { return setValue(val, getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(const QTime &val, int column);
bool setValue(const QTime &val, char *column) { return setValue(val, getColumnIdx(column)); };
bool setValue(const QTime &val, char *table, char *column) { return setValue(val, getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(const QDateTime &val, int column);
bool setValue(const QDateTime &val, char *column) { return setValue(val, getColumnIdx(column)); };
bool setValue(const QDateTime &val, char *table, char *column) { return setValue(val, getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(double num, int column);
bool setValue(double num, char *column) { return setValue(num, getColumnIdx(column)); };
bool setValue(double num, char *table, char *column) { return setValue(num, getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setValue
* Switches to edit mode, if autoedit is set.
*/
bool setValue(long num, int column);
bool setValue(long num, char *column) { return setValue(num, getColumnIdx(column)); };
bool setValue(long num, char *table, char *column) { return setValue(num, getColumnIdx(table, column)); };
/** sets the value to null
* Switches to edit mode, if autoedit is set.
*/
bool setNull(int column);
bool setNull(char *column) { return setNull(getColumnIdx(column)); };
bool setNull(char *table, char *column) { return setNull(getColumnIdx(table, column)); };
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(const QString &str, int column);
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(const QDate &val, int column);
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(const QTime &val, int column);
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(const QDateTime &val, int column);
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(double val, int column);
/** Wrapper for DBRecord::setParameter
*/
bool setParameter(long val, int column);
/** Get the column index of the column, 0 based
*
* @param column the name of the column
*/
int getColumnIdx(char *column);
/** Get the column index of the column, 0 based
*
* @param table the name of the table respectively the alias
* (Id did'n work for me, the mysql odbc driver hides the tablename ???)
* @param column the name of the column
*/
int getColumnIdx(char *table, char *column);
protected slots:
void masterStateChanged();
void masterCursorChanged();
void masterRemoved();
public slots:
/** Opens the DBRecord.
*/
virtual bool open();
/** Closes the DBRecord.
*/
virtual void close();
/** SetValue will switch to edit mode, default: false.
*/
virtual void setAutoEdit(bool on);
/** Changed fields will be written to the database before changing the database cursor, default false.
*/
virtual void setAutoPost(bool on);
/** Fetch resultset from database after post, default true.
*/
virtual void setAutoRefresh(bool on);
/** Marks datasource as readonly. If the DBRecord is readonly the datasource will stay readonly!
*/
virtual void setReadOnly(bool on);
/** Switches to edit mode.
*/
virtual bool edit();
/** Apends a record and initializes it with 0 resp. "".
* Switches to insert mode.
*
* @param setNull True: init with null values if column allows it.
* False init with 0 or "".
*/
virtual bool append();
virtual bool append(bool setNull);
/** Apends a record and initializes it from the current record.
* Switches to insert mode.
*/
virtual bool copy();
/** Deletes the current record from the database.
*/
virtual bool remove();
/** Insert the current record if the datasource is in insert mode.
* Updates the database if the datasource is in edit mode.
*/
virtual bool post();
/** Fetch resultset from database.
*/
virtual bool refresh();
/** Cancels the last edit/append/copy
*/
virtual bool cancel();
/** If you call abort from a slot connected to a beforeXXX signel, it will stop the operation.
*/
virtual void abort();
/** Wrapper for DBRecord::first
*/
virtual bool first();
/** Wrapper for DBRecord::prior
*/
virtual bool prior();
/** Wrapper for DBRecord::next
*/
virtual bool next();
/** Wrapper for DBRecord::last
*/
virtual bool last();
/** Wrapper for DBRecord::moveBy
*/
virtual bool moveBy(long);
/** Wrapper for DBRecord::moveTo
*/
virtual bool moveTo(long);
/** This method saves the current state and suspresses all signals.
*/
virtual void disableWidgets();
/** This method resores the state.
*/
virtual void enableWidgets();
signals:
/** The state of the datasource changed.
*/
void stateChanged();
/** The position of the database cursor changed.
* If an operation changes the state and the cursor stateChanged is emited first.
* The datasource also emits cursorChanged if the set changed.
*/
void cursorChanged();
/** A value of a field changed.
* If the change is caused by a cursor movement, only cursorChanged is emited.
*/
void dataChanged(int column);
/** Something wants to switch to edit mode. You can call abort to keep the old state.
*/
void beforeEdit();
/** The datasource is now in edit mode.
*/
void afterEdit();
/** Something wants to switch to insert mode. You can call abort to keep the old state.
*
* @param isCopy True if the new record will be initialized from the current record.
*/
void beforeAppend(bool isCopy);
/** The datasource is now in insert mode.
*
* @param isCopy True if the new record was initialized from the current record.
*/
void afterAppend(bool isCopy);
/** Something wants to delete the current record from the database. You can call abort to keep the old state.
*/
void beforeRemove();
void beforeRemove2();
/** The database record is deleted and the next current record is now the current one.
*/
void afterRemove();
/** Sonething wants to post the current record to the database. You can call abort to keep the old state.
*/
void beforePost(bool isInsert);
/** The chaned values have been written to the database.
*/
void afterPost(bool isInsert);
void afterPost2();
/** Sonething wants to cancel the edit/append/copy call. You can call abort to keep the old state.
*/
void beforeCancel();
/** The edit/append/copy is canceled.
*/
void afterCancel();
void afterCancel2();
/** A beforeXXX slot aborted an operation.
*/
void aborted();
/** The dataset fetched a record from the database.
* A setValue call will not be mark the record for update.
*/
void calcFields();
/** A append or copy created a new record.
* A setValue call will not be mark the record for insert.
*/
void newRecord(bool isCopy);
};
inline int DBDataSource::getColumnIdx(char *column)
{
const char *cn;
for ( int i = 0; (cn = getColumnName(i)); i++ )
{
if ( strcmp(column, cn) == 0 ) return i;
}
return -1;
}
inline int DBDataSource::getColumnIdx(char *table, char *column)
{
const char *cn;
for ( int i = 0; (cn = getColumnName(i)); i++ )
{
if ( strcmp(column, cn) == 0 && strcmp(getColumnQualifierName(i), cn) == 0 ) return i;
}
return -1;
}
#endif
Documentation generated by eg@wonko on Sam Feb 19 00:09:53 MET 2000