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.
kmymoney/kmymoney2/widgets/register.h

606 lines
19 KiB

/***************************************************************************
register.h
----------
begin : Fri Mar 10 2006
copyright : (C) 2006 by Thomas Baumgart
email : Thomas Baumgart <ipwizard@users.sourceforge.net>
***************************************************************************/
/***************************************************************************
* *
* 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 REGISTER_H
#define REGISTER_H
// Some STL headers in GCC4.3 contain operator new. Memory checker mangles these
#ifdef _CHECK_MEMORY
#undef new
#endif
#include <algorithm>
// ----------------------------------------------------------------------------
// QT Includes
#include <tqtable.h>
#include <tqvaluelist.h>
#include <tqvaluevector.h>
#include <tqwidgetlist.h>
#include <tqmap.h>
#include <tqpair.h>
#include <tqevent.h>
// ----------------------------------------------------------------------------
// KDE Includes
// ----------------------------------------------------------------------------
// Project Includes
#ifdef _CHECK_MEMORY
#include <kmymoney/mymoneyutils.h>
#endif
#include <kmymoney/mymoneyaccount.h>
#include <kmymoney/registeritem.h>
#include <kmymoney/transaction.h>
#include <kmymoney/transactioneditorcontainer.h>
#include <kmymoney/selectedtransaction.h>
#include <kmymoney/transactionsortoption.h>
class RegisterToolTip;
namespace KMyMoneyRegister {
typedef enum {
UnknownSort = 0, //< unknown sort criteria
PostDateSort = 1, //< sort by post date
EntryDateSort, //< sort by entry date
PayeeSort, //< sort by payee name
ValueSort, //< sort by value
NoSort, //< sort by number field
EntryOrderSort, //< sort by entry order
TypeSort, //< sort by CashFlowDirection
CategorySort, //< sort by Category
ReconcileStateSort, //< sort by reconciliation state
SecuritySort, //< sort by security (only useful for investment accounts)
// insert new values in front of this line
MaxSortFields
} TransactionSortField;
typedef enum {
Ascending = 0, //< sort in ascending order
Descending //< sort in descending order
} SortDirection;
class Register;
class RegisterItem;
class ItemPtrVector;
const TQString sortOrderToText(TransactionSortField idx);
TransactionSortField textToSortOrder(const TQString& text);
class TQWidgetContainer : public TQMap<TQString, TQWidget*>
{
public:
TQWidgetContainer() {}
TQWidget* haveWidget(const TQString& name) const {
TQWidgetContainer::const_iterator it_w;
it_w = find(name);
if(it_w != end())
return *it_w;
return 0;
}
void removeOrphans(void) {
TQWidgetContainer::iterator it_w;
for(it_w = begin(); it_w != end(); ) {
if((*it_w) && (*it_w)->parent())
++it_w;
else {
delete (*it_w);
remove(it_w);
it_w = begin();
}
}
}
};
class GroupMarker : public RegisterItem
{
public:
GroupMarker(Register* parent, const TQString& txt = TQString());
~GroupMarker();
void setText(const TQString& txt) { m_txt = txt; }
const TQString& text(void) const { return m_txt; }
bool isSelectable(void) const { return false; }
bool canHaveFocus(void) const { return false; }
int numRows(void) const { return 1; }
virtual const char* className(void) { return "GroupMarker"; }
bool isErronous(void) const { return false; }
void paintRegisterCell(TQPainter* painter, int row, int col, const TQRect& r, bool selected, const TQColorGroup& cg);
void paintFormCell(TQPainter* /* painter */, int /* row */, int /* col */, const TQRect& /* r */, bool /* selected */, const TQColorGroup& /* cg */) {}
int rowHeightHint(void) const;
bool matches(const TQString&) const { return true; }
virtual int sortSamePostDate(void) const { return 0; }
protected:
void setupColors(TQColorGroup& cg);
protected:
TQString m_txt;
unsigned int m_drawCounter;
bool m_showDate;
static TQPixmap* m_bg;
static int m_bgRefCnt;
};
class FancyDateGroupMarker : public GroupMarker
{
public:
FancyDateGroupMarker(Register* parent, const TQDate& date, const TQString& txt);
virtual const TQDate& sortPostDate(void) const { return m_date; }
virtual const TQDate& sortEntryDate(void) const { return m_date; }
virtual const char* className(void) { return "FancyDateGroupMarker"; }
private:
TQDate m_date;
};
class StatementGroupMarker : public FancyDateGroupMarker
{
public:
StatementGroupMarker(Register* parent, CashFlowDirection dir, const TQDate& date, const TQString& txt );
CashFlowDirection sortType(void) const { return m_dir; }
virtual int sortSamePostDate(void) const { return 3; }
private:
CashFlowDirection m_dir;
};
class SimpleDateGroupMarker : public FancyDateGroupMarker
{
public:
SimpleDateGroupMarker(Register* parent, const TQDate& date, const TQString& txt);
void paintRegisterCell(TQPainter* painter, int row, int col, const TQRect& r, bool selected, const TQColorGroup& cg);
int rowHeightHint(void) const;
virtual const char* className(void) { return "SimpleDateGroupMarker"; }
};
class TypeGroupMarker : public GroupMarker
{
public:
TypeGroupMarker(Register* parent, CashFlowDirection dir, MyMoneyAccount::accountTypeE accType);
CashFlowDirection sortType(void) const { return m_dir; }
private:
CashFlowDirection m_dir;
};
class FiscalYearGroupMarker : public FancyDateGroupMarker
{
public:
FiscalYearGroupMarker(Register* parent, const TQDate& date, const TQString& txt);
virtual const char* className(void) { return "FiscalYearGroupMarker"; }
virtual int sortSamePostDate(void) const { return 1; }
protected:
void setupColors(TQColorGroup& cg);
};
class PayeeGroupMarker : public GroupMarker
{
public:
PayeeGroupMarker(Register* parent, const TQString& name);
const TQString& sortPayee(void) const { return m_txt; }
};
class CategoryGroupMarker : public GroupMarker
{
public:
CategoryGroupMarker(Register* parent, const TQString& category);
const TQString& sortCategory(void) const { return m_txt; }
const TQString& sortSecurity(void) const { return m_txt; }
virtual const char* className(void) { return "CategoryGroupMarker"; }
};
class ReconcileGroupMarker : public GroupMarker
{
public:
ReconcileGroupMarker(Register* parent, MyMoneySplit::reconcileFlagE state);
virtual MyMoneySplit::reconcileFlagE sortReconcileState(void) const { return m_state; }
private:
MyMoneySplit::reconcileFlagE m_state;
};
class ItemPtrVector : public TQValueVector<RegisterItem *>
{
public:
ItemPtrVector() {}
void sort(void);
protected:
/**
* sorter's compare routine. Returns true if i1 < i2
*/
static bool item_cmp(RegisterItem* i1, RegisterItem* i2);
};
class Register : public TransactionEditorContainer
{
TQ_OBJECT
// friend class TQHeader;
// friend class TQTableHeader;
// friend class RegisterItem;
friend class Transaction;
friend class StdTransaction;
friend class InvestTransaction;
public:
Register(TQWidget *parent = 0, const char *name = 0);
virtual ~Register();
/**
* add the item @a p to the register
*/
void addItem(RegisterItem* p);
/**
* insert the item @a p into the register after item @a q
*/
void insertItemAfter(RegisterItem* p, RegisterItem* q);
/**
* remove the item @p from the register
*/
void removeItem(RegisterItem* p);
/**
* This method returns a list of pointers to all selected items
* in the register
*
* @retval TQValueList<RegisterItem*>
*/
TQValueList<RegisterItem*> selectedItems(void) const;
/**
* Construct a list of all currently selected transactions in the register.
* If the current item carrying the focus (see focusItem() ) is selected
* it will be the first one contained in the list.
*
* @param list reference to TQValueList receiving the SelectedTransaction()'s
*/
void selectedTransactions(SelectedTransactions& list) const;
TQString text(int row, int col) const;
TQWidget* createEditor(int row, int col, bool initFromCell) const;
void setCellContentFromEditor(int row, int col);
TQWidget* cellWidget(int row, int col) const;
void endEdit(int row, int col, bool accept, bool replace);
void paintCell(TQPainter* painter, int row, int col, const TQRect& r, bool selected, const TQColorGroup& cg);
void resizeData(int) {}
TQTableItem* item(int, int) { return 0; }
void setItem(int, int, TQTableItem*) {}
void clearCell(int, int) {}
void clearCellWidget(int, int);
/**
* Override the TQTable member function to avoid display of focus
*/
void paintFocus(TQPainter*, const TQRect& ) {}
/**
* Override the TQTable member function to avoid functionality
*/
void updateCell(int /* row */, int /* col */) {}
RegisterItem* focusItem(void) const { return m_focusItem; }
RegisterItem* anchorItem(void) const { return m_selectAnchor; }
/**
* set focus to specific item.
* @return true if the item got focus
*/
bool setFocusItem(RegisterItem* focusItem);
void setAnchorItem(RegisterItem* anchorItem);
/**
* Set focus to the first focussable item
* @return true if a focussable item was found
*/
bool setFocusToTop(void);
/**
* Select @a item and unselect all others if @a dontChangeSelections
* is @a false. If m_buttonState differs from Qt::NoButton (method is
* called as a result of a mouse button press), then the setting of
* @a dontChangeSelections has no effect.
*/
void selectItem(RegisterItem* item, bool dontChangeSelections = false);
/**
* Clears all items in the register. All objects
* added to the register will be deleted.
*/
void clear(void);
void updateRegister(bool forceUpdateRowHeight = false);
/**
* Assign all visible items an alternate background color
*/
void updateAlternate(void) const;
/**
* make sure, we only show a single marker in a row
* through hiding unused ones
*/
void suppressAdjacentMarkers(void);
/**
* Adjusts column @a col so that all data fits in width.
*/
void adjustColumn(int col);
/**
* Convenience method to setup the register to show the columns
* based on the account type of @a account. If @a showAccountColumn
* is @a true then the account column is shown independant of the
* account type. If @a account does not have an @a id, all columns
* will be hidden.
*/
void setupRegister(const MyMoneyAccount& account, bool showAccountColumn = false);
/**
* Show the columns contained in @a cols for @a account. @a account
* can be left empty ( MyMoneyAccount() ) e.g. for the search dialog.
*/
void setupRegister(const MyMoneyAccount& account, const TQValueList<Column>& cols);
void setSortOrder(const TQString& order);
const TQValueList<TransactionSortField>& sortOrder(void) const { return m_sortOrder; }
TransactionSortField primarySortKey(void) const;
void sortItems(void);
/**
* This member returns the last visible column that is used by the register
* after it has been setup using setupRegister().
*
* @return last actively used column (base 0)
*/
Column lastCol(void) const { return m_lastCol; }
RegisterItem* firstItem(void) const;
RegisterItem* firstVisibleItem(void) const;
RegisterItem* nextItem(RegisterItem*) const;
RegisterItem* lastItem(void) const;
RegisterItem* lastVisibleItem(void) const;
RegisterItem* prevItem(RegisterItem*) const;
RegisterItem* itemAtRow(int row) const;
void resize(int col);
void forceUpdateLists(void) { m_listsDirty = true; }
void ensureItemVisible(RegisterItem* item);
void arrangeEditWidgets(TQMap<TQString, TQWidget*>& editWidgets, Transaction* t);
void removeEditWidgets(TQMap<TQString, TQWidget*>& editWidgets);
void tabOrder(TQWidgetList& tabOrderWidgets, KMyMoneyRegister::Transaction* t) const;
int rowHeightHint(void) const;
void clearSelection(void);
bool markErronousTransactions(void) const { return (m_markErronousTransactions & 0x01) != 0; }
/**
* This method creates a specifc transaction according to the
* transaction passed in @a transaction.
*
* @param parent pointer to register where the created object should be added
* @param transaction the transaction which should be used to create the object
* @param split the split of the transaction which should be used to create the object
* @param uniqueId an int that will be used to construct the id of the item
*
* @return pointer to created object (0 upon failure)
*/
static Transaction* transactionFactory(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId);
const MyMoneyAccount& account(void) const { return m_account; }
void repaintItems(RegisterItem* first = 0, RegisterItem* last = 0);
unsigned int drawCounter(void) const { return m_drawCounter; }
/**
* This method creates group marker items and adds them to the register
*/
void addGroupMarkers(void);
/**
* This method removes all trailing group markers and in a second
* run reduces all adjacent group markers to show only one. In that
* case the last one will remain.
*/
void removeUnwantedGroupMarkers(void);
void setLedgerLensForced(bool forced=true) { m_ledgerLensForced = forced; }
/**
* Sets the selection mode to @a mode. Supported modes are TQTable::Single and
* TQTable::Multi. TQTable::Multi is the default when the object is created.
*/
void setSelectionMode(SelectionMode mode) { m_selectionMode = mode; }
protected:
void drawContents(TQPainter *p, int cx, int cy, int cw, int ch);
void contentsMouseReleaseEvent( TQMouseEvent *e );
void unselectItems(int from = -1, int to = -1) { doSelectItems(from, to, false); }
void selectItems(int from, int to) { doSelectItems(from, to, true); }
void doSelectItems(int from, int to, bool selected);
int selectedItemsCount(void) const;
void focusOutEvent(TQFocusEvent*);
void focusInEvent(TQFocusEvent*);
void keyPressEvent(TQKeyEvent*);
int rowToIndex(int row) const;
void setupItemIndex(int rowCount);
/**
* This method determines the register item that is one page
* further down or up in the ledger from the previous focus item.
* The height to scroll is determined by visibleHeight()
*
* @param key TQt::Page_Up or TQt::Page_Down depending on the direction to scroll
* @param state state of TQt::ShiftButton, TQt::ControlButton, TQt::AltButton and
* TQt::MetaButton.
*/
void scrollPage(int key, ButtonState state);
/**
* This method determines the pointer to a RegisterItem
* based on the item's @a id. If @a id is empty, this method
* returns @a m_lastItem.
*
* @param id id of the item to be searched
* @return pointer to RegisterItem or 0 if not found
*/
RegisterItem* itemById(const TQString& id) const;
void insertWidget(int row, int col, TQWidget* w);
/**
* Override logic and use standard TQFrame behaviour
*/
bool focusNextPrevChild(bool next);
bool eventFilter(TQObject* o, TQEvent* e);
void handleItemChange(RegisterItem* old, bool shift, bool control);
void selectRange(RegisterItem* from, RegisterItem* to, bool invert, bool includeFirst, bool clearSel);
// DND
void dragMoveEvent(TQDragMoveEvent* event);
void dropEvent(TQDropEvent* event);
Transaction* dropTransaction(TQPoint cPos) const;
protected slots:
void resize(void);
void selectItem(int row, int col, int button, const TQPoint & mousePos );
void slotEnsureItemVisible(void);
void slotDoubleClicked(int, int, int, const TQPoint&);
void slotToggleErronousTransactions(void);
void slotAutoColumnSizing(int section);
signals:
void selectionChanged(void);
void selectionChanged(const KMyMoneyRegister::SelectedTransactions& list);
/**
* This signal is emitted when the focus and selection changes to @p item.
*
* @param item pointer to transaction that received the focus and was selected
*/
void focusChanged(KMyMoneyRegister::Transaction* item);
/**
* This signal is emitted when the focus changes but the selection remains
* the same. This usually happens when the focus is changed using the keyboard.
*/
void focusChanged(void);
/**
* This signal is emitted when an @p item is about to be selected. The boolean
* @p okToSelect is preset to @c true. If the @p item should not be selected
* for whatever reason, the boolean @p okToSelect should be reset to @c false
* by the connected slot.
*/
void aboutToSelectItem(KMyMoneyRegister::RegisterItem* item, bool& okToSelect);
void editTransaction(void);
void headerClicked(void);
/**
* This signal is sent out when the user clicks on the ReconcileStateColumn and
* only a single transaction is selected.
*/
void reconcileStateColumnClicked(KMyMoneyRegister::Transaction* item);
/**
* This signal is sent out, if an item without a transaction id has been selected.
*/
void emptyItemSelected(void);
/**
* This signal is sent out, if the user selects an item with the right mouse button
*/
void openContextMenu(void);
/**
* This signal is sent out when a new item has been added to the register
*/
void itemAdded(RegisterItem* item);
protected:
ItemPtrVector m_items;
TQValueVector<RegisterItem*> m_itemIndex;
RegisterItem* m_selectAnchor;
RegisterItem* m_focusItem;
RegisterItem* m_ensureVisibleItem;
RegisterItem* m_firstItem;
RegisterItem* m_lastItem;
RegisterItem* m_firstErronous;
RegisterItem* m_lastErronous;
int m_markErronousTransactions;
int m_rowHeightHint;
MyMoneyAccount m_account;
bool m_ledgerLensForced;
SelectionMode m_selectionMode;
private:
bool m_listsDirty;
bool m_ignoreNextButtonRelease;
bool m_needInitialColumnResize;
TQt::ButtonState m_buttonState;
Column m_lastCol;
TQValueList<TransactionSortField> m_sortOrder;
TQMap<TQPair<int, int>, TQWidget*> m_cellWidgets;
RegisterToolTip* m_tooltip;
TQRect m_lastRepaintRect;
unsigned int m_drawCounter;
};
} // namespace
#endif