summaryrefslogtreecommitdiffstats
path: root/kexi/widget/tableview/kexitableviewdata.h
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/widget/tableview/kexitableviewdata.h')
-rw-r--r--kexi/widget/tableview/kexitableviewdata.h540
1 files changed, 540 insertions, 0 deletions
diff --git a/kexi/widget/tableview/kexitableviewdata.h b/kexi/widget/tableview/kexitableviewdata.h
new file mode 100644
index 00000000..970d1d23
--- /dev/null
+++ b/kexi/widget/tableview/kexitableviewdata.h
@@ -0,0 +1,540 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
+ Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
+ Copyright (C) 2003-2006 Jaroslaw Staniek <js@iidea.pl>
+
+ 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.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+ Original Author: Till Busch <till@bux.at>
+ Original Project: buX (www.bux.at)
+*/
+
+#ifndef KEXITABLEVIEWDATA_H
+#define KEXITABLEVIEWDATA_H
+
+#include <qptrlist.h>
+#include <qvariant.h>
+#include <qvaluevector.h>
+#include <qstring.h>
+#include <qobject.h>
+
+#include "kexitableitem.h"
+
+#include <kexidb/error.h>
+
+namespace KexiDB {
+class Field;
+class QuerySchema;
+class RowEditBuffer;
+class Cursor;
+}
+
+namespace KexiUtils {
+class Validator;
+}
+class KexiTableViewData;
+
+
+/*! Single column definition. */
+class KEXIDATATABLE_EXPORT KexiTableViewColumn {
+ public:
+ typedef QPtrList<KexiTableViewColumn> List;
+ typedef QPtrListIterator<KexiTableViewColumn> ListIterator;
+
+ /*! Not db-aware ctor. if \a owner is true, the field \a will be owned by this column,
+ so you shouldn't care about destroying this field. */
+ KexiTableViewColumn(KexiDB::Field& f, bool owner = false);
+
+ /*! Not db-aware, convenience ctor, like above. The field is created using specified parameters that are
+ equal to these accepted by KexiDB::Field ctor. The column will be the owner
+ of this automatically generated field.
+ */
+ KexiTableViewColumn(const QString& name, KexiDB::Field::Type ctype,
+ uint cconst = KexiDB::Field::NoConstraints,
+ uint options = KexiDB::Field::NoOptions,
+ uint length=0, uint precision=0,
+ QVariant defaultValue=QVariant(),
+ const QString& caption = QString::null,
+ const QString& description = QString::null,
+ uint width = 0);
+
+ /*! Not db-aware, convenience ctor, simplified version of the above. */
+ KexiTableViewColumn(const QString& name, KexiDB::Field::Type ctype, const QString& caption,
+ const QString& description = QString::null);
+
+ //! Db-aware version.
+ KexiTableViewColumn(const KexiDB::QuerySchema &query, KexiDB::QueryColumnInfo& aColumnInfo,
+ KexiDB::QueryColumnInfo* aVisibleLookupColumnInfo = 0);
+
+ virtual ~KexiTableViewColumn();
+
+ virtual bool acceptsFirstChar(const QChar& ch) const;
+
+ /*! \return true if the column is read-only
+ For db-aware column this can depend on whether the column
+ is in parent table of this query. \sa setReadOnly() */
+ bool isReadOnly() const;
+
+//TODO: synchronize this with table view:
+ //! forces readOnly flag to be set to \a ro
+ inline void setReadOnly(bool ro) { m_readOnly=ro; }
+
+ //! Column visibility. By default column is visible.
+ inline bool visible() const { return columnInfo ? columnInfo->visible : m_visible; }
+
+ //! Changes column visibility.
+ inline void setVisible(bool v) {
+ if (columnInfo)
+ columnInfo->visible = v;
+ m_visible=v;
+ }
+
+ /*! Sets icon for displaying in the caption area (header). */
+ void setIcon(const QIconSet& icon) { m_icon = icon; }
+
+ /*! \return bame of icon displayed in the caption area (header). */
+ QIconSet icon() const { return m_icon; }
+
+ /*! If \a visible is true, caption has to be displayed in the column's header,
+ (or field's name if caption is empty. True by default. */
+ void setHeaderTextVisible(bool visible) { m_headerTextVisible = visible; }
+
+ /*! \return true if caption has to be displayed in the column's header,
+ (or field's name if caption is empty. */
+ bool isHeaderTextVisible() const { return m_headerTextVisible; }
+
+ /*! \return whatever is available:
+ - field's caption
+ - or field's alias (from query)
+ - or finally - field's name */
+ inline QString captionAliasOrName() const { return m_captionAliasOrName; }
+
+ /*! Assigns validator \a v for this column.
+ If the validator has no parent object, it will be owned by the column,
+ so you shouldn't care about destroying it. */
+ void setValidator( KexiUtils::Validator* v );
+
+ //! \return validator assigned for this column of 0 if there is no validator assigned.
+ inline KexiUtils::Validator* validator() const { return m_validator; }
+
+ /*! For not-db-aware data only:
+ Sets related data \a data for this column, what defines simple one-field,
+ one-to-many relationship between this column and the primary key in \a data.
+ The relationship will be used to generate a popup editor instead of just regular editor.
+ This assignment has no result if \a data has no primary key defined.
+ \a data is owned, so is will be destroyed when needed. It is also destroyed
+ when another data (or NULL) is set for the same column. */
+ void setRelatedData(KexiTableViewData *data);
+
+ /*! For not-db-aware data only:
+ Related data \a data for this column, what defines simple one-field.
+ NULL by default. \sa setRelatedData() */
+ inline KexiTableViewData *relatedData() const { return m_relatedData; }
+
+ /*! \return field for this column.
+ For db-aware information is taken from \a columnInfo member. */
+ inline KexiDB::Field* field() const { return m_field; }
+
+ /*! Only usable if related data is set (ie. this is for combo boxes).
+ Sets 'editable' flag for this column, what means a new value can be entered
+ by hand. This is similar to QComboBox::setEditable(). */
+ void setRelatedDataEditable(bool set);
+
+ /*! Only usable if related data is set (ie. this is for combo boxes).
+ \return 'editable' flag for this column.
+ False by default. @see setRelatedDataEditable(bool). */
+ inline bool relatedDataEditable() const { return m_relatedDataEditable; }
+
+ /*! A rich field information for db-aware data.
+ For not-db-aware data it is always 0 (use field() instead). */
+ KexiDB::QueryColumnInfo* columnInfo;
+
+ /*! A rich field information for db-aware data. Specifies information for a column
+ that should be visible instead of columnInfo. For example case see
+ @ref KexiDB::QueryColumnInfo::Vector KexiDB::QuerySchema::fieldsExpanded(KexiDB::QuerySchema::FieldsExpandedOptions options = Default)
+
+ For not-db-aware data it is always 0. */
+ KexiDB::QueryColumnInfo* visibleLookupColumnInfo;
+
+ bool isDBAware : 1; //!< true if data is stored in DB, not only in memeory
+
+/* QString caption;
+ int type; //!< one of KexiDB::Field::Type
+ uint width;
+*/
+// bool isNull() const;
+
+/* virtual QString caption() const;
+ virtual void setCaption(const QString& c);
+ */
+ protected:
+ //! special ctor that do not allocate d member;
+ KexiTableViewColumn(bool);
+
+ void init();
+
+ QString m_captionAliasOrName;
+
+ QIconSet m_icon;
+
+ KexiUtils::Validator* m_validator;
+
+ //! Data that this column is assigned to.
+ KexiTableViewData* m_data;
+
+ KexiTableViewData* m_relatedData;
+ uint m_relatedDataPKeyID;
+
+ KexiDB::Field* m_field;
+
+ bool m_readOnly : 1;
+ bool m_fieldOwned : 1;
+ bool m_visible : 1;
+ bool m_relatedDataEditable : 1;
+ bool m_headerTextVisible : 1;
+
+ friend class KexiTableViewData;
+};
+
+
+/*! List of column definitions. */
+//typedef QValueVector<KexiTableViewColumn> KexiTableViewColumnList;
+
+typedef QPtrList<KexiTableItem> KexiTableViewDataBase;
+
+/*! Reimplements QPtrList to allow configurable sorting and more.
+ Original author: Till Busch.
+ Reimplemented by Jaroslaw Staniek.
+*/
+class KEXIDATATABLE_EXPORT KexiTableViewData : public QObject, protected KexiTableViewDataBase
+{
+ Q_OBJECT
+
+public:
+ typedef QPtrListIterator<KexiTableItem> Iterator;
+
+ //! not db-aware version
+ KexiTableViewData();
+
+ //! db-aware version
+ KexiTableViewData(KexiDB::Cursor *c);
+
+//TODO: make this more generic: allow to add more columns!
+ /*! Defines two-column table usually used with comboboxes.
+ First column is invisible and contains key values.
+ Second column and contains user-visible value.
+ @param keys a list of keys
+ @param values a list of text values (must be of the same length as keys list)
+ @param keyType a type for keys
+ @param valueType a type for values
+ */
+ KexiTableViewData(
+ const QValueList<QVariant> &keys, const QValueList<QVariant> &values,
+ KexiDB::Field::Type keyType = KexiDB::Field::Text,
+ KexiDB::Field::Type valueType = KexiDB::Field::Text);
+
+ /*! Like above constructor, but keys and values are not provided.
+ You can do this later by calling append(KexiTableItem*) method.
+ (KexiTableItem object must have exactly two columns)
+ */
+ KexiTableViewData(KexiDB::Field::Type keyType, KexiDB::Field::Type valueType);
+
+ virtual ~KexiTableViewData();
+//js void setSorting(int key, bool order=true, short type=1);
+
+ /*! Preloads all rows provided by cursor (only for db-aware version). */
+//! @todo change to bool and return false on error!
+ void preloadAllRows();
+
+ /*! Sets sorting for \a column. If \a column is -1, sorting is disabled. */
+ void setSorting(int column, bool ascending=true);
+
+ /*! \return the column number by which the data is sorted,
+ or -1 if sorting is disabled. In this case sortingOrder() will return 0.
+ Initial sorted column number for data after instantiating object is -1. */
+ inline int sortedColumn() const { return m_sortedColumn; }
+
+ /*! \return 1 if ascending sort order is set, -1 id descending sort order is set,
+ or 0 if no sorting is set. This is independent of whether data is sorted now.
+ Initial sorting for data after instantiating object is 0. */
+ inline int sortingOrder() const { return m_order; }
+
+ /*! Adds column \a col.
+ Warning: \a col will be owned by this object, and deleted on its destruction. */
+ void addColumn( KexiTableViewColumn* col );
+
+ inline int globalColumnID(int visibleID) { return m_globalColumnsIDs.at( visibleID ); }
+ inline int visibleColumnID(int globalID) { return m_visibleColumnsIDs.at( globalID ); }
+
+ /*virtual?*/
+ /*! \return true if this db-aware data set. */
+ inline bool isDBAware() { return m_cursor; }
+
+ /*! For db-aware data set only: table name is returned;
+ equivalent to cursor()->query()->parentTable()->name(). */
+ QString dbTableName() const;
+
+ inline KexiDB::Cursor* cursor() const { return m_cursor; }
+
+ inline uint columnsCount() const { return columns.count(); }
+
+ inline KexiTableViewColumn* column(uint c) { return columns.at(c); }
+
+ /*! Columns information */
+ KexiTableViewColumn::List columns;
+
+ /*! \return true if data is not editable. Can be set using setReadOnly()
+ but it's still true if database cursor returned by cursor()
+ is not 0 and has read-only connection. */
+ virtual bool isReadOnly() const;
+
+ /*! Sets readOnly flag for this data.
+ If \a set is true, insertingEnabled flag will be cleared automatically.
+ \sa isInsertingEnabled() */
+ virtual void setReadOnly(bool set);
+
+ /*! \return true if data inserting is enabled (the default). */
+ virtual bool isInsertingEnabled() const { return m_insertingEnabled; }
+
+ /*! Sets insertingEnabled flag. If true, empty row is available
+ If \a set is true, read-only flag will be cleared automatically.
+ \sa setReadOnly() */
+ virtual void setInsertingEnabled(bool set);
+
+ /*! Clears and initializes internal row edit buffer for incoming editing.
+ Creates buffer using KexiDB::RowEditBuffer(false) (false means not db-aware type)
+ if our data is not db-aware,
+ or db-aware buffer if data is db-aware (isDBAware()==true).
+ \sa KexiDB::RowEditBuffer
+ */
+ void clearRowEditBuffer();
+
+ /*! Updates internal row edit buffer: currently edited column \a col (number \a colnum)
+ has now assigned new value of \a newval.
+ Uses column's caption to address the column in buffer
+ if the buffer is of simple type, or db-aware buffer if (isDBAware()==true).
+ (then fields are addressed with KexiDB::Field, instead of caption strings).
+ If \a allowSignals is true (the default), aboutToChangeCell() signal is emitted.
+ \a visibleValueForLookupField allows to pass visible value (usually a text)
+ for a lookup field (only reasonable if col->visibleLookupColumnInfo != 0).
+ Note that \a newval may be changed in aboutToChangeCell() signal handler.
+ \sa KexiDB::RowEditBuffer */
+ bool updateRowEditBufferRef(KexiTableItem *item,
+ int colnum, KexiTableViewColumn* col, QVariant& newval, bool allowSignals = true,
+ QVariant *visibleValueForLookupField = 0);
+
+ /*! Added for convenience. Like above but \a newval is passed by value. */
+ inline bool updateRowEditBuffer(KexiTableItem *item, int colnum, KexiTableViewColumn* col,
+ QVariant newval, bool allowSignals = true)
+ {
+ QVariant newv(newval);
+ return updateRowEditBufferRef(item, colnum, col, newv, allowSignals);
+ }
+
+ /*! Added for convenience. Like above but it's assumed that \a item item's columns are ordered
+ like in table view, not like in form view. Don't use this with form views. */
+ inline bool updateRowEditBuffer(KexiTableItem *item, int colnum,
+ QVariant newval, bool allowSignals = true)
+ {
+ KexiTableViewColumn* col = columns.at(colnum);
+ return col ? updateRowEditBufferRef(item, colnum, col, newval, allowSignals) : false;
+ }
+
+ inline KexiDB::RowEditBuffer* rowEditBuffer() const { return m_pRowEditBuffer; }
+
+ /*! \return last operation's result information (always not null). */
+ inline KexiDB::ResultInfo* result() { return &m_result; }
+
+ bool saveRowChanges(KexiTableItem& item, bool repaint = false);
+
+ bool saveNewRow(KexiTableItem& item, bool repaint = false);
+
+ bool deleteRow(KexiTableItem& item, bool repaint = false);
+
+ /*! Deletes rows (by number) passed with \a rowsToDelete.
+ Currently, this method is only for non data-aware tables. */
+ void deleteRows( const QValueList<int> &rowsToDelete, bool repaint = false );
+
+ /*! Deletes all rows. Works either for db-aware and non db-aware tables.
+ Column's definition is not changed.
+ For db-aware version, all rows are removed from a database.
+ Row-edit buffer is cleared.
+
+ If \a repaint is true, reloadRequested() signal
+ is emitted after deleting (if at least one row was deleted),
+ so presenters can repaint their contents.
+
+ \return true on success. */
+ virtual bool deleteAllRows(bool repaint = false);
+
+ /*! @internal method, used mostly by specialized classes like KexiTableView.
+ Clears internal row structures. Row-edit buffer is cleared.
+ Does not touch data @ database backend.
+ Use deleteAllRows() to safely delete all rows. */
+ virtual void clearInternal();
+
+ /*! Inserts new \a item at index \a index.
+ \a item will be owned by this data object.
+ Note: Reasonable only for not not-db-aware version. */
+ void insertRow(KexiTableItem& item, uint index, bool repaint = false);
+
+/*TODO: add this as well?
+ void insertRow(KexiTableItem& item, KexiTableItem& aboveItem); */
+
+ //! \return index of autoincremented column. The result is cached.
+//! \todo what about multiple autoinc columns?
+//! \todo what about changing column order?
+ int autoIncrementedColumn();
+
+ //! Emits reloadRequested() signal to reload presenters.
+ void reload() { emit reloadRequested(); }
+
+ inline KexiTableItem* at( uint index ) { return KexiTableViewDataBase::at(index); }
+ inline virtual uint count() const { return KexiTableViewDataBase::count(); }
+ inline bool isEmpty () const { return KexiTableViewDataBase::isEmpty(); }
+ inline KexiTableItem* first() { return KexiTableViewDataBase::first(); }
+ inline KexiTableItem* last() { return KexiTableViewDataBase::last(); }
+ inline int findRef( const KexiTableItem* item ) { return KexiTableViewDataBase::findRef(item); }
+ inline void sort() { KexiTableViewDataBase::sort(); }
+ inline bool removeFirst() { return KexiTableViewDataBase::removeFirst(); }
+ inline bool removeLast() { return KexiTableViewDataBase::removeLast(); }
+ inline void append( const KexiTableItem* item ) { KexiTableViewDataBase::append(item); }
+ inline void prepend( const KexiTableItem* item ) { KexiTableViewDataBase::prepend(item); }
+ inline Iterator iterator() { return Iterator(*this); }
+ inline Iterator* createIterator() { return new Iterator(*this); }
+
+ /*! \return true if ROWID information is stored within every row.
+ Only reasonable for db-aware version. ROWID information is available
+ if DriverBehaviour::ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE == false
+ for a KexiDB database driver and a table has no primary key defined.
+ Phisically, ROWID information is stored after last KexiTableItem's element,
+ so every KexiTableItem's length is expanded by one. */
+ inline bool containsROWIDInfo() const { return m_containsROWIDInfo; }
+
+ inline KexiTableItem* createItem() const
+ { return new KexiTableItem(m_itemSize); }
+
+public slots:
+ //! @internal The same as QObject::deleteLater() but also sets smart pointer m_cursor to 0 to avoid crashes...
+ void deleteLater();
+
+signals:
+ void destroying();
+
+ /*! Emitted before change of the single, currently edited cell.
+ Connect this signal to your slot and set \a result->success to false
+ to disallow this change. You can also change \a newValue to other value,
+ or change other columns in \a item row. */
+ void aboutToChangeCell(KexiTableItem *item, int colnum, QVariant& newValue,
+ KexiDB::ResultInfo* result);
+
+ /*! Emited before inserting of a new, current row.
+ Connect this signal to your slot and set \a result->success to false
+ to disallow this inserting. You can also change columns in \a item row. */
+ void aboutToInsertRow(KexiTableItem *item, KexiDB::ResultInfo* result, bool repaint);
+
+ /*! Emited before changing of an edited, current row.
+ Connect this signal to your slot and set \a result->success to false
+ to disallow this change. You can also change columns in \a item row. */
+ void aboutToUpdateRow(KexiTableItem *item, KexiDB::RowEditBuffer* buffer,
+ KexiDB::ResultInfo* result);
+
+ void rowUpdated(KexiTableItem*); //!< Current row has been updated
+
+ void rowInserted(KexiTableItem*, bool repaint); //!< A row has been inserted
+
+ //! A row has been inserted at \a index position (not db-aware data only)
+ void rowInserted(KexiTableItem*, uint index, bool repaint);
+
+ /*! Emited before deleting of a current row.
+ Connect this signal to your slot and set \a result->success to false
+ to disallow this deleting. */
+ void aboutToDeleteRow(KexiTableItem& item, KexiDB::ResultInfo* result, bool repaint);
+
+ //! Current row has been deleted
+ void rowDeleted();
+
+ //! Rows have been deleted
+ void rowsDeleted( const QValueList<int> &rowsToDelete );
+
+ //! Displayed data needs to be reloaded in all presenters.
+ void reloadRequested();
+
+ void rowRepaintRequested(KexiTableItem&);
+
+protected:
+ void init();
+ void init(
+ const QValueList<QVariant> &keys, const QValueList<QVariant> &values,
+ KexiDB::Field::Type keyType, KexiDB::Field::Type valueType);
+
+ virtual int compareItems(Item item1, Item item2);
+ int cmpStr(Item item1, Item item2);
+ int cmpInt(Item item1, Item item2);
+ int cmpUInt(Item item1, Item item2);
+ int cmpLongLong(Item item1, Item item2);
+ int cmpULongLong(Item item1, Item item2);
+ int cmpDouble(Item item1, Item item2);
+ int cmpDate(Item item1, Item item2);
+ int cmpDateTime(Item item1, Item item2);
+ int cmpTime(Item item1, Item item2);
+
+ //! Compare function for BLOB data (QByteArray). Uses size as the weight.
+ int cmpBLOB(Item item1, Item item2);
+
+ //! internal: for saveRowChanges() and saveNewRow()
+ bool saveRow(KexiTableItem& item, bool insert, bool repaint);
+
+ //! (logical) sorted column number, set by setSorting()
+ //! can differ from m_realSortedColumn if there's lookup column used
+ int m_sortedColumn;
+ //! real sorted column number, set by setSorting(), used by cmp*() methods
+ int m_realSortedColumn;
+ short m_order;
+ short m_type;
+ int m_itemSize;
+ static unsigned short charTable[];
+ KexiDB::RowEditBuffer *m_pRowEditBuffer;
+ QGuardedPtr<KexiDB::Cursor> m_cursor;
+
+ //! used to faster lookup columns of simple type (not dbaware)
+// QDict<KexiTableViewColumn> *m_simpleColumnsByName;
+
+ KexiDB::ResultInfo m_result;
+
+ uint m_visibleColumnsCount;
+ QValueVector<int> m_visibleColumnsIDs, m_globalColumnsIDs;
+
+ bool m_readOnly : 1;
+ bool m_insertingEnabled : 1;
+
+ /*! Used in acceptEditor() to avoid infinite recursion,
+ eg. when we're calling acceptRowEdit() during cell accepting phase. */
+ bool m_inside_acceptEditor : 1;
+
+ //! @see containsROWIDInfo()
+ bool m_containsROWIDInfo : 1;
+
+ int m_autoIncrementedColumn;
+
+ int (KexiTableViewData::*cmpFunc)(void *, void *);
+
+ //! Temporary, used in compare functions like cmpInt(), cmpString()
+ //! to avoid memory allocations.
+ QVariant m_leftTmp, m_rightTmp;
+};
+
+#endif