/*************************************************************************** kmymoneysplittable.cpp - description ------------------- begin : Thu Jan 10 2002 copyright : (C) 2000-2002 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif // ---------------------------------------------------------------------------- // TQt Includes #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // TDE Includes #include #include #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "kmymoneysplittable.h" #include #include #include #include #include #include #include #include "../dialogs/kcurrencycalculator.h" #include "../mymoney/mymoneyutils.h" kMyMoneySplitTable::kMyMoneySplitTable(TQWidget *parent, const char *name ) : TQTable(parent,name), m_currentRow(0), m_maxRows(0), m_editMode(false), m_amountWidth(80), m_editCategory(0), m_editMemo(0), m_editAmount(0) { // setup the transactions table setNumRows(1); setNumCols(3); horizontalHeader()->setLabel(0, i18n("Category")); horizontalHeader()->setLabel(1, i18n("Memo")); horizontalHeader()->setLabel(2, i18n("Amount")); setSelectionMode(TQTable::NoSelection); setLeftMargin(0); verticalHeader()->hide(); setColumnStretchable(0, false); setColumnStretchable(1, false); setColumnStretchable(2, false); horizontalHeader()->setResizeEnabled(false); horizontalHeader()->setMovingEnabled(false); horizontalHeader()->setFont(KMyMoneyGlobalSettings::listHeaderFont()); setVScrollBarMode(TQScrollView::AlwaysOn); // never show a horizontal scroll bar setHScrollBarMode(TQScrollView::AlwaysOff); // setup the context menu m_contextMenu = new TDEPopupMenu(this); TDEIconLoader *il = TDEGlobal::iconLoader(); m_contextMenu->insertTitle(il->loadIcon("transaction", TDEIcon::MainToolbar), i18n("Split Options")); m_contextMenu->insertItem(il->loadIcon("edit", TDEIcon::Small), i18n("Edit..."), this, TQ_SLOT(slotStartEdit())); m_contextMenuDuplicate = m_contextMenu->insertItem(il->loadIcon("edit-copy", TDEIcon::Small), i18n("Duplicate"), this, TQ_SLOT(slotDuplicateSplit())); m_contextMenuDelete = m_contextMenu->insertItem(il->loadIcon("delete", TDEIcon::Small), i18n("Delete ..."), this, TQ_SLOT(slotDeleteSplit())); connect(this, TQ_SIGNAL(clicked(int, int, int, const TQPoint&)), this, TQ_SLOT(slotSetFocus(int, int, int, const TQPoint&))); connect(this, TQ_SIGNAL(transactionChanged(const MyMoneyTransaction&)), this, TQ_SLOT(slotUpdateData(const MyMoneyTransaction&))); } kMyMoneySplitTable::~kMyMoneySplitTable() { } void kMyMoneySplitTable::setup(const TQMap& priceInfo) { m_priceInfo = priceInfo; } const TQColor kMyMoneySplitTable::rowBackgroundColor(const int row) const { return (row % 2) ? KMyMoneyGlobalSettings::listColor() : KMyMoneyGlobalSettings::listBGColor(); } void kMyMoneySplitTable::paintCell(TQPainter *p, int row, int col, const TQRect& r, bool /*selected*/) { TQColorGroup g = colorGroup(); TQColor textColor; g.setColor(TQColorGroup::Base, rowBackgroundColor(row)); p->setFont(KMyMoneyGlobalSettings::listCellFont()); TQString firsttext = text(row, col); TQString qstringCategory; TQString qstringMemo; int intPos = firsttext.find("|"); if(intPos > -1) { qstringCategory = firsttext.left(intPos); qstringMemo = firsttext.mid(intPos + 1); } TQRect rr = r; TQRect rr2 = r; rr.setX(0); rr.setY(0); rr.setWidth(columnWidth(col)); rr.setHeight(rowHeight(row)); rr2.setX(2); rr2.setY(0); rr2.setWidth(columnWidth(col)-4); rr2.setHeight(rowHeight(row)); if(row == m_currentRow) { TQBrush backgroundBrush(g.highlight()); textColor = g.highlightedText(); p->fillRect(rr,backgroundBrush); } else { TQBrush backgroundBrush(g.base()); textColor = g.text(); p->fillRect(rr,backgroundBrush); } if (KMyMoneyGlobalSettings::showGrid()) { p->setPen(KMyMoneyGlobalSettings::listGridColor()); if(col != 0) p->drawLine(rr.x(), 0, rr.x(), rr.height()-1); // left frame p->drawLine(rr.x(), rr.y(), rr.width(), 0); // bottom frame p->setPen(textColor); } switch (col) { case 0: // category case 1: // memo p->drawText(rr2, TQt::AlignLeft | TQt::AlignVCenter, text(row, col)); break; case 2: // amount p->drawText(rr2, TQt::AlignRight | TQt::AlignVCenter,firsttext); break; } } /** Override the TQTable member function to avoid display of focus */ void kMyMoneySplitTable::paintFocus(TQPainter * /* p */, const TQRect & /*cr*/) { } void kMyMoneySplitTable::columnWidthChanged(int col) { for (int i=0; i (e); bool rc = false; int row = currentRow(); int lines = visibleHeight()/rowHeight(0); TQWidget* w; if(e->type() == TQEvent::KeyPress && !isEditMode()) { rc = true; switch(k->key()) { case TQt::Key_Up: if(row) slotSetFocus(row-1); break; case TQt::Key_Down: if(row < static_cast (m_transaction.splits().count()-1)) slotSetFocus(row+1); break; case TQt::Key_Home: slotSetFocus(0); break; case TQt::Key_End: slotSetFocus(m_transaction.splits().count()-1); break; case TQt::Key_PageUp: if(lines) { while(lines-- > 0 && row) row--; slotSetFocus(row); } break; case TQt::Key_PageDown: if(row < static_cast (m_transaction.splits().count()-1)) { while(lines-- > 0 && row < static_cast (m_transaction.splits().count()-1)) row++; slotSetFocus(row); } break; case TQt::Key_Delete: slotDeleteSplit(); break; case TQt::Key_Return: case TQt::Key_Enter: if(row < static_cast (m_transaction.splits().count()-1) && KMyMoneyGlobalSettings::enterMovesBetweenFields()) { slotStartEdit(); } else emit returnPressed(); break; case TQt::Key_Escape: emit escapePressed(); break; case TQt::Key_F2: slotStartEdit(); break; default: rc = true; TDEShortcut copySplit(i18n("Duplicate split", "CTRL+c")); TDEShortcut newSplit(TQKeySequence(TQt::CTRL | TQt::Key_Insert)); if(copySplit.contains(KKey(k))) { slotDuplicateSplit(); } else if(newSplit.contains(KKey(k))) { slotSetFocus(m_transaction.splits().count()-1); slotStartEdit(); } else if ( k->text()[ 0 ].isPrint() ) { w = slotStartEdit(); // make sure, the widget receives the key again TQApplication::sendEvent(w, e); } break; } } else if(e->type() == TQEvent::KeyPress && isEditMode()) { bool terminate = true; rc = true; switch(k->key()) { // suppress the F2 functionality to start editing in inline edit mode case TQt::Key_F2: // suppress the cursor movement in inline edit mode case TQt::Key_Up: case TQt::Key_Down: case TQt::Key_PageUp: case TQt::Key_PageDown: break; case TQt::Key_Return: case TQt::Key_Enter: // we cannot call the slot directly, as it destroys the caller of // this method :-( So we let the event handler take care of calling // the respective slot using a timeout. For a KLineEdit derived object // it could be, that at this point the user selected a value from // a completion list. In this case, we close the completion list and // do not end editing of the transaction. if(o->inherits("KLineEdit")) { KLineEdit* le = dynamic_cast (o); TDECompletionBox* box = le->completionBox(false); if(box && box->isVisible()) { terminate = false; le->completionBox(false)->hide(); } } // in case we have the 'enter moves focus between fields', we need to simulate // a TAB key when the object 'o' points to the category or memo field. if(KMyMoneyGlobalSettings::enterMovesBetweenFields()) { if(o == m_editCategory->lineEdit() || o == m_editMemo) { terminate = false; TQKeyEvent evt(e->type(), Key_Tab, 0, k->state(), TQString(), k->isAutoRepeat(), k->count()); TQApplication::sendEvent( o, &evt ); } } if(terminate) { TQTimer::singleShot(0, this, TQ_SLOT(slotEndEditKeyboard())); } break; case TQt::Key_Escape: // we cannot call the slot directly, as it destroys the caller of // this method :-( So we let the event handler take care of calling // the respective slot using a timeout. TQTimer::singleShot(0, this, TQ_SLOT(slotCancelEdit())); break; default: rc = false; break; } } else if(e->type() == TQEvent::KeyRelease && !isEditMode()) { // for some reason, we only see a KeyRelease event of the Menu key // here. In other locations (e.g. Register::eventFilter()) we see // a KeyPress event. Strange. (ipwizard - 2008-05-10) switch(k->key()) { case TQt::Key_Menu: // if the very last entry is selected, the delete // operation is not available otherwise it is m_contextMenu->setItemEnabled(m_contextMenuDelete, row < static_cast (m_transaction.splits().count()-1)); m_contextMenu->setItemEnabled(m_contextMenuDuplicate, row < static_cast (m_transaction.splits().count()-1)); m_contextMenu->exec(TQCursor::pos()); rc = true; break; default: break; } } // if the event has not been processed here, forward it to // the base class implementation if it's not a key event if(rc == false) { if(e->type() != TQEvent::KeyPress && e->type() != TQEvent::KeyRelease) { rc = TQTable::eventFilter(o, e); } } return rc; } void kMyMoneySplitTable::slotSetFocus(int realrow, int /* col */, int button, const TQPoint& /* point */) { MYMONEYTRACER(tracer); int row = realrow; // adjust row to used area if(row > static_cast (m_transaction.splits().count()-1)) row = m_transaction.splits().count()-1; if(row < 0) row = 0; // make sure the row will be on the screen ensureCellVisible(row, 0); if(button == TQt::LeftButton) { // left mouse button if(isEditMode()) { // in edit mode? if(KMyMoneyGlobalSettings::focusChangeIsEnter()) slotEndEdit(); else slotCancelEdit(); } if(row != static_cast (currentRow())) { // setup new current row and update visible selection setCurrentCell(row, 0); slotUpdateData(m_transaction); } } else if(button == TQt::RightButton) { // context menu is only available when cursor is on // an existing transaction or the first line after this area if(row == realrow) { // setup new current row and update visible selection setCurrentCell(row, 0); slotUpdateData(m_transaction); // if the very last entry is selected, the delete // operation is not available otherwise it is m_contextMenu->setItemEnabled(m_contextMenuDelete, row < static_cast (m_transaction.splits().count()-1)); m_contextMenu->setItemEnabled(m_contextMenuDuplicate, row < static_cast (m_transaction.splits().count()-1)); m_contextMenu->exec(TQCursor::pos()); } } } void kMyMoneySplitTable::contentsMousePressEvent( TQMouseEvent* e ) { slotSetFocus( rowAt(e->pos().y()), columnAt(e->pos().x()), e->button(), e->pos() ); } /* turn off TQTable behaviour */ void kMyMoneySplitTable::contentsMouseReleaseEvent( TQMouseEvent* /* e */ ) { } void kMyMoneySplitTable::contentsMouseDoubleClickEvent( TQMouseEvent *e ) { MYMONEYTRACER(tracer); int col = columnAt(e->pos().x()); slotSetFocus( rowAt(e->pos().y()), col, e->button(), e->pos() ); slotStartEdit(); KLineEdit* editWidget = 0; switch(col) { case 1: editWidget = m_editMemo; break; case 2: editWidget = dynamic_cast (m_editAmount->focusWidget()); break; default: break; } if(editWidget) { editWidget->setFocus(); editWidget->selectAll(); // we need to call setFocus on the edit widget from the // main loop again to get the keyboard focus to the widget also TQTimer::singleShot(0, editWidget, TQ_SLOT(setFocus())); } } void kMyMoneySplitTable::setCurrentCell(int row, int /* col */) { MYMONEYTRACER(tracer); if(row > m_maxRows) row = m_maxRows; m_currentRow = row; TQTable::setCurrentCell(row, 0); TQValueList list = getSplits(m_transaction); if(row < static_cast(list.count())) m_split = list[row]; else m_split = MyMoneySplit(); } void kMyMoneySplitTable::setNumRows(int irows) { TQTable::setNumRows(irows); // determine row height according to the edit widgets // we use the category widget as the base TQFontMetrics fm( KMyMoneyGlobalSettings::listCellFont() ); int height = fm.lineSpacing()+6; #if 0 // recalculate row height hint KMyMoneyCategory cat; height = TQMAX(cat.sizeHint().height(), height); #endif verticalHeader()->setUpdatesEnabled(false); for(int i = 0; i < irows; ++i) verticalHeader()->resizeSection(i, height); verticalHeader()->setUpdatesEnabled(true); // add or remove scrollbars as required updateScrollBars(); } void kMyMoneySplitTable::setTransaction(const MyMoneyTransaction& t, const MyMoneySplit& s, const MyMoneyAccount& acc) { MYMONEYTRACER(tracer); m_transaction = t; m_account = acc; m_hiddenSplit = s; setCurrentCell(0, 0); slotUpdateData(m_transaction); } const TQValueList kMyMoneySplitTable::getSplits(const MyMoneyTransaction& t) const { TQValueList list; TQValueList::Iterator it; // get list of splits list = t.splits(); // and ignore the one that should be hidden for(it = list.begin(); it != list.end(); ++it) { if((*it).id() == m_hiddenSplit.id()) { list.remove(it); break; } } return list; } void kMyMoneySplitTable::slotUpdateData(const MyMoneyTransaction& t) { MYMONEYTRACER(tracer); unsigned long rowCount=0; TQValueList list = getSplits(t); updateTransactionTableSize(); // fill the part that is used by transactions TQValueList::Iterator it; kMyMoneyEdit* valfield = new kMyMoneyEdit(); for(it = list.begin(); it != list.end(); ++it) { TQString colText; MyMoneyMoney value = (*it).value(); if(!(*it).accountId().isEmpty()) { try { colText = MyMoneyFile::instance()->accountToCategory((*it).accountId()); } catch(MyMoneyException *e) { tqDebug("Unexpected exception in kMyMoneySplitTable::slotUpdateData()"); delete e; } } TQString amountTxt = value.formatMoney(m_account.fraction()); if(value == MyMoneyMoney::autoCalc) { amountTxt = i18n("will be calculated"); } if(colText.isEmpty() && (*it).memo().isEmpty() && value.isZero()) amountTxt = TQString(); unsigned width = fontMetrics().width(amountTxt); valfield->setMinimumWidth(width); width = valfield->minimumSizeHint().width(); if(width > m_amountWidth) m_amountWidth = width; setText(rowCount, 0, colText); setText(rowCount, 1, (*it).memo()); setText(rowCount, 2, amountTxt); rowCount++; } delete valfield; // now clean out the remainder of the table while(rowCount < static_cast (numRows())) { setText(rowCount, 0, ""); setText(rowCount, 1, ""); setText(rowCount, 2, ""); ++rowCount; } } void kMyMoneySplitTable::updateTransactionTableSize(void) { // get current size of transactions table int rowHeight = cellGeometry(0, 0).height(); // add half a row to the height to avoid unnecessary toggling when // changing the number of rows int tableHeight = (height() + rowHeight/2); int splitCount = m_transaction.splits().count()-1; if(splitCount < 0) splitCount = 0; // see if we need some extra lines to fill the current size with the grid int numExtraLines = (tableHeight / rowHeight) - splitCount; if(numExtraLines < 2) numExtraLines = 2; setNumRows(splitCount + numExtraLines); // setMaxRows(splitCount); m_maxRows = splitCount; } void kMyMoneySplitTable::resizeEvent(TQResizeEvent* /* ev */) { int w = visibleWidth() - m_amountWidth; // resize the columns setColumnWidth(0, w/2); setColumnWidth(1, w/2); setColumnWidth(2, m_amountWidth); updateTransactionTableSize(); } void kMyMoneySplitTable::slotDuplicateSplit(void) { MYMONEYTRACER(tracer); TQValueList list = getSplits(m_transaction); if(m_currentRow < static_cast (list.count())) { MyMoneySplit split = list[m_currentRow]; split.clearId(); try { m_transaction.addSplit(split); emit transactionChanged(m_transaction); } catch(MyMoneyException *e) { tqDebug("Cannot duplicate split: %s", e->what().latin1()); delete e; } } } void kMyMoneySplitTable::slotDeleteSplit(void) { MYMONEYTRACER(tracer); TQValueList list = getSplits(m_transaction); if(m_currentRow < static_cast (list.count())) { if(KMessageBox::warningContinueCancel (this, i18n("You are about to delete the selected split. " "Do you really want to continue?"), i18n("KMyMoney"), i18n("Continue") ) == KMessageBox::Continue) { try { m_transaction.removeSplit(list[m_currentRow]); // if we removed the last split, select the previous if(m_currentRow && m_currentRow == static_cast(list.count())-1) setCurrentCell(m_currentRow-1, 0); else setCurrentCell(m_currentRow, 0); emit transactionChanged(m_transaction); } catch(MyMoneyException *e) { tqDebug("Cannot remove split: %s", e->what().latin1()); delete e; } } } } TQWidget* kMyMoneySplitTable::slotStartEdit(void) { MYMONEYTRACER(tracer); return createEditWidgets(); } void kMyMoneySplitTable::slotEndEdit(void) { endEdit(false); } void kMyMoneySplitTable::slotEndEditKeyboard(void) { endEdit(true); } void kMyMoneySplitTable::endEdit(bool keyBoardDriven) { // Don't proceed, if we're not in edit mode if(!m_editCategory) return; MyMoneyFile* file = MyMoneyFile::instance(); MYMONEYTRACER(tracer); MyMoneySplit s1 = m_split; if (m_editCategory->selectedItem().isEmpty()) { KMessageBox::information(this, i18n("You need to assign a category to this split before it can be entered."), i18n("Enter split"), "EnterSplitWithEmptyCategory"); m_editCategory->setFocus(); return; } bool needUpdate = false; if(m_editCategory->selectedItem() != m_split.accountId()) { s1.setAccountId(m_editCategory->selectedItem()); needUpdate = true; } if(m_editMemo->text() != m_split.memo()) { s1.setMemo(m_editMemo->text()); needUpdate = true; } if(m_editAmount->value() != m_split.value()) { s1.setValue(m_editAmount->value()); needUpdate = true; } if(needUpdate) { if(!s1.value().isZero()) { MyMoneyAccount cat = file->account(s1.accountId()); if(cat.currencyId() != m_transaction.commodity()) { MyMoneySecurity fromCurrency, toCurrency; MyMoneyMoney fromValue, toValue; fromCurrency = file->security(m_transaction.commodity()); toCurrency = file->security(cat.currencyId()); // determine the fraction required for this category int fract = toCurrency.smallestAccountFraction(); if(cat.accountType() == MyMoneyAccount::Cash) fract = toCurrency.smallestCashFraction(); // display only positive values to the user fromValue = s1.value().abs(); // if we had a price info in the beginning, we use it here if(m_priceInfo.find(cat.currencyId()) != m_priceInfo.end()) { toValue = (fromValue * m_priceInfo[cat.currencyId()]).convert(fract); } // if the shares are still 0, we need to change that if(toValue.isZero()) { MyMoneyPrice price = MyMoneyFile::instance()->price(fromCurrency.id(), toCurrency.id()); // if the price is valid calculate the shares. If it is invalid // assume a conversion rate of 1.0 if(price.isValid()) { toValue = (price.rate(toCurrency.id()) * fromValue).convert(fract); } else { toValue = fromValue; } } // now present all that to the user KCurrencyCalculator calc(fromCurrency, toCurrency, fromValue, toValue, m_transaction.postDate(), fract, this, "currencyCalculator"); if(calc.exec() == TQDialog::Rejected) { return; } else { s1.setShares((s1.value() * calc.price()).convert(fract)); } } else { s1.setShares(s1.value()); } } else s1.setShares(s1.value()); m_split = s1; try { if(m_split.id().isEmpty()) { m_transaction.addSplit(m_split); } else { m_transaction.modifySplit(m_split); } emit transactionChanged(m_transaction); } catch(MyMoneyException *e) { tqDebug("Cannot add/modify split: %s", e->what().latin1()); delete e; } } this->setFocus(); destroyEditWidgets(); slotSetFocus(currentRow()+1); // if we still have more splits, we start editing right away // in case we have selected 'enter moves betweeen fields' if(keyBoardDriven && currentRow() < static_cast (m_transaction.splits().count()-1) && KMyMoneyGlobalSettings::enterMovesBetweenFields()) { slotStartEdit(); } } void kMyMoneySplitTable::slotCancelEdit(void) { MYMONEYTRACER(tracer); if(isEditMode()) { destroyEditWidgets(); this->setFocus(); } } bool kMyMoneySplitTable::isEditMode(void) const { return m_editMode; } void kMyMoneySplitTable::destroyEditWidgets(void) { MYMONEYTRACER(tracer); disconnect(MyMoneyFile::instance(), TQ_SIGNAL(dataChanged()), this, TQ_SLOT(slotLoadEditWidgets())); clearCellWidget(m_currentRow, 0); clearCellWidget(m_currentRow, 1); clearCellWidget(m_currentRow, 2); clearCellWidget(m_currentRow+1, 0); m_editMode = false; TQApplication::eventLoop()->processEvents(TQEventLoop::ExcludeUserInput, 100); } TQWidget* kMyMoneySplitTable::createEditWidgets(void) { MYMONEYTRACER(tracer); TQFont cellFont = KMyMoneyGlobalSettings::listCellFont(); m_tabOrderWidgets.clear(); // create the widgets m_editAmount = new kMyMoneyEdit(0); m_editAmount->setFont(cellFont); m_editAmount->setResetButtonVisible(false); m_editCategory = new KMyMoneyCategory(); m_editCategory->setHint(i18n("Category")); m_editCategory->setFont(cellFont); connect(m_editCategory, TQ_SIGNAL(createItem(const TQString&, TQString&)), this, TQ_SIGNAL(createCategory(const TQString&, TQString&))); connect(m_editCategory, TQ_SIGNAL(objectCreation(bool)), this, TQ_SIGNAL(objectCreation(bool))); m_editMemo = new kMyMoneyLineEdit(0, 0, false, AlignLeft|AlignVCenter); m_editMemo->setHint(i18n("Memo")); m_editMemo->setFont(cellFont); // create buttons for the mouse users TDEIconLoader *il = TDEGlobal::iconLoader(); m_registerButtonFrame = new TQFrame(this, "buttonFrame"); TQPalette palette = m_registerButtonFrame->palette(); palette.setColor(TQColorGroup::Background, rowBackgroundColor(m_currentRow+1) ); m_registerButtonFrame->setPalette(palette); TQHBoxLayout* l = new TQHBoxLayout(m_registerButtonFrame); m_registerEnterButton = new KPushButton(il->loadIcon("button_ok", TDEIcon::Small, TDEIcon::SizeSmall), TQString(), m_registerButtonFrame, "EnterButton"); m_registerCancelButton = new KPushButton(il->loadIcon("button_cancel", TDEIcon::Small, TDEIcon::SizeSmall), TQString(), m_registerButtonFrame, "CancelButton"); l->addWidget(m_registerEnterButton); l->addWidget(m_registerCancelButton); l->addStretch(2); connect(m_registerEnterButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotEndEdit())); connect(m_registerCancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotCancelEdit())); // setup tab order addToTabOrder(m_editCategory); addToTabOrder(m_editMemo); addToTabOrder(m_editAmount); addToTabOrder(m_registerEnterButton); addToTabOrder(m_registerCancelButton); if(!m_split.accountId().isEmpty()) { m_editCategory->setSelectedItem(m_split.accountId()); } else { // check if the transaction is balanced or not. If not, // assign the remainder to the amount. MyMoneyMoney diff; TQValueList list = m_transaction.splits(); TQValueList::ConstIterator it_s; for(it_s = list.begin(); it_s != list.end(); ++it_s) { if(!(*it_s).accountId().isEmpty()) diff += (*it_s).value(); } m_split.setValue(-diff); } m_editMemo->loadText(m_split.memo()); // don't allow automatically calculated values to be modified if(m_split.value() == MyMoneyMoney::autoCalc) { m_editAmount->setEnabled(false); m_editAmount->loadText("will be calculated"); } else m_editAmount->setValue(m_split.value()); setCellWidget(m_currentRow, 0, m_editCategory); setCellWidget(m_currentRow, 1, m_editMemo); setCellWidget(m_currentRow, 2, m_editAmount); setCellWidget(m_currentRow+1, 0, m_registerButtonFrame); // load e.g. the category widget with the account list slotLoadEditWidgets(); connect(MyMoneyFile::instance(), TQ_SIGNAL(dataChanged()), this, TQ_SLOT(slotLoadEditWidgets())); // setup the keyboard filter for all widgets for(TQWidget* w = m_tabOrderWidgets.first(); w; w = m_tabOrderWidgets.next()) { w->installEventFilter(this); } m_editCategory->setFocus(); m_editCategory->lineEdit()->selectAll(); m_editMode = true; return m_editCategory->lineEdit(); } void kMyMoneySplitTable::slotLoadEditWidgets(void) { // reload category widget TQString categoryId = m_editCategory->selectedItem(); AccountSet aSet; aSet.addAccountGroup(MyMoneyAccount::Asset); aSet.addAccountGroup(MyMoneyAccount::Liability); aSet.addAccountGroup(MyMoneyAccount::Income); aSet.addAccountGroup(MyMoneyAccount::Expense); if(KMyMoneyGlobalSettings::expertMode()) aSet.addAccountGroup(MyMoneyAccount::Equity); // remove the accounts with invalid types at this point aSet.removeAccountType(MyMoneyAccount::CertificateDep); aSet.removeAccountType(MyMoneyAccount::Investment); aSet.removeAccountType(MyMoneyAccount::Stock); aSet.removeAccountType(MyMoneyAccount::MoneyMarket); aSet.load(m_editCategory->selector()); // if an account is specified then remove it from the widget so that the user // cannot create a transfer with from and to account being the same account if(!m_account.id().isEmpty()) m_editCategory->selector()->removeItem(m_account.id()); if(!categoryId.isEmpty()) m_editCategory->setSelectedItem(categoryId); } void kMyMoneySplitTable::addToTabOrder(TQWidget* w) { if(w) { while(w->focusProxy()) w = w->focusProxy(); m_tabOrderWidgets.append(w); } } bool kMyMoneySplitTable::focusNextPrevChild(bool next) { MYMONEYTRACER(tracer); bool rc = false; if(m_editCategory) { TQWidget *w = 0; TQWidget *currentWidget; m_tabOrderWidgets.find(tqApp->focusWidget()); currentWidget = m_tabOrderWidgets.current(); w = next ? m_tabOrderWidgets.next() : m_tabOrderWidgets.prev(); do { if(!w) { w = next ? m_tabOrderWidgets.first() : m_tabOrderWidgets.last(); } if(w != currentWidget && ((w->focusPolicy() & TQWidget::TabFocus) == TQWidget::TabFocus) && w->isVisible() && w->isEnabled()) { w->setFocus(); rc = true; break; } w = next ? m_tabOrderWidgets.next() : m_tabOrderWidgets.prev(); } while(w != currentWidget); } else rc = TQTable::focusNextPrevChild(next); return rc; } #include "kmymoneysplittable.moc"