/*************************************************************************** register.h ---------- begin : Fri Mar 10 2006 copyright : (C) 2006 by Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * 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 // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #ifdef _CHECK_MEMORY #include #endif #include #include #include #include #include #include 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 QString sortOrderToText(TransactionSortField idx); TransactionSortField textToSortOrder(const QString& text); class QWidgetContainer : public QMap { public: QWidgetContainer() {} QWidget* haveWidget(const QString& name) const { QWidgetContainer::const_iterator it_w; it_w = find(name); if(it_w != end()) return *it_w; return 0; } void removeOrphans(void) { QWidgetContainer::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 QString& txt = QString()); ~GroupMarker(); void setText(const QString& txt) { m_txt = txt; } const QString& 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(QPainter* painter, int row, int col, const QRect& r, bool selected, const QColorGroup& cg); void paintFormCell(QPainter* /* painter */, int /* row */, int /* col */, const QRect& /* r */, bool /* selected */, const QColorGroup& /* cg */) {} int rowHeightHint(void) const; bool matches(const QString&) const { return true; } virtual int sortSamePostDate(void) const { return 0; } protected: void setupColors(QColorGroup& cg); protected: QString m_txt; unsigned int m_drawCounter; bool m_showDate; static QPixmap* m_bg; static int m_bgRefCnt; }; class FancyDateGroupMarker : public GroupMarker { public: FancyDateGroupMarker(Register* parent, const QDate& date, const QString& txt); virtual const QDate& sortPostDate(void) const { return m_date; } virtual const QDate& sortEntryDate(void) const { return m_date; } virtual const char* className(void) { return "FancyDateGroupMarker"; } private: QDate m_date; }; class StatementGroupMarker : public FancyDateGroupMarker { public: StatementGroupMarker(Register* parent, CashFlowDirection dir, const QDate& date, const QString& 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 QDate& date, const QString& txt); void paintRegisterCell(QPainter* painter, int row, int col, const QRect& r, bool selected, const QColorGroup& 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 QDate& date, const QString& txt); virtual const char* className(void) { return "FiscalYearGroupMarker"; } virtual int sortSamePostDate(void) const { return 1; } protected: void setupColors(QColorGroup& cg); }; class PayeeGroupMarker : public GroupMarker { public: PayeeGroupMarker(Register* parent, const QString& name); const QString& sortPayee(void) const { return m_txt; } }; class CategoryGroupMarker : public GroupMarker { public: CategoryGroupMarker(Register* parent, const QString& category); const QString& sortCategory(void) const { return m_txt; } const QString& 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 QValueVector { 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 { Q_OBJECT // friend class QHeader; // friend class QTableHeader; // friend class RegisterItem; friend class Transaction; friend class StdTransaction; friend class InvestTransaction; public: Register(QWidget *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 QValueList */ QValueList 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 QValueList receiving the SelectedTransaction()'s */ void selectedTransactions(SelectedTransactions& list) const; QString text(int row, int col) const; QWidget* createEditor(int row, int col, bool initFromCell) const; void setCellContentFromEditor(int row, int col); QWidget* cellWidget(int row, int col) const; void endEdit(int row, int col, bool accept, bool replace); void paintCell(QPainter* painter, int row, int col, const QRect& r, bool selected, const QColorGroup& cg); void resizeData(int) {} QTableItem* item(int, int) { return 0; } void setItem(int, int, QTableItem*) {} void clearCell(int, int) {} void clearCellWidget(int, int); /** * Override the QTable member function to avoid display of focus */ void paintFocus(QPainter*, const QRect& ) {} /** * Override the QTable 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 QValueList& cols); void setSortOrder(const QString& order); const QValueList& 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(QMap& editWidgets, Transaction* t); void removeEditWidgets(QMap& editWidgets); void tabOrder(QWidgetList& 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 QTable::Single and * QTable::Multi. QTable::Multi is the default when the object is created. */ void setSelectionMode(SelectionMode mode) { m_selectionMode = mode; } protected: void drawContents(QPainter *p, int cx, int cy, int cw, int ch); void contentsMouseReleaseEvent( QMouseEvent *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(QFocusEvent*); void focusInEvent(QFocusEvent*); void keyPressEvent(QKeyEvent*); 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 Qt::Page_Up or Qt::Page_Down depending on the direction to scroll * @param state state of Qt::ShiftButton, Qt::ControlButton, Qt::AltButton and * Qt::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 QString& id) const; void insertWidget(int row, int col, QWidget* w); /** * Override logic and use standard QFrame behaviour */ bool focusNextPrevChild(bool next); bool eventFilter(QObject* o, QEvent* e); void handleItemChange(RegisterItem* old, bool shift, bool control); void selectRange(RegisterItem* from, RegisterItem* to, bool invert, bool includeFirst, bool clearSel); // DND void dragMoveEvent(QDragMoveEvent* event); void dropEvent(QDropEvent* event); Transaction* dropTransaction(QPoint cPos) const; protected slots: void resize(void); void selectItem(int row, int col, int button, const QPoint & mousePos ); void slotEnsureItemVisible(void); void slotDoubleClicked(int, int, int, const QPoint&); 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; QValueVector 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; Qt::ButtonState m_buttonState; Column m_lastCol; QValueList m_sortOrder; QMap, QWidget*> m_cellWidgets; RegisterToolTip* m_tooltip; QRect m_lastRepaintRect; unsigned int m_drawCounter; }; } // namespace #endif // vim:cin:si:ai:et:ts=2:sw=2: