You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
919 lines
38 KiB
919 lines
38 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2005-2007 Jaroslaw Staniek <js@iidea.pl>
|
|
|
|
Based on KexiTableView code.
|
|
Copyright (C) 2002 Till Busch <till@bux.at>
|
|
Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
|
|
Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
|
|
Copyright (C) 2003 Joseph Wenninger <jowenn@kde.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.
|
|
|
|
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.
|
|
*/
|
|
|
|
#ifndef KEXIDATAAWAREOBJECTINTERFACE_H
|
|
#define KEXIDATAAWAREOBJECTINTERFACE_H
|
|
|
|
#include <tqguardedptr.h>
|
|
|
|
#include <tqtimer.h>
|
|
#include <kdebug.h>
|
|
#include <widget/utils/kexiarrowtip.h>
|
|
#include <kexisearchandreplaceiface.h>
|
|
#include "kexitableviewdata.h"
|
|
|
|
class TQObject;
|
|
class TQScrollBar;
|
|
class KPopupMenu;
|
|
class KexiTableItem;
|
|
class KexiTableViewData;
|
|
class KexiRecordMarker;
|
|
class KexiTableViewHeader;
|
|
class KexiRecordNavigator;
|
|
#include <kexidataiteminterface.h>
|
|
|
|
namespace KexiDB {
|
|
class RowEditBuffer;
|
|
}
|
|
|
|
//! default column width in pixels
|
|
#define KEXI_DEFAULT_DATA_COLUMN_WIDTH 120
|
|
|
|
//! \brief The KexiDataAwareObjectInterface is an interface for record-based data object.
|
|
/** This interface is implemented by KexiTableView and KexiFormView
|
|
and used by KexiDataAwareView. If yu're implementing this interface,
|
|
add KEXI_DATAAWAREOBJECTINTERFACE convenience macro just after Q_OBJECT.
|
|
|
|
You should add following code to your destructor so data is deleted:
|
|
\code
|
|
if (m_owner)
|
|
delete m_data;
|
|
m_data = 0;
|
|
\endcode
|
|
This is not performed in KexiDataAwareObjectInterface because you may need
|
|
to access m_data in your desctructor.
|
|
*/
|
|
class KEXIDATATABLE_EXPORT KexiDataAwareObjectInterface
|
|
{
|
|
public:
|
|
KexiDataAwareObjectInterface();
|
|
virtual ~KexiDataAwareObjectInterface();
|
|
|
|
/*! Sets data for this object. if \a owner is true, the object will own
|
|
\a data and therefore will be destroyed when needed, else: \a data is (possibly) shared and
|
|
not owned by the widget.
|
|
If widget already has _different_ data object assigned (and owns this data),
|
|
old data is destroyed before new assignment.
|
|
*/
|
|
void setData( KexiTableViewData *data, bool owner = true );
|
|
|
|
/*! \return data structure displayed for this object */
|
|
inline KexiTableViewData *data() const { return m_data; }
|
|
|
|
/*! \return currently selected column number or -1. */
|
|
inline int currentColumn() const { return m_curCol; }
|
|
|
|
/*! \return currently selected row number or -1. */
|
|
inline int currentRow() const { return m_curRow; }
|
|
|
|
/*! \return last row visible on the screen (counting from 0).
|
|
The returned value is guaranteed to be smaller or equal to currentRow() or -1
|
|
if there are no rows. */
|
|
virtual int lastVisibleRow() const = 0;
|
|
|
|
/*! \return currently selected item (row data) or null. */
|
|
KexiTableItem *selectedItem() const { return m_currentItem; }
|
|
|
|
/*! \return number of rows in this view. */
|
|
int rows() const;
|
|
|
|
/*! \return number of visible columns in this view.
|
|
By default returns dataColumns(), what is proper table view.
|
|
In case of form view, there can be a number of duplicated columns defined
|
|
(data-aware widgets, see KexiFormScrollView::columns()),
|
|
so columns() can return greater number than dataColumns(). */
|
|
virtual int columns() const { return dataColumns(); }
|
|
|
|
/*! Helper function.
|
|
\return number of columns of data. */
|
|
int dataColumns() const;
|
|
|
|
/*! \return true if data represented by this object
|
|
is not editable (it can be editable with other ways although,
|
|
outside of this object). */
|
|
virtual bool isReadOnly() const;
|
|
|
|
/*! Sets readOnly flag for this object.
|
|
Unless the flag is set, the widget inherits readOnly flag from it's data
|
|
structure assigned with setData(). The default value if false.
|
|
|
|
This method is useful when you need to switch on the flag indepentently
|
|
from the data structure.
|
|
Note: it is not allowed to force readOnly off
|
|
when internal data is readOnly - in that case the method does nothing.
|
|
You can check internal data flag calling data()->isReadOnly().
|
|
|
|
If \a set is true, insertingEnabled flag will be cleared automatically.
|
|
\sa isInsertingEnabled()
|
|
*/
|
|
void setReadOnly(bool set);
|
|
|
|
/*! \return true if sorting is enabled. */
|
|
inline bool isSortingEnabled() const { return m_isSortingEnabled; }
|
|
|
|
/*! Sets sorting on column \a col, or (when \a col == -1) sets rows unsorted
|
|
this will do not work if sorting is disabled with setSortingEnabled() */
|
|
virtual void setSorting(int col, bool ascending=true);
|
|
|
|
/*! Enables or disables sorting for this object
|
|
This method is different that setSorting() because it prevents both user
|
|
and programmer from sorting by clicking a column's header or calling setSorting().
|
|
By default sorting is enabled.
|
|
*/
|
|
virtual void setSortingEnabled(bool set);
|
|
|
|
/*! \return sorted column number or -1 if no column is sorted within data.
|
|
This does not mean that any sorting has been performed within GUI of this object,
|
|
because the data could be changed in the meantime outside of this GUI object. */
|
|
int dataSortedColumn() const;
|
|
|
|
/*! \return 1 if ascending order for data sorting data is set, -1 for descending,
|
|
0 for no sorting.
|
|
This does not mean that any sorting has been performed within GUI of this objetct,
|
|
because the data could be changed in the meantime outside of this GUI object.
|
|
*/
|
|
int dataSortingOrder() const;
|
|
|
|
/*! Sorts all rows by column selected with setSorting().
|
|
If there is currently row edited, it is accepted.
|
|
If acception failed, sort() will return false.
|
|
\return true on success. */
|
|
virtual bool sort();
|
|
|
|
/*! Sorts currently selected column in ascending order.
|
|
This slot is used typically for "data_sort_az" action. */
|
|
void sortAscending();
|
|
|
|
/*! Sorts currently selected column in descending order.
|
|
This slot is used typically for "data_sort_za" action. */
|
|
void sortDescending();
|
|
|
|
/*! \return true if data inserting is enabled (the default). */
|
|
virtual bool isInsertingEnabled() const;
|
|
|
|
/*! Sets insertingEnabled flag. If true, empty row is available
|
|
at the end of this widget for new entering new data.
|
|
Unless the flag is set, the widget inherits insertingEnabled flag from it's data
|
|
structure assigned with setData(). The default value if false.
|
|
|
|
Note: it is not allowed to force insertingEnabled on when internal data
|
|
has insertingEnabled set off - in that case the method does nothing.
|
|
You can check internal data flag calling data()->insertingEnabled().
|
|
|
|
Setting this flag to true will have no effect if read-only flag is true.
|
|
\sa setReadOnly()
|
|
*/
|
|
void setInsertingEnabled(bool set);
|
|
|
|
/*! \return true if row deleting is enabled.
|
|
Equal to deletionPolicy() != NoDelete && !isReadOnly()). */
|
|
bool isDeleteEnabled() const;
|
|
|
|
/*! \return true if inserting empty rows are enabled (false by default).
|
|
Mostly usable for not db-aware objects (e.g. used in Kexi Alter Table).
|
|
Note, that if inserting is disabled, or the data set is read-only,
|
|
this flag will be ignored. */
|
|
bool isEmptyRowInsertingEnabled() const { return m_emptyRowInsertingEnabled; }
|
|
|
|
/*! Sets emptyRowInserting flag.
|
|
Note, that if inserting is disabled, this flag is ignored. */
|
|
void setEmptyRowInsertingEnabled(bool set);
|
|
|
|
/*! Enables or disables filtering. Filtering is enabled by default. */
|
|
virtual void setFilteringEnabled(bool set);
|
|
|
|
/*! \return true if filtering is enabled. */
|
|
inline bool isFilteringEnabled() const { return m_isFilteringEnabled; }
|
|
|
|
/*! Added for convenience: configure this object
|
|
to behave more like spreadsheet (it's used for things like alter-table view).
|
|
- hides navigator
|
|
- disables sorting, inserting and filtering
|
|
- enables accepting row after cell accepting; see setAcceptsRowEditAfterCellAccepting()
|
|
- enables inserting empty row; see setEmptyRowInsertingEnabled() */
|
|
virtual void setSpreadSheetMode();
|
|
|
|
/*! \return true id "spreadSheetMode" is enabled. It's false by default. */
|
|
bool spreadSheetMode() const { return m_spreadSheetMode; }
|
|
|
|
/*! \return true if currently selected row is edited. */
|
|
inline bool rowEditing() const { return m_rowEditing; }
|
|
|
|
enum DeletionPolicy
|
|
{
|
|
NoDelete = 0,
|
|
AskDelete = 1,
|
|
ImmediateDelete = 2,
|
|
SignalDelete = 3
|
|
};
|
|
|
|
/*! \return deletion policy for this object.
|
|
The default (after allocating) is AskDelete. */
|
|
DeletionPolicy deletionPolicy() const { return m_deletionPolicy; }
|
|
|
|
virtual void setDeletionPolicy(DeletionPolicy policy);
|
|
|
|
/*! Deletes currently selected record; does nothing if no record
|
|
is currently selected. If record is in edit mode, editing
|
|
is cancelled before deleting. */
|
|
virtual void deleteCurrentRow();
|
|
|
|
/*! Inserts one empty row above row \a row. If \a row is -1 (the default),
|
|
new row is inserted above the current row (or above 1st row if there is no current).
|
|
A new item becomes current if row is -1 or if row is equal currentRow().
|
|
This method does nothing if:
|
|
-inserting flag is disabled (see isInsertingEnabled())
|
|
-read-only flag is set (see isReadOnly())
|
|
\ return inserted row's data
|
|
*/
|
|
virtual KexiTableItem *insertEmptyRow(int row = -1);
|
|
|
|
/*! For reimplementation: called by deleteItem(). If returns false, deleting is aborted.
|
|
Default implementation just returns true. */
|
|
virtual bool beforeDeleteItem(KexiTableItem *item);
|
|
|
|
/*! Deletes \a item. Used by deleteCurrentRow(). Calls beforeDeleteItem() before deleting,
|
|
to double-check if deleting is allowed.
|
|
\return true on success. */
|
|
bool deleteItem(KexiTableItem *item);//, bool moveCursor=true);
|
|
|
|
/*! Inserts newItem at \a row. -1 means current row. Used by insertEmptyRow(). */
|
|
void insertItem(KexiTableItem *newItem, int row = -1);
|
|
|
|
/*! Clears entire table data, its visible representation
|
|
and deletes data at database backend (if this is db-aware object).
|
|
Does not clear columns information.
|
|
Does not destroy KexiTableViewData object (if present) but only clears its contents.
|
|
Displays confirmation dialog if \a ask is true (the default is false).
|
|
Repaints widget if \a tqrepaint is true (the default).
|
|
For empty tables, true is returned immediately.
|
|
If isDeleteEnabled() is false, false is returned.
|
|
For spreadsheet mode all current rows are just replaced by empty rows.
|
|
\return true on success, false on failure, and cancelled if user cancelled deletion
|
|
(only possible if \a ask is true).
|
|
*/
|
|
tristate deleteAllRows(bool ask = false, bool tqrepaint = true);
|
|
|
|
/*! \return maximum number of rows that can be displayed per one "page"
|
|
for current view's size. */
|
|
virtual int rowsPerPage() const = 0;
|
|
|
|
virtual void selectRow(int row);
|
|
virtual void selectNextRow();
|
|
virtual void selectPrevRow();
|
|
virtual void selectNextPage(); //!< page down action
|
|
virtual void selectPrevPage(); //!< page up action
|
|
virtual void selectFirstRow();
|
|
virtual void selectLastRow();
|
|
virtual void addNewRecordRequested();
|
|
|
|
/*! Clears current selection. Current row and column will be now unspecified:
|
|
currentRow(), currentColumn() will return -1, and selectedItem() will return null. */
|
|
virtual void clearSelection();
|
|
|
|
/*! Moves cursor to \a row and \a col. If \a col is -1, current column number is used.
|
|
If forceSet is true, cursor position is updated even if \a row and \a col doesn't
|
|
differ from actual position. */
|
|
virtual void setCursorPosition(int row, int col = -1, bool forceSet = false);
|
|
|
|
/*! Ensures that cell at \a row and \a col is visible.
|
|
If \a col is -1, current column number is used. \a row and \a col (if not -1) must
|
|
be between 0 and rows() (or cols() accordingly). */
|
|
virtual void ensureCellVisible(int row, int col/*=-1*/) = 0;
|
|
|
|
/*! Specifies, if this object automatically accepts
|
|
row editing (using acceptRowEdit()) on accepting any cell's edit
|
|
(i.e. after acceptEditor()). \sa acceptsRowEditAfterCellAccepting() */
|
|
virtual void setAcceptsRowEditAfterCellAccepting(bool set);
|
|
|
|
/*! \return true, if this object automatically accepts
|
|
row editing (using acceptRowEdit()) on accepting any cell's edit
|
|
(i.e. after acceptEditor()).
|
|
By default this flag is set to false.
|
|
Not that if the query for this table has given constraints defined,
|
|
like NOT NULL / NOT EMPTY for more than one field - editing a record would
|
|
be impossible for the flag set to true, because of constraints violation.
|
|
However, setting this flag to true can be useful especially for not-db-aware
|
|
data set (it's used e.g. in Kexi Alter Table's field editor). */
|
|
bool acceptsRowEditAfterCellAccepting() const { return m_acceptsRowEditAfterCellAccepting; }
|
|
|
|
/*! \return true, if this table accepts dropping data on the rows. */
|
|
bool dropsAtRowEnabled() const { return m_dropsAtRowEnabled; }
|
|
|
|
/*! Specifies, if this table accepts dropping data on the rows.
|
|
If enabled:
|
|
- dragging over row is indicated by drawing a line at bottom side of this row
|
|
- dragOverRow() signal will be emitted on dragging,
|
|
-droppedAtRow() will be emitted on dropping
|
|
By default this flag is set to false. */
|
|
virtual void setDropsAtRowEnabled(bool set);
|
|
|
|
/*! \return currently used data (field/cell) editor or 0 if there is no data editing. */
|
|
inline KexiDataItemInterface *editor() const { return m_editor; }
|
|
|
|
/*! Cancels row editing All changes made to the editing
|
|
row during this current session will be undone.
|
|
\return true on success or false on failure (e.g. when editor does not exist) */
|
|
virtual bool cancelRowEdit();
|
|
|
|
/*! Accepts row editing. All changes made to the editing
|
|
row during this current session will be accepted (saved).
|
|
\return true if accepting was successful, false otherwise
|
|
(e.g. when current row contain data that does not meet given constraints). */
|
|
virtual bool acceptRowEdit();
|
|
|
|
virtual void removeEditor();
|
|
|
|
/*! Cancels changes made to the currently active editor.
|
|
Reverts the editor's value to old one.
|
|
\return true on success or false on failure (e.g. when editor does not exist) */
|
|
virtual bool cancelEditor();
|
|
|
|
//! Accepst changes made to the currently active editor.
|
|
//! \return true on success or false on failure (e.g. when editor does not exist or there is data validation error)
|
|
virtual bool acceptEditor();
|
|
|
|
//! Creates editors and shows it, what usually means the beginning of a cell editing
|
|
virtual void createEditor(int row, int col, const TQString& addText = TQString(),
|
|
bool removeOld = false) = 0;
|
|
|
|
/*! Used when Return key is pressed on cell, the cell has been double clicked
|
|
or "+" navigator's button is clicked.
|
|
Also used when we want to continue editing a cell after "invalid value" message
|
|
was displayed (in this case, \a setText is usually not empty, what means
|
|
that text will be set in the cell replacing previous value).
|
|
*/
|
|
virtual void startEditCurrentCell(const TQString& setText = TQString());
|
|
|
|
/*! Deletes currently selected cell's contents, if allowed.
|
|
In most cases delete is not accepted immediately but "row editing" mode is just started. */
|
|
virtual void deleteAndStartEditCurrentCell();
|
|
|
|
inline KexiTableItem *itemAt(int row) const;
|
|
|
|
/*! \return column information for column number \a col.
|
|
Default implementation just returns column # col,
|
|
but for Kexi Forms column data
|
|
corresponding to widget number is used here
|
|
(see KexiFormScrollView::fieldNumberForColumn()). */
|
|
virtual KexiTableViewColumn* column(int col);
|
|
|
|
/*! \return field number within data model connected to a data-aware
|
|
widget at column \a col. Can return -1 if there's no such column. */
|
|
virtual int fieldNumberForColumn(int col) { return col; }
|
|
|
|
bool hasDefaultValueAt(const KexiTableViewColumn& tvcol);
|
|
|
|
const TQVariant* bufferedValueAt(int col, bool useDefaultValueIfPossible = true);
|
|
|
|
//! \return a type of column \a col - one of KexiDB::Field::Type
|
|
int columnType(int col);
|
|
|
|
//! \return default value for column \a col
|
|
TQVariant columnDefaultValue(int col) const;
|
|
|
|
/*! \return true is column \a col is editable.
|
|
Default implementation takes information about 'readOnly' flag from data member.
|
|
Within forms, this is reimplemented for checking 'readOnly' flag from a widget
|
|
('readOnly' flag from data member is still checked though).
|
|
*/
|
|
virtual bool columnEditable(int col);
|
|
|
|
/*! Redraws the current cell. To be implemented. */
|
|
virtual void updateCurrentCell() = 0;
|
|
|
|
inline KexiRecordMarker* verticalHeader() const { return m_verticalHeader; }
|
|
|
|
//! signals
|
|
virtual void itemChanged(KexiTableItem *, int row, int col) = 0;
|
|
virtual void itemChanged(KexiTableItem *, int row, int col, TQVariant oldValue) = 0;
|
|
virtual void itemDeleteRequest(KexiTableItem *, int row, int col) = 0;
|
|
virtual void currentItemDeleteRequest() = 0;
|
|
//! Emitted for spreadsheet mode when an item was deleted and a new item has been appended
|
|
virtual void newItemAppendedForAfterDeletingInSpreadSheetMode() = 0;
|
|
|
|
/*! Data has been refreshed on-screen - emitted from initDataContents(). */
|
|
virtual void dataRefreshed() = 0;
|
|
virtual void dataSet( KexiTableViewData *data ) = 0;
|
|
|
|
/*! \return a pointer to context menu. This can be used to plug some actions there. */
|
|
KPopupMenu* contextMenu() const { return m_popupMenu; }
|
|
|
|
/*! \return true if the context menu is enabled (visible) for the view.
|
|
True by default. */
|
|
bool contextMenuEnabled() const { return m_contextMenuEnabled; }
|
|
|
|
/*! Enables or disables the context menu for the view. */
|
|
void setContextMenuEnabled(bool set) { m_contextMenuEnabled = set; }
|
|
|
|
/*! \return true if vertical scrollbar's tooltips are enabled (true by default). */
|
|
bool scrollbarToolTipsEnabled() const;
|
|
|
|
/*! Enables or disables vertical scrollbar's tooltip. */
|
|
void setScrollbarToolTipsEnabled(bool set);
|
|
|
|
/*! Typically handles pressing Enter or F2 key:
|
|
if current cell has boolean type, toggles it's value,
|
|
otherwise starts editing (startEditCurrentCell()). */
|
|
void startEditOrToggleValue();
|
|
|
|
/*! \return true if new row is edited; implies: rowEditing==true. */
|
|
inline bool newRowEditing() const { return m_newRowEditing; }
|
|
|
|
/*! Reaction on toggling a boolean value of a cell:
|
|
we're starting to edit the cell and inverting it's state. */
|
|
virtual void boolToggled();
|
|
|
|
virtual void connectCellSelectedSignal(const TQObject* receiver,
|
|
const char* intIntMember) = 0;
|
|
|
|
virtual void connectRowEditStartedSignal(const TQObject* receiver,
|
|
const char* intMember) = 0;
|
|
|
|
virtual void connectRowEditTerminatedSignal(const TQObject* receiver,
|
|
const char* voidMember) = 0;
|
|
|
|
virtual void connectReloadActionsSignal(const TQObject* receiver,
|
|
const char* voidMember) = 0;
|
|
|
|
virtual void connectDataSetSignal(const TQObject* receiver,
|
|
const char* kexiTableViewDataMember) = 0;
|
|
|
|
virtual void connectToReloadDataSlot(const TQObject* sender,
|
|
const char* voidSignal) = 0;
|
|
|
|
virtual void slotDataDestroying();
|
|
|
|
//! Copy current selection to a clipboard (e.g. cell)
|
|
virtual void copySelection() = 0;
|
|
|
|
//! Cut current selection to a clipboard (e.g. cell)
|
|
virtual void cutSelection() = 0;
|
|
|
|
//! Paste current clipboard contents (e.g. to a cell)
|
|
virtual void paste() = 0;
|
|
|
|
/*! Finds \a valueToFind within the data items
|
|
\a options are used to control the process. Selection is moved to found value.
|
|
If \a next is true, "find next" is performed, else "find previous" is performed.
|
|
|
|
Searching behaviour also depends on status of the previous search: for every search,
|
|
position of the cells containing the found value is stored internally
|
|
by the data-aware interface (not in options).
|
|
Moreover, position (start, end) of the found value is also stored.
|
|
Thus, the subsequent search will reuse this information to be able to start
|
|
searching exactly after the previously found value (or before for "find previous" option).
|
|
The flags can be zeroed, what will lead to seaching from the first character
|
|
of the current item (cell).
|
|
|
|
\return true if value has been found, false if value has not been found,
|
|
and cancelled if there is nothing to find or there is no data to search in. */
|
|
virtual tristate find(const TQVariant& valueToFind,
|
|
const KexiSearchAndReplaceViewInterface::Options& options, bool next);
|
|
|
|
/*! Finds \a valueToFind within the data items and replaces with \a replacement
|
|
\a options are used to control the process.
|
|
\return true if value has been found and replaced, false if value
|
|
has not been found and replaced, and cancelled if there is nothing
|
|
to find or there is no data to search in or the data is read only.
|
|
If \a replaceAll is true, all found values are replaced. */
|
|
virtual tristate findNextAndReplace(const TQVariant& valueToFind,
|
|
const TQVariant& replacement,
|
|
const KexiSearchAndReplaceViewInterface::Options& options, bool replaceAll);
|
|
|
|
/*! \return vertical scrollbar */
|
|
virtual TQScrollBar* verticalScrollBar() const = 0;
|
|
|
|
/*! Used in KexiTableView::keyPressEvent() (and in continuous forms).
|
|
\return true when the key press event \e was consumed.
|
|
You should also check e->isAccepted(), if it's true, nothing should be done;
|
|
if it is false, you should call setCursorPosition() for the altered \a curCol
|
|
and \c curRow variables.
|
|
|
|
If \a moveToFirstField is not 0, *moveToFirstField will be set to true
|
|
when the cursor should be moved to the first field (in tab order) and to false otherwise.
|
|
If \a moveToLastField is not 0, *moveToLastField will be set to true
|
|
when the cursor should be moved to the last field (in tab order) and to false otherwise.
|
|
Note for forms: if moveToFirstField and moveToLastField are not 0,
|
|
\a curCol is altered after calling this method, so setCursorPosition() will set to
|
|
the index of an appropriate column (field). This is needed because field widgets can be
|
|
inserted and ordered in custom tab order, so the very first field in the data source
|
|
can be other than the very first field in the form.
|
|
|
|
Used by KexiTableView::keyPressEvent() and KexiTableView::keyPressEvent(). */
|
|
virtual bool handleKeyPress(TQKeyEvent *e, int &curRow, int &curCol, bool fullRowSelection,
|
|
bool *moveToFirstField = 0, bool *moveToLastField = 0);
|
|
|
|
protected:
|
|
/*! Reimplementation for KexiDataAwareObjectInterface.
|
|
Initializes data contents (resizes it, sets cursor at 1st row).
|
|
Sets record count for record navigator.
|
|
Sets cursor positin (using setCursorPosition()) to first row or sets
|
|
(-1, -1) position if no rows are available.
|
|
Called on setData(). Also called once on show event after
|
|
refreshRequested() signal was received from KexiTableViewData object. */
|
|
virtual void initDataContents();
|
|
|
|
/*! Clears columns information and thus all internal table data
|
|
and its visible representation. Repaints widget if \a tqrepaint is true. */
|
|
virtual void clearColumns(bool tqrepaint = true);
|
|
|
|
/*! Called by clearColumns() to clear internals of the object.
|
|
For example, KexiTableView removes contents of it's horizontal header. */
|
|
virtual void clearColumnsInternal(bool tqrepaint) = 0;
|
|
|
|
/*! @internal for implementation
|
|
This should append another section within horizontal header or any sort of caption
|
|
for a field using provided names. \a width is a hint for new field's width. */
|
|
virtual void addHeaderColumn(const TQString& caption, const TQString& description,
|
|
const TQIconSet& icon, int size) = 0;
|
|
|
|
/*! @internal for implementation
|
|
\return sorting order (within GUI): -1: descending, 1: ascending, 0: no sorting.
|
|
This does not mean that any sorting has been performed within GUI of this object,
|
|
because the data could be changed in the meantime outside of this GUI object.
|
|
@see dataSortingOrder()*/
|
|
virtual int currentLocalSortingOrder() const = 0;
|
|
|
|
/*! @internal for implementation
|
|
\return sorted column number for this widget or -1 if no column
|
|
is sorted witin GUI.
|
|
This does not mean that the same sorting is performed within data member
|
|
which is used by this widget, because the data could be changed in the meantime
|
|
outside of this GUI widget.
|
|
@see dataSortedColumn() */
|
|
virtual int currentLocalSortColumn() const = 0;
|
|
|
|
/*! @internal for implementation
|
|
Shows sorting indicator order within GUI: -1: descending, 1: ascending,
|
|
0: no sorting. This should not perform any sorting within data member
|
|
which is used by this object.
|
|
col = -1 should mean "no sorting" as well. */
|
|
virtual void setLocalSortingOrder(int col, int order) = 0;
|
|
|
|
/*! @internal Sets order for \a column: -1: descending, 1: ascending,
|
|
0: invert order */
|
|
virtual void sortColumnInternal(int col, int order = 0);
|
|
|
|
/*! @internal for implementation
|
|
Updates GUI after sorting.
|
|
After sorting you need to ensure current row and column
|
|
is visible to avoid user confusion. For exaple, in KexiTableView
|
|
implementation, current cell is centered (if possible)
|
|
and updateContents() is called. */
|
|
virtual void updateGUIAfterSorting() = 0;
|
|
|
|
/*! Emitted in initActions() to force reload actions
|
|
You should remove existing actions and add them again.
|
|
Define and emit reloadActions() signal here. */
|
|
virtual void reloadActions() = 0;
|
|
|
|
/*! Reloads data for this object. */
|
|
virtual void reloadData();
|
|
|
|
/*! for implementation as a signal */
|
|
virtual void itemSelected(KexiTableItem *) = 0;
|
|
|
|
/*! for implementation as a signal */
|
|
virtual void cellSelected(int col, int row) = 0;
|
|
|
|
/*! for implementation as a signal */
|
|
virtual void sortedColumnChanged(int col) = 0;
|
|
|
|
/*! for implementation as a signal */
|
|
virtual void rowEditTerminated(int row) = 0;
|
|
|
|
/*! Clear temporary members like the pointer to current editor.
|
|
If you reimplement this method, don't forget to call this one. */
|
|
virtual void clearVariables();
|
|
|
|
/*! @internal
|
|
Creates editor structure without filling it with data.
|
|
Used in createEditor() and few places to be able to display cell contents
|
|
dependending on its type. If \a ignoreMissingEditor is false (the default),
|
|
and editor cannot be instantiated, current row editing (if present) is cancelled.
|
|
*/
|
|
virtual KexiDataItemInterface *editor( int col, bool ignoreMissingEditor = false ) = 0;
|
|
|
|
/*! Updates editor's position, size and shows its focus (not the editor!)
|
|
for \a row and \a col, using editor(). Does nothing if editor not found. */
|
|
virtual void editorShowFocus( int row, int col ) = 0;
|
|
|
|
/*! Redraws specified cell. */
|
|
virtual void updateCell(int row, int col) = 0;
|
|
|
|
/*! Redraws all cells of specified row. */
|
|
virtual void updateRow(int row) = 0;
|
|
|
|
/*! Updates contents of the widget. Just call update() here on your widget. */
|
|
virtual void updateWidgetContents() = 0;
|
|
|
|
/*! Updates widget's contents size e.g. using TQScrollView::resizeContents(). */
|
|
virtual void updateWidgetContentsSize() = 0;
|
|
|
|
/*! Updates scrollbars of the widget.
|
|
TQScrollView::updateScrollbars() will be usually called here. */
|
|
virtual void updateWidgetScrollBars() = 0;
|
|
|
|
/*! @internal
|
|
Updates row appearance after canceling row edit.
|
|
Used by cancelRowEdit(). By default just calls updateRow(m_curRow).
|
|
Reimplemented by KexiFormScrollView. */
|
|
virtual void updateAfterCancelRowEdit();
|
|
|
|
/*! @internal
|
|
Updates row appearance after accepting row edit.
|
|
Used by acceptRowEdit(). By default just calls updateRow(m_curRow).
|
|
Reimplemented by KexiFormScrollView. */
|
|
virtual void updateAfterAcceptRowEdit();
|
|
|
|
//! Handles KexiTableViewData::rowRepaintRequested() signal
|
|
virtual void slotRowRepaintRequested(KexiTableItem& item) { Q_UNUSED( item ); }
|
|
|
|
//! Handles KexiTableViewData::aboutToDeleteRow() signal. Prepares info for slotRowDeleted().
|
|
virtual void slotAboutToDeleteRow(KexiTableItem& item, KexiDB::ResultInfo* result,
|
|
bool tqrepaint);
|
|
|
|
//! Handles KexiTableViewData::rowDeleted() signal to tqrepaint when needed.
|
|
virtual void slotRowDeleted();
|
|
|
|
//! Handles KexiTableViewData::rowInserted() signal to tqrepaint when needed.
|
|
virtual void slotRowInserted(KexiTableItem *item, bool tqrepaint);
|
|
|
|
//! Like above, not db-aware version
|
|
virtual void slotRowInserted(KexiTableItem *item, uint row, bool tqrepaint);
|
|
|
|
virtual void slotRowsDeleted( const TQValueList<int> & ) {}
|
|
|
|
//! for sanity checks (return true if m_data is present; else: outputs warning)
|
|
inline bool hasData() const;
|
|
|
|
/*! Only needed for forms: called by KexiDataAwareObjectInterface::setCursorPosition()
|
|
if cursor's position is really changed. */
|
|
virtual void selectCellInternal() {}
|
|
|
|
/*! Used in KexiDataAwareObjectInterface::slotRowDeleted()
|
|
to tqrepaint tow \a row and all visible below.
|
|
Implemented if there is more than one row displayed, i.e. currently for KexiTableView. */
|
|
virtual void updateAllVisibleRowsBelow(int row) { Q_UNUSED( row ); }
|
|
|
|
//! Call this from the subclass. */
|
|
virtual void focusOutEvent(TQFocusEvent* e);
|
|
|
|
/*! Handles verticalScrollBar()'s valueChanged(int) signal.
|
|
Called when vscrollbar's value has been changed.
|
|
Call this method from the subclass. */
|
|
virtual void vScrollBarValueChanged(int v);
|
|
|
|
/*! Handles sliderReleased() signal of the verticalScrollBar(). Used to hide the "row number" tooltip. */
|
|
virtual void vScrollBarSliderReleased();
|
|
|
|
/*! Handles timeout() signal of the m_scrollBarTipTimer. If the tooltip is visible,
|
|
m_scrollBarTipTimerCnt is set to 0 and m_scrollBarTipTimerCnt is restarted;
|
|
else the m_scrollBarTipTimerCnt is just set to 0.*/
|
|
virtual void scrollBarTipTimeout();
|
|
|
|
/*! Shows error message box suitable for \a resultInfo. This can be "sorry" or "detailedSorry"
|
|
message box or "queryYesNo" if resultInfo->allowToDiscardChanges is true.
|
|
\return code of button clicked: KMessageBox::Ok in case of "sorry" or "detailedSorry" messages
|
|
and KMessageBox::Yes or KMessageBox::No in case of "queryYesNo" message. */
|
|
int showErrorMessageForResult(KexiDB::ResultInfo* resultInfo);
|
|
|
|
/*! Prepares array of indices of visible values to search within.
|
|
This is per-interface global cache.
|
|
Needed for faster lookup because there could be lookup values.
|
|
Called whenever columns definition changes, i.e. in setData() and clearColumns().
|
|
@see find() */
|
|
void updateIndicesForVisibleValues();
|
|
|
|
//! data structure displayed for this object
|
|
KexiTableViewData *m_data;
|
|
|
|
//! true if m_data member is owned by this object
|
|
bool m_owner : 1;
|
|
|
|
//! cursor position
|
|
int m_curRow, m_curCol;
|
|
|
|
//! current data item
|
|
KexiTableItem *m_currentItem;
|
|
|
|
//! data item's iterator
|
|
KexiTableViewData::Iterator *m_itemIterator;
|
|
|
|
//! item data for inserting
|
|
KexiTableItem *m_insertItem;
|
|
|
|
//! when (current or new) row is edited - changed field values are temporary stored here
|
|
// KexiDB::RowEditBuffer *m_rowEditBuffer;
|
|
|
|
/*! true if currently selected row is edited */
|
|
bool m_rowEditing : 1;
|
|
|
|
/*! true if new row is edited; implies: rowEditing==true. */
|
|
bool m_newRowEditing : 1;
|
|
|
|
/*! 'sorting by column' availability flag for widget */
|
|
bool m_isSortingEnabled : 1;
|
|
|
|
/*! true if filtering is enabled for the view. */
|
|
bool m_isFilteringEnabled : 1;
|
|
|
|
/*! Public version of 'acceptsRowEditAfterCellAcceptin' flag (available for a user).
|
|
It's OR'es together with above flag.
|
|
*/
|
|
bool m_acceptsRowEditAfterCellAccepting : 1;
|
|
|
|
/*! Used in acceptEditor() to avoid infinite recursion,
|
|
eg. when we're calling acceptRowEdit() during cell accepting phase. */
|
|
bool m_inside_acceptEditor : 1;
|
|
|
|
/*! @internal if true, this object automatically accepts
|
|
row editing (using acceptRowEdit()) on accepting any cell's edit
|
|
(i.e. after acceptEditor()). */
|
|
bool m_internal_acceptsRowEditAfterCellAccepting : 1;
|
|
|
|
/*! true, if inserting empty rows are enabled (false by default) */
|
|
bool m_emptyRowInsertingEnabled : 1;
|
|
|
|
/*! Contains 1 if the object is readOnly, 0 if not;
|
|
otherwise (-1 means "do not know") the 'readOnly' flag from object's
|
|
internal data structure (KexiTableViewData *KexiTableView::m_data) is reused.
|
|
*/
|
|
int m_readOnly;
|
|
|
|
//! @todo really keep this here and not in KexiTableView?
|
|
/*! true if currently double click action was is performed
|
|
(so accept/cancel editor shoudn't be executed) */
|
|
bool m_contentsMousePressEvent_dblClick : 1;
|
|
|
|
/*! like for readOnly: 1 if inserting is enabled */
|
|
int m_insertingEnabled;
|
|
|
|
/*! true, if initDataContents() should be called on show event. */
|
|
bool m_initDataContentsOnShow : 1;
|
|
|
|
/*! Set to true in setCursorPosition() to indicate that cursor position was set
|
|
before show() and it shouldn't be changed on show().
|
|
Only used if initDataContentsOnShow is true. */
|
|
bool m_cursorPositionSetExplicityBeforeShow : 1;
|
|
|
|
/*! true if spreadSheetMode is enabled. False by default.
|
|
@see KexiTableView::setSpreadSheetMode() */
|
|
bool m_spreadSheetMode : 1;
|
|
|
|
/*! true, if this table accepts dropping data on the rows (false by default). */
|
|
bool m_dropsAtRowEnabled : 1;
|
|
|
|
/*! true, if this entire (visible) row should be updated when boving to other row.
|
|
False by default. For table view with 'row highlighting' flag enabled, it is true. */
|
|
bool m_updateEntireRowWhenMovingToOtherRow : 1;
|
|
|
|
DeletionPolicy m_deletionPolicy;
|
|
|
|
//! @todo make generic interface out of KexiRecordMarker
|
|
KexiRecordMarker *m_verticalHeader;
|
|
|
|
//! @todo make generic interface out of KexiTableViewHeader
|
|
KexiTableViewHeader *m_horizontalHeader;
|
|
|
|
KexiDataItemInterface *m_editor;
|
|
// KexiTableEdit *m_editor;
|
|
|
|
/*! Navigation panel, used if navigationPanelEnabled is true. */
|
|
KexiRecordNavigator *m_navPanel; //!< main navigation widget
|
|
|
|
bool m_navPanelEnabled : 1;
|
|
|
|
/*! true, if certical header shouldn't be increased in
|
|
KexiTableView::slotRowInserted() because it was already done
|
|
in KexiTableView::createEditor(). */
|
|
bool m_verticalHeaderAlreadyAdded : 1;
|
|
|
|
/*! Row number that over which user drags a mouse pointer.
|
|
Used to indicate dropping possibility for that row.
|
|
Equal -1 if no indication is needed. */
|
|
int m_dragIndicatorLine;
|
|
|
|
/*! Context menu widget. */
|
|
KPopupMenu *m_popupMenu;
|
|
|
|
bool m_contextMenuEnabled : 1;
|
|
|
|
//! Used by updateAfterCancelRowEdit()
|
|
bool m_alsoUpdateNextRow : 1;
|
|
|
|
/*! Row number (>=0 or -1 == no row) that will be deleted in deleteRow().
|
|
It is set in slotAboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)) slot
|
|
received from KexiTableViewData member.
|
|
This value will be used in slotRowDeleted() after rowDeleted() signal
|
|
is received from KexiTableViewData member and then cleared (set to -1). */
|
|
int m_rowWillBeDeleted;
|
|
|
|
/*! Displays passive error popup label used when invalid data has been entered. */
|
|
TQGuardedPtr<KexiArrowTip> m_errorMessagePopup;
|
|
|
|
/*! Used to enable/disable execution of vScrollBarValueChanged()
|
|
when users navigate through rows using keyboard, so vscrollbar tooltips are not visible. */
|
|
bool m_vScrollBarValueChanged_enabled : 1;
|
|
|
|
/*! True, if vscrollbar tooltips are enabled (true by default). */
|
|
bool m_scrollbarToolTipsEnabled : 1;
|
|
|
|
TQLabel* m_scrollBarTip; //!< scrollbar tooltip
|
|
TQTimer m_scrollBarTipTimer; //!< scrollbar tooltip's timer
|
|
uint m_scrollBarTipTimerCnt; //!< helper for timeout counting (scrollbar tooltip)
|
|
|
|
//! Used to mark recently found value
|
|
class PositionOfValue {
|
|
public:
|
|
PositionOfValue() : firstCharacter(0), lastCharacter(0), exists(false)
|
|
{}
|
|
uint firstCharacter;
|
|
uint lastCharacter;
|
|
bool exists : 1;
|
|
};
|
|
|
|
/*! Used to mark recently found value. Updated on succesful execution of find().
|
|
If the current cursor's position changes, or data in the current cell changes,
|
|
positionOfRecentlyFoundValue.exists is set to false. */
|
|
PositionOfValue m_positionOfRecentlyFoundValue;
|
|
|
|
/*! Used to compare whether we're looking for new value. */
|
|
TQVariant m_recentlySearchedValue;
|
|
|
|
/*! Used to compare whether the search direction has changed. */
|
|
KexiSearchAndReplaceViewInterface::Options::SearchDirection m_recentSearchDirection;
|
|
|
|
//! Setup by updateIndicesForVisibleValues() and used by find()
|
|
TQValueVector<uint> m_indicesForVisibleValues;
|
|
};
|
|
|
|
inline bool KexiDataAwareObjectInterface::hasData() const
|
|
{
|
|
if (!m_data)
|
|
kdDebug() << "KexiDataAwareObjectInterface: No data assigned!" << endl;
|
|
return m_data!=0;
|
|
}
|
|
|
|
inline KexiTableItem *KexiDataAwareObjectInterface::itemAt(int row) const
|
|
{
|
|
KexiTableItem *item = m_data->at(row);
|
|
if (!item)
|
|
kdDebug() << "KexiTableView::itemAt(" << row << "): NO ITEM!!" << endl;
|
|
else {
|
|
/* kdDebug() << "KexiTableView::itemAt(" << row << "):" << endl;
|
|
int i=1;
|
|
for (KexiTableItem::Iterator it = item->begin();it!=item->end();++it,i++)
|
|
kdDebug() << i<<": " << (*it).toString()<< endl;*/
|
|
}
|
|
return item;
|
|
}
|
|
|
|
//! Convenience macro used for KexiDataAwareObjectInterface implementations.
|
|
#define KEXI_DATAAWAREOBJECTINTERFACE \
|
|
public: \
|
|
void connectCellSelectedSignal(const TQObject* receiver, const char* intIntMember) { \
|
|
connect(this, TQT_SIGNAL(cellSelected(int,int)), receiver, intIntMember); \
|
|
} \
|
|
void connectRowEditStartedSignal(const TQObject* receiver, const char* intMember) { \
|
|
connect(this, TQT_SIGNAL(rowEditStarted(int)), receiver, intMember); \
|
|
} \
|
|
void connectRowEditTerminatedSignal(const TQObject* receiver, const char* voidMember) { \
|
|
connect(this, TQT_SIGNAL(rowEditTerminated(int)), receiver, voidMember); \
|
|
} \
|
|
void connectReloadActionsSignal(const TQObject* receiver, const char* voidMember) { \
|
|
connect(this, TQT_SIGNAL(reloadActions()), receiver, voidMember); \
|
|
} \
|
|
void connectDataSetSignal(const TQObject* receiver, \
|
|
const char* kexiTableViewDataMember) { \
|
|
connect(this, TQT_SIGNAL(dataSet(KexiTableViewData*)), receiver, kexiTableViewDataMember); \
|
|
} \
|
|
void connectToReloadDataSlot(const TQObject* sender, const char* voidSignal) { \
|
|
connect(sender, voidSignal, this, TQT_SLOT(reloadData())); \
|
|
}
|
|
|
|
#endif
|