/***************************************************************************
                          transaction.cpp  -  description
                             -------------------
    begin                : Tue Jun 13 2006
    copyright            : (C) 2000-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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

// ----------------------------------------------------------------------------
// TQt Includes

#include <tqstring.h>
#include <tqpainter.h>
#include <tqwidgetlist.h>

// ----------------------------------------------------------------------------
// TDE Includes

#include <tdelocale.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <kdebug.h>

// ----------------------------------------------------------------------------
// Project Includes

#include <kmymoney/transaction.h>
#include <kmymoney/mymoneytransaction.h>
#include <kmymoney/mymoneysplit.h>
#include <kmymoney/mymoneyfile.h>
#include <kmymoney/mymoneypayee.h>
#include <kmymoney/register.h>
#include <kmymoney/kmymoneycategory.h>
#include <kmymoney/kmymoneydateinput.h>
#include <kmymoney/transactionform.h>
#include <kmymoney/kmymoneylineedit.h>
#include <kmymoney/kmymoneyedit.h>
#include <kmymoney/transactioneditor.h>
#include <kmymoney/investtransactioneditor.h>
#include <kmymoney/kmymoneyutils.h>

#include "../kmymoneyglobalsettings.h"

using namespace KMyMoneyRegister;
using namespace KMyMoneyTransactionForm;

static unsigned char attentionSign[] = {
  0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,
  0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
  0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x14,
  0x08,0x06,0x00,0x00,0x00,0x8D,0x89,0x1D,
  0x0D,0x00,0x00,0x00,0x04,0x73,0x42,0x49,
  0x54,0x08,0x08,0x08,0x08,0x7C,0x08,0x64,
  0x88,0x00,0x00,0x00,0x19,0x74,0x45,0x58,
  0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,
  0x65,0x00,0x77,0x77,0x77,0x2E,0x69,0x6E,
  0x6B,0x73,0x63,0x61,0x70,0x65,0x2E,0x6F,
  0x72,0x67,0x9B,0xEE,0x3C,0x1A,0x00,0x00,
  0x02,0x05,0x49,0x44,0x41,0x54,0x38,0x8D,
  0xAD,0x95,0xBF,0x4B,0x5B,0x51,0x14,0xC7,
  0x3F,0x2F,0xBC,0x97,0x97,0x97,0x97,0x77,
  0xF3,0xF2,0x1C,0xA4,0x54,0x6B,0x70,0x10,
  0x44,0x70,0x2A,0x91,0x2E,0x52,0x02,0x55,
  0x8A,0xB5,0xA3,0xAB,0x38,0x08,0x66,0xCC,
  0xEE,0xE0,0xE2,0x20,0xB8,0x38,0xB8,0xB8,
  0xF8,0x1F,0x38,0x29,0xA5,0x29,0x74,0x90,
  0x0E,0x0D,0x0E,0x22,0x1D,0x44,0xA8,0xD0,
  0xD4,0xB4,0x58,0x4B,0x09,0xF9,0xF1,0x4A,
  0x3B,0xD4,0xD3,0xE1,0x55,0xD3,0x34,0xAF,
  0x49,0x6C,0x3D,0xF0,0x85,0x7B,0xCF,0xFD,
  0x9E,0xEF,0x3D,0xE7,0xFE,0xD4,0x44,0x84,
  0xDB,0xB4,0x48,0x2F,0xA4,0x94,0xAB,0xE5,
  0x52,0xAE,0x96,0xEB,0x49,0x51,0x44,0x3A,
  0x02,0x18,0x88,0xC7,0xF1,0xE3,0x71,0x7C,
  0x60,0xA0,0x1B,0xBF,0x6B,0x86,0x49,0xC5,
  0x46,0x3E,0x47,0x34,0x9F,0x23,0x9A,0x54,
  0x6C,0xFC,0x57,0x86,0x40,0xC6,0x4B,0xE1,
  0x37,0xCA,0x48,0xA3,0x8C,0x78,0x29,0x7C,
  0x20,0xD3,0x31,0xA6,0xD3,0xA0,0x52,0x1C,
  0x6D,0x6F,0x72,0xD9,0x28,0x23,0xFE,0x07,
  0x64,0x7B,0x93,0x4B,0xA5,0x38,0xFA,0x27,
  0x41,0x60,0x6E,0x74,0x84,0x7A,0xE5,0x1D,
  0x92,0x54,0x88,0xE7,0x22,0xD5,0x12,0x32,
  0x3A,0x42,0x1D,0x98,0xBB,0x91,0x20,0x60,
  0xDA,0x36,0x17,0xFB,0x7B,0xC8,0xC1,0x4B,
  0x04,0x02,0xBC,0x7E,0x81,0xEC,0xEF,0x21,
  0xB6,0xCD,0x05,0x60,0xF6,0x2C,0x68,0x9A,
  0x2C,0xCF,0x4C,0xE1,0x4B,0x05,0x39,0x3F,
  0x69,0x0A,0xBE,0x7F,0x83,0x48,0x05,0x99,
  0x99,0xC2,0x37,0x4D,0x96,0x7B,0x12,0x04,
  0xFA,0x2D,0x8B,0xC6,0xE9,0x61,0x10,0x2C,
  0x15,0xC4,0x8A,0x21,0x86,0x8E,0xFC,0xF8,
  0x12,0xF4,0x4F,0x0F,0x11,0xCB,0xA2,0x01,
  0xF4,0x77,0x3D,0x36,0x4E,0x82,0xF5,0xA5,
  0x05,0x8C,0xE1,0x74,0xD3,0x37,0x34,0x18,
  0x20,0xF2,0x8B,0x3D,0x9C,0x86,0xA5,0x05,
  0x0C,0x27,0xC1,0x7A,0xC7,0x63,0x03,0x8C,
  0x2B,0x07,0xBF,0x5A,0x6A,0x66,0x27,0x15,
  0x64,0x3A,0x8B,0x3C,0x7A,0xD8,0xEA,0xAB,
  0x96,0x10,0xE5,0xE0,0x03,0xE3,0x7F,0xCD,
  0x50,0x39,0x6C,0xAD,0xAD,0x10,0x53,0xAA,
  0x75,0xD2,0xF4,0xBD,0x00,0x2D,0x5C,0x05,
  0x6B,0x2B,0xC4,0x94,0xC3,0xD6,0xEF,0xFE,
  0x6B,0x41,0x4D,0xD3,0x66,0xFB,0x3C,0xC6,
  0x16,0xE7,0xDB,0x97,0x61,0xE2,0x3E,0x3C,
  0xC8,0xB4,0x15,0xC7,0xE2,0x3C,0x91,0x3E,
  0x8F,0x31,0x4D,0xD3,0x66,0x5B,0x4A,0x06,
  0x8C,0x84,0xCD,0x59,0x61,0xA7,0xB5,0xAC,
  0x2B,0x9C,0x1C,0x04,0x08,0x1B,0x2B,0xEC,
  0x20,0x09,0x9B,0x33,0xC0,0xB8,0xDE,0x65,
  0x43,0x27,0x9F,0x9D,0xA4,0x1E,0x16,0xF0,
  0xF9,0x6D,0xB0,0xC3,0x86,0x1E,0xB4,0xC3,
  0x38,0xD9,0x49,0xEA,0x86,0x4E,0xFE,0xEA,
  0x29,0xF4,0x2C,0x8B,0xDA,0x71,0x31,0x9C,
  0xFC,0xF5,0x23,0x32,0x34,0x88,0xDC,0xBD,
  0x13,0x5C,0xBF,0x30,0xCE,0x71,0x11,0xB1,
  0x2C,0x6A,0x80,0xA7,0xDB,0x36,0xAB,0x4F,
  0xA6,0x89,0xBA,0x49,0x38,0xFF,0xD4,0xBE,
  0x4E,0x00,0xAF,0x9E,0x81,0x08,0xD4,0xEA,
  0x01,0xFE,0x34,0x37,0x09,0x4F,0x1F,0x13,
  0xDD,0x7D,0xCE,0xAA,0x96,0x72,0x29,0x7C,
  0xFB,0xCE,0x44,0xB8,0xD4,0xCD,0x2C,0x66,
  0x52,0xD4,0x6E,0xFB,0x0B,0xF8,0x09,0x63,
  0x63,0x31,0xE4,0x85,0x76,0x2E,0x0E,0x00,
  0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,
  0x42,0x60,0x82
};

Transaction::Transaction(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId) :
  RegisterItem(parent),
  m_transaction(transaction),
  m_split(split),
  m_form(0),
  m_uniqueId(m_transaction.id()),
  m_formRowHeight(-1),
  m_selected(false),
  m_focus(false),
  m_erronous(false),
  m_inEdit(false),
  m_inRegisterEdit(false),
  m_showBalance(true),
  m_reducedIntensity(false)
{
  MyMoneyFile* file = MyMoneyFile::instance();

  // load the account
  if(!m_split.accountId().isEmpty())
    m_account = file->account(m_split.accountId());

  // load the payee
  if(!m_split.payeeId().isEmpty()) {
    m_payee = file->payee(m_split.payeeId()).name();
  }
  if(parent->account().isIncomeExpense()) {
    m_payeeHeader = m_split.shares().isNegative() ? i18n("From") : i18n("Pay to");
  } else {
    m_payeeHeader = m_split.shares().isNegative() ? i18n("Pay to") : i18n("From");
  }

  // load the currency
  if(!m_transaction.id().isEmpty())
    m_splitCurrencyId = m_account.currencyId();

  // check if transaction is errnous or not
  m_erronous = !m_transaction.splitSum().isZero();

  if(!m_uniqueId.isEmpty()) {
    m_uniqueId += "-";
    TQString id;
    id.setNum(uniqueId);
    m_uniqueId += id.rightJustify(3, '0');
  }
}

void Transaction::setFocus(bool focus, bool updateLens)
{
  if(focus != m_focus) {
    m_focus = focus;
  }
  if(updateLens) {
    if(KMyMoneyGlobalSettings::ledgerLens()
    || !KMyMoneyGlobalSettings::transactionForm()
    || KMyMoneyGlobalSettings::showRegisterDetailed()
    || m_parent->m_ledgerLensForced) {
      if(focus)
        setNumRowsRegister(numRowsRegister(true));
      else
        setNumRowsRegister(numRowsRegister(KMyMoneyGlobalSettings::showRegisterDetailed()));
    }
  }
}

void Transaction::markAttachment(TQPainter* painter, int /* row */, int /* col */, const TQRect& r)
{
  static TQPixmap clip;

  const int m = 2;  // margin
  int h = m_parent->rowHeightHint() - (2*m);
  int lx = r.topRight().x() - h;
  if(isErronous())
    lx -= h;
  TQRect cr(TQPoint(lx - m, m), TQSize(h, h));

  painter->save();
  if(clip.isNull()) {
    clip = TDEGlobal::iconLoader()->loadIcon("attach", TDEIcon::Small, TDEIcon::SizeSmall, TDEIcon::DefaultState);
    if(clip.height() > h) {
      clip.resize(h, h);
    }
  }

  painter->drawPixmap(TQPoint(lx - m, m + (h - clip.height())/2 ), clip);
  painter->restore();
}

void Transaction::markAsErronous(TQPainter* painter, int /* row */, int /* col */, const TQRect& r)
{
  const int m = 2;  // margin
  int h = m_parent->rowHeightHint() - (2*m);
  TQRect cr(TQPoint(r.topRight().x() - h - m, m), TQSize(h, h));

  painter->save();
  TQPixmap attention;
  attention.loadFromData(attentionSign, sizeof(attentionSign), 0, 0);

  if(attention.height() > h) {
    attention.resize(h, h);
  }
  painter->drawPixmap(TQPoint(r.topRight().x() - h - m, m + (h - attention.height())/2 ), attention);
  painter->restore();

}

bool Transaction::paintRegisterCellSetup(TQPainter* painter, int& row, int& col, TQRect& cellRect, TQRect& textRect, TQColorGroup& cg, TQBrush& brush)
{
  if(m_reducedIntensity)
    cg = m_parent->palette().disabled();

  if(m_alternate)
    cg.setColor(TQColorGroup::Base, KMyMoneyGlobalSettings::listColor());
  else
    cg.setColor(TQColorGroup::Base, KMyMoneyGlobalSettings::listBGColor());

  cellRect.setX(0);
  cellRect.setY(0);
  cellRect.setWidth(m_parent->columnWidth(col));
  cellRect.setHeight(m_parent->rowHeight(m_startRow + row));

  textRect = cellRect;
  textRect.setX(2);
  textRect.setWidth(textRect.width()-4);

  if(m_selected) {
    brush = TQBrush(cg.highlight());
    painter->setPen(cg.highlightedText());
  } else {
    brush = TQBrush(cg.base());
    painter->setPen(cg.text());
  }

  // do we need to switch to the error color?
  if(m_erronous && m_parent->markErronousTransactions()) {
    painter->setPen(KMyMoneyGlobalSettings::listErronousTransactionColor());
  }

  // do we need to switch to the negative balance color?
  if(col == BalanceColumn) {
    bool showNegative = m_balance.isNegative();
    if(m_account.accountGroup() == MyMoneyAccount::Liability && !m_balance.isZero() )
      showNegative = !showNegative;
    if(showNegative)
      painter->setPen(KMyMoneyGlobalSettings::listNegativeValueColor());
  }
  return true;
}

void Transaction::paintRegisterCellFocus(TQPainter* painter, int row, int col, const TQRect& r, const TQColorGroup& cg)
{

  if(m_focus) {
    TQPen oldPen = painter->pen();
    TQPen newPen = oldPen;
    newPen.setWidth(0);

    painter->setFont(KMyMoneyGlobalSettings::listCellFont());
    painter->setPen(newPen);
    painter->setPen(cg.foreground());
    painter->setPen(TQt::DotLine);
    // for the first Row, we need to paint the top
    TQPoint start, end;
#if 0
    if(row == 0) {
      start = TQPoint(r.x(), r.y() + 1);
      end = TQPoint(r.x() + r.width(), r.y() + 1);
      if(col == 0) {
        start.rx()++;
      } else if(col == m_parent->lastCol()) {
        end.rx()--;
      }
      // painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the last Row, we need to paint the bottom
    if(row == numRows() - 1) {
      start = TQPoint(r.x(), r.y() + r.height() - 1);
      end = TQPoint(r.x() + r.width(), r.y() + r.height() - 1);
      if(col == 0) {
        start.rx()++;
      } else if(col == m_parent->lastCol()) {
        end.rx()--;
      }
      // painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the first col, we need to paint the left
    if(col == 0) {
      start = TQPoint(r.x() + 1, r.y());
      end = TQPoint(r.x() + 1, r.y() + r.height());
      if(row == 0) {
        start.ry()++;
      } else if(row == numRows()-1) {
        end.ry()--;
      }
      //painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the last col, we need to paint the left
    if(col == m_parent->lastCol()) {
      start = TQPoint(r.x() + r.width() - 1, r.y());
      end = TQPoint(r.x() + r.width() - 1, r.y() + r.height());
      if(row == 0) {
        start.ry()++;
      } else if(row == numRows()-1) {
        end.ry()--;
      }
      //painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
#endif
    if(row == 0) {
      start = TQPoint(r.x(), r.y());
      end = TQPoint(r.x() + r.width(), r.y() + 1);
      if(col == 0) {
        start.rx()++;
      } else if(col == m_parent->lastCol()) {
        end.rx()--;
      }
      // painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the last Row, we need to paint the bottom
    if(row == numRowsRegister() - 1) {
      start = TQPoint(r.x(), r.y() + r.height() - 2);
      end = TQPoint(r.x() + r.width(), r.y() + r.height() - 2);
      if(col == 0) {
        start.rx()++;
      } else if(col == m_parent->lastCol()) {
        end.rx()--;
      }
      // painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the first col, we need to paint the left
    if(col == 0) {
      start = TQPoint(r.x() + 1, r.y());
      end = TQPoint(r.x() + 1, r.y() + r.height());
      if(row == 0) {
        start.ry()++;
      } else if(row == numRowsRegister()-1) {
        end.ry()--;
      }
      //painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    // for the last col, we need to paint the left
    if(col == m_parent->lastCol()) {
      start = TQPoint(r.x() + r.width() - 1, r.y());
      end = TQPoint(r.x() + r.width() - 1, r.y() + r.height());
      if(row == 0) {
        start.ry()++;
      } else if(row == numRowsRegister()-1) {
        end.ry()--;
      }
      //painter->drawLine(start, end);
      painter->drawWinFocusRect(TQRect(start, end));
    }
    painter->setPen(oldPen);
  }
}

void Transaction::registerCellText(TQString& txt, int row, int col)
{
  int align = 0;
  registerCellText(txt, align, row, col, 0);
}

void Transaction::paintRegisterCell(TQPainter* painter, int row, int col, const TQRect& r, bool /* selected */, const TQColorGroup& _cg)
{
  TQColorGroup cg(_cg);
  TQRect cellRect(r);
  TQRect textRect;
  TQBrush backgroundBrush;

  painter->save();

  if(paintRegisterCellSetup(painter, row, col, cellRect, textRect, cg, backgroundBrush)) {
    // construct the text for the cell
    int align = TQt::AlignVCenter;
    TQString txt;
    if(m_transaction != MyMoneyTransaction() && !m_inRegisterEdit) {
      registerCellText(txt, align, row, col, painter);
    }

    paintRegisterCellBackground(painter, row, col, cellRect, backgroundBrush);

    // and paint it
    paintRegisterCellText(painter, row, col, textRect, cg, align, txt);

    // paint the grid
    paintRegisterGrid(painter, row, col, cellRect, cg);

    // possible icons
    paintRegisterIcons(painter, row, col, cellRect, cg);

    // and the focus
    paintRegisterCellFocus(painter, row, col, cellRect, cg);
  }

  painter->restore();
}

void Transaction::paintRegisterIcons(TQPainter* painter, int row, int col, const TQRect& /*r*/, const TQColorGroup& /*cg*/)
{
  if(row == 0 && col == DetailColumn && painter) {
    if(m_erronous || !m_transaction.value("kmm-attachment").isEmpty()) {
      TQRect cellRect;
      cellRect.setX(0);
      cellRect.setY(0);
      cellRect.setWidth(m_parent->columnWidth(col));
      cellRect.setHeight(m_parent->rowHeight(m_startRow + row));
      if(m_erronous) {
        markAsErronous(painter, row, col, cellRect);
      }
      if(!m_transaction.value("kmm-attachment").isEmpty()) {
        markAttachment(painter, row, col, cellRect);
      }
    }
  }
}
void Transaction::paintRegisterCellBackground(TQPainter* painter, int row, int col, const TQRect& r, const TQBrush& backgroundBrush)
{
  Q_UNUSED(row);
  Q_UNUSED(col);

  // fill the background
  painter->fillRect(r, backgroundBrush);
}

void Transaction::paintRegisterGrid(TQPainter* painter, int row, int col, const TQRect& r, const TQColorGroup& _cg) const
{
  Q_UNUSED(_cg);

  // if a grid is selected, we paint it right away
  if (KMyMoneyGlobalSettings::showGrid()) {
    painter->setPen(KMyMoneyGlobalSettings::listGridColor());
    if(col != 0)
      painter->drawLine(r.x(), 0, r.x(), r.height()-1);
    if(row == numRowsRegister()-1)
      painter->drawLine(r.x(), r.height()-1, r.width(), r.height()-1);
  }
}

void Transaction::paintRegisterCellText(TQPainter* painter, int row, int col, const TQRect& r, const TQColorGroup& _cg, int align, const TQString& txt)
{
  Q_UNUSED(row);
  Q_UNUSED(col);
  Q_UNUSED(r);
  Q_UNUSED(_cg);

  // make sure, we clear the cell
  if(txt.isEmpty())
    painter->drawText(r, align, " ");
  else
    painter->drawText(r, align, txt);
}

int Transaction::formRowHeight(int /*row*/)
{
  if(m_formRowHeight < 0) {
    m_formRowHeight = formRowHeight();
  }
  return m_formRowHeight;
}

int Transaction::formRowHeight(void) const
{
  if(m_formRowHeight < 0) {
    // determine the height of the objects in the table
    kMyMoneyDateInput dateInput;
    KMyMoneyCategory category(0,0,true);

    return TQMAX(dateInput.sizeHint().height(), category.sizeHint().height());
  }
  return m_formRowHeight;
}

void Transaction::setupForm(TransactionForm* form)
{
  m_form = form;
  form->verticalHeader()->setUpdatesEnabled(false);
  form->horizontalHeader()->setUpdatesEnabled(false);

  form->setNumRows(numRowsForm());
  form->setNumCols(numColsForm());

  // Force all cells to have some text (so that paintCell is called for each cell)
  for(int r = 0; r < numRowsForm(); ++r) {
    for(int c = 0; c < numColsForm(); ++c) {
      form->setText(r, c, "x");
      if(r == 0 && form->columnWidth(c) == 0) {
        form->setColumnWidth(c, 10);
      }
    }
  }
  form->horizontalHeader()->setUpdatesEnabled(true);
  form->verticalHeader()->setUpdatesEnabled(true);

  loadTab(form);
}

void Transaction::paintFormCell(TQPainter* painter, int row, int col, const TQRect& /*r*/, bool /*selected*/, const TQColorGroup& _cg)
{
  if(!m_form)
    return;

  TQRect cellRect = m_form->cellRect(row, col);

  TQRect textRect(cellRect);
  textRect.setX(1);
  textRect.setY(1);
  textRect.setWidth(textRect.width()-2);
  textRect.setHeight(textRect.height()-2);

  painter->fillRect(cellRect, _cg.background());
  painter->setPen(_cg.text());

  TQString txt;
  int align = TQt::AlignVCenter;
  bool editField = formCellText(txt, align, row, col, painter);

  // if we have an editable field and don't currently edit the transaction
  // show the background in a different color
  if(editField && !m_inEdit) {
    painter->fillRect(textRect, _cg.base());
  }

  // make sure, we clear the cell
  // in case of an editable field and edit mode, we just clear the field
  if(txt.isEmpty() || (editField && m_inEdit))
    painter->drawText(textRect, align, " ");
  else
    painter->drawText(textRect, align, txt);

}

void Transaction::setupPalette(const TQPalette& palette, TQMap<TQString, TQWidget*>& editWidgets)
{
  TQMap<TQString, TQWidget*>::iterator it_w;
  for(it_w = editWidgets.begin(); it_w != editWidgets.end(); ++it_w) {
    if(*it_w) {
      (*it_w)->setPalette(palette);
    }
  }
}

void Transaction::setupFormPalette(TQMap<TQString, TQWidget*>& editWidgets)
{
  setupPalette(m_parent->palette(), editWidgets);
}

void Transaction::setupRegisterPalette(TQMap<TQString, TQWidget*>& editWidgets)
{
  // make sure, we're using the right palette
  TQPalette palette = m_parent->palette();

  // use the highlight color as background
  palette.setColor(TQPalette::Active, TQColorGroup::Background, palette.color(TQPalette::Active, TQColorGroup::Highlight));

  setupPalette(palette, editWidgets);
}

TQWidget* Transaction::focusWidget(TQWidget* w) const
{
  if(w) {
    while(w->focusProxy())
      w = w->focusProxy();
  }
  return w;
}

void Transaction::arrangeWidget(TQTable* tbl, int row, int col, TQWidget* w) const
{
  if(w) {
    tbl->setCellWidget(row, col, w);
    // remove the widget from the TQTable's eventFilter so that all
    // events will be directed to the edit widget
    w->removeEventFilter(tbl);
  } else
    tqDebug("No widget for %d,%d", row, col);
}

bool Transaction::haveNumberField(void) const
{
  bool rc = true;
  switch(m_account.accountType()) {
    case MyMoneyAccount::Savings:
    case MyMoneyAccount::Cash:
    case MyMoneyAccount::Loan:
    case MyMoneyAccount::AssetLoan:
    case MyMoneyAccount::Asset:
    case MyMoneyAccount::Liability:
    case MyMoneyAccount::Equity:
      rc = KMyMoneyGlobalSettings::alwaysShowNrField();
      break;

    case MyMoneyAccount::Checkings:
    case MyMoneyAccount::CreditCard:
    // the next case is used for the editor when the account
    // is unknown (eg. when creating new schedules)
    case MyMoneyAccount::UnknownAccountType:
      break;

    default:
      rc = false;
      break;
  }
  return rc;
}

bool Transaction::maybeTip(const TQPoint& cpos, int row, int col, TQRect& r, TQString& msg)
{
  if(col != DetailColumn)
    return false;

  if(!m_erronous && m_transaction.splitCount() < 3)
    return false;

  int h = m_parent->rowHeightHint();

  // check for detail column in row 0 of the transaction for a possible exclamation mark
  r = m_parent->cellGeometry(m_startRow + 0, col);
  // tqDebug("r is %d,%d,%d,%d", r.x(), r.y(), r.width(), r.height());
  r.setBottomLeft(TQPoint(r.x() + (r.width() - h), r.y() + h));
  // tqDebug("r is %d,%d,%d,%d", r.x(), r.y(), r.width(), r.height());
  // tqDebug("p is in r = %d", r.contains(cpos));
  if(r.contains(cpos) && m_erronous) {
    if(m_transaction.splits().count() < 2) {
      msg = TQString("<qt>%1</qt>").arg(i18n("Transaction is missing a category assignment."));
    } else {
      const MyMoneySecurity& sec = MyMoneyFile::instance()->security(m_account.currencyId());
      msg = TQString("<qt>%1</qt>").arg(i18n("The transaction has a missing assignment of <b>%1</b>.").arg(m_transaction.splitSum().abs().formatMoney(m_account, sec)));
    }
    return true;
  }

  // check for detail column in row 1 of the transaction for a possible exclamation mark
  r = m_parent->cellGeometry(m_startRow + 1, col);
  if(row == 1 && r.contains(cpos) && m_transaction.splitCount() > 2) {
    MyMoneyFile* file = MyMoneyFile::instance();
    TQValueList<MyMoneySplit>::const_iterator it_s;
    TQString txt;
    const MyMoneySecurity& sec = file->security(m_transaction.commodity());
    MyMoneyMoney factor(1, 1);
    if(!m_split.value().isNegative())
      factor = -factor;

    for(it_s = m_transaction.splits().begin(); it_s != m_transaction.splits().end(); ++it_s) {
      if(*it_s == m_split)
        continue;
      const MyMoneyAccount& acc = file->account((*it_s).accountId());
      TQString category = file->accountToCategory(acc.id());
      TQString amount = ((*it_s).value() * factor).formatMoney(acc, sec);

      txt += TQString("<tr><td><nobr>%1</nobr></td><td align=right><nobr>%2</nobr></td></tr>").arg(category, amount);
    }
    msg = TQString("<table>%1</table>").arg(txt);
    return true;
  }

  return false;
}

TQString Transaction::reconcileState(bool text) const
{
  TQString txt = KMyMoneyUtils::reconcileStateToString(m_split.reconcileFlag(), text);

  if((text == true)
  && (txt == i18n("Unknown"))
  && (m_transaction == MyMoneyTransaction()))
    txt = TQString();
  return txt;
}

void Transaction::startEditMode(void)
{
  m_inEdit = true;
  // only update the number of lines displayed if we edit inside the register
  if(m_inRegisterEdit)
    setNumRowsRegister(numRowsRegister(true));
}

void Transaction::leaveEditMode(void)
{
  m_inEdit = false;
  m_inRegisterEdit = false;
  setFocus(hasFocus(), true);
}

void Transaction::singleLineMemo(TQString& txt, const MyMoneySplit& split) const
{
  txt = split.memo();
  // remove empty lines
  txt.replace("\n\n", "\n");
  // replace '\n' with ", "
  txt.replace('\n', ", ");
}

int Transaction::rowHeightHint(void) const
{
  return m_inEdit ? formRowHeight()-4 : RegisterItem::rowHeightHint();
}


bool Transaction::matches(const TQString& txt) const
{
  if(txt.isEmpty() || m_transaction.splitCount() == 0)
    return true;

  MyMoneyFile* file = MyMoneyFile::instance();
  TQString s(txt);
  s.replace(MyMoneyMoney::thousandSeparator(), TQString());

  const TQValueList<MyMoneySplit>&list = m_transaction.splits();
  TQValueList<MyMoneySplit>::const_iterator it_s;
  for(it_s = list.begin(); it_s != list.end(); ++it_s) {
    // check if the text is contained in one of the fields
    // memo, number, payee, account
    if((*it_s).memo().contains(txt, false)
       || (*it_s).number().contains(txt, false))
      return true;

    if(!(*it_s).payeeId().isEmpty()) {
      const MyMoneyPayee& payee = file->payee((*it_s).payeeId());
      if(payee.name().contains(txt, false))
        return true;
    }
    const MyMoneyAccount& acc = file->account((*it_s).accountId());
    if(acc.name().contains(txt, false))
      return true;

    if(!s.isEmpty()) {
      // check if any of the value field matches if a value has been entered
      TQString r = (*it_s).value().formatMoney(m_account.fraction(), false);
      if(r.contains(s, false))
        return true;
      const MyMoneyAccount& acc = file->account((*it_s).accountId());
      r = (*it_s).shares().formatMoney(acc.fraction(), false);
      if(r.contains(s, false))
        return true;
    }
  }

  return false;
}

void Transaction::setShowBalance(bool showBalance)
{
  m_showBalance = showBalance;
}

void Transaction::setVisible(bool visible)
{
  if(visible != isVisible()) {
    RegisterItem::setVisible(visible);
    RegisterItem* p;
    Transaction* t;
    if(!visible) {
      // if we are hidden, we need to inform all previous transactions
      // about it so that they don't show the balance
      p = prevItem();
      while(p) {
        t = dynamic_cast<Transaction*>(p);
        if(t) {
          if(!t->m_showBalance)
            break;
          t->m_showBalance = false;
        }
        p = p->prevItem();
      }
    } else {
      // if we are shown, we need to check if the next transaction
      // is visible and change the display of the balance
      p = this;
      do {
        p = p->nextItem();
        t = dynamic_cast<Transaction*>(p);
      } while(!t && p);

      // if the next transaction is visible or I am the last one
      if((t && t->m_showBalance) || !t) {
        m_showBalance = true;
        p = prevItem();
        while(p && p->isVisible()) {
          t = dynamic_cast<Transaction*>(p);
          if(t) {
            if(t->m_showBalance)
              break;
            t->m_showBalance = true;
          }
          p = p->prevItem();
        }
      }
    }
  }
}

void Transaction::setSelected(bool selected)
{
  if(!selected || (selected && isVisible()))
    m_selected = selected;
}

StdTransaction::StdTransaction(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId) :
  Transaction(parent, transaction, split, uniqueId),
  m_showAccountRow(false)
{
  try {
    m_categoryHeader = i18n("Category");
    switch(transaction.splitCount()) {
      default:
        m_category = i18n("Split transaction (category replacement)", "Split transaction");
        break;

      case 0: // the empty transaction
      case 1:
        break;

      case 2:
        setupFormHeader(m_transaction.splitByAccount(m_split.accountId(), false).accountId());
        break;
    }
  } catch(MyMoneyException *e) {
    kdDebug(2) << "Problem determining the category for transaction '" << m_transaction.id() << "'. Reason: " << e->what()  << "\n";
    delete e;
  }
  m_rowsForm = 6;

  if(KMyMoneyUtils::transactionType(m_transaction) == KMyMoneyUtils::InvestmentTransaction) {
    MyMoneySplit split = KMyMoneyUtils::stockSplit(m_transaction);
    m_payee = MyMoneyFile::instance()->account(split.accountId()).name();
    TQString addon;
    if(split.action() == MyMoneySplit::ActionBuyShares) {
      if(split.value().isNegative()) {
        addon = i18n("Sell");
      } else {
        addon = i18n("Buy");
      }
    } else if(split.action() == MyMoneySplit::ActionDividend) {
        addon = i18n("Dividend");
    } else if(split.action() == MyMoneySplit::ActionYield) {
        addon = i18n("Yield");
    }
    if(!addon.isEmpty()) {
      m_payee += TQString(" (%1)").arg(addon);
    }
    m_payeeHeader = i18n("Activity");
    m_category = i18n("Investment transaction");
  }

  // setup initial size
  setNumRowsRegister(numRowsRegister(KMyMoneyGlobalSettings::showRegisterDetailed()));

  emit parent->itemAdded(this);
}

void StdTransaction::setupFormHeader(const TQString& id)
{
  m_category = MyMoneyFile::instance()->accountToCategory(id);
  switch(MyMoneyFile::instance()->account(id).accountGroup()) {
    case MyMoneyAccount::Asset:
    case MyMoneyAccount::Liability:
      m_categoryHeader = m_split.shares().isNegative() ? i18n("Transfer to") : i18n("Transfer from");
      break;

    default:
      m_categoryHeader = i18n("Category");
      break;
  }
}

KMyMoneyRegister::Action StdTransaction::actionType(void) const
{
  KMyMoneyRegister::Action action=ActionNone;

  // if at least one split is referencing an income or
  // expense account, we will not call it a transfer
  TQValueList<MyMoneySplit>::const_iterator it_s;

  for(it_s = m_transaction.splits().begin(); it_s != m_transaction.splits().end(); ++it_s) {
    if((*it_s).accountId() == m_split.accountId())
      continue;
    MyMoneyAccount acc = MyMoneyFile::instance()->account((*it_s).accountId());
    if(acc.accountGroup() == MyMoneyAccount::Income
    || acc.accountGroup() == MyMoneyAccount::Expense) {
      // otherwise, we have to determine between deposit and withdrawal
      action = m_split.shares().isNegative() ? ActionWithdrawal : ActionDeposit;
      break;
    }
  }
    // otherwise, it's a transfer
  if(it_s == m_transaction.splits().end())
    action = ActionTransfer;

  return action;
}

void StdTransaction::loadTab(TransactionForm* form)
{
  TabBar* bar = form->tabBar();
  bar->setSignalEmission(TabBar::SignalNever);
  for(int i = 0; i < bar->count(); ++i) {
    bar->setTabEnabled(bar->tabAt(i)->identifier(), true);
  }

  if(m_transaction.splitCount() > 0) {
    bar->setCurrentTab(actionType());
  }
  bar->setSignalEmission(TabBar::SignalAlways);
}

void StdTransaction::setupForm(TransactionForm* form)
{
  Transaction::setupForm(form);

  TQTableItem* memo = form->item(3, ValueColumn1);
  memo->setSpan(3, 1);
}

bool StdTransaction::showRowInForm(int row) const
{
  return row == 0 ? m_showAccountRow : true;
}

void StdTransaction::setShowRowInForm(int row, bool show)
{
  if(row == 0)
    m_showAccountRow = show;
}

bool StdTransaction::formCellText(TQString& txt, int& align, int row, int col, TQPainter* /* painter */)
{
  // if(m_transaction != MyMoneyTransaction()) {
    switch(row) {
      case 0:
        switch(col) {
          case LabelColumn1:
            align |= TQt::AlignLeft;
            txt = i18n("Account");
            break;
        }
        break;

      case 1:
        switch(col) {
          case LabelColumn1:
            align |= TQt::AlignLeft;
            txt = m_payeeHeader;
            break;

          case ValueColumn1:
            align |= TQt::AlignLeft;
            txt = m_payee;
            break;

          case LabelColumn2:
            align |= TQt::AlignLeft;
            if(haveNumberField())
              txt = i18n("Number");
            break;

          case ValueColumn2:
            align |= TQt::AlignRight;
            if(haveNumberField())
              txt = m_split.number();
            break;
        }
        break;

      case 2:
        switch(col) {
          case LabelColumn1:
            align |= TQt::AlignLeft;
            txt = m_categoryHeader;
            break;

          case ValueColumn1:
            align |= TQt::AlignLeft;
            txt = m_category;
            if(m_transaction != MyMoneyTransaction()) {
              if(txt.isEmpty() && !m_split.value().isZero())
                txt = i18n("*** UNASSIGNED ***");
            }
            break;

          case LabelColumn2:
            align |= TQt::AlignLeft;
            txt = i18n("Date");
            break;

          case ValueColumn2:
            align |= TQt::AlignRight;
            if(m_transaction != MyMoneyTransaction())
              txt = TDEGlobal::locale()->formatDate(m_transaction.postDate(), true);
            break;
        }
        break;

      case 3:
        switch(col) {
          case LabelColumn1:
            align |= TQt::AlignLeft;
            txt = i18n("Memo");
            break;

          case ValueColumn1:
            align &= ~TQt::AlignVCenter;
            align |= TQt::AlignTop;
            align |= TQt::AlignLeft;
            if(m_transaction != MyMoneyTransaction())
              txt = m_split.memo().section('\n', 0, 2);
            break;

          case LabelColumn2:
            align |= TQt::AlignLeft;
            txt = i18n("Amount");
            break;

          case ValueColumn2:
            align |= TQt::AlignRight;
            if(m_transaction != MyMoneyTransaction()) {
              txt = (m_split.value(m_transaction.commodity(), m_splitCurrencyId).abs()).formatMoney(m_account.fraction());
            }
            break;
        }
        break;

      case 5:
        switch(col) {
          case LabelColumn2:
            align |= TQt::AlignLeft;
            txt = i18n("Status");
            break;

          case ValueColumn2:
            align |= TQt::AlignRight;
            txt = reconcileState();
            break;
        }
    }
  // }
  if(col == ValueColumn2 && row == 1) {
    return haveNumberField();
  }
  return (col == ValueColumn1 && row < 4) || (col == ValueColumn2 && row > 0 && row != 4);
}

void StdTransaction::registerCellText(TQString& txt, int& align, int row, int col, TQPainter* painter)
{
  switch(row) {
    case 0:
      switch(col) {
        case NumberColumn:
          align |= TQt::AlignLeft;
          if(haveNumberField())
            txt = m_split.number();
          break;

        case DateColumn:
          align |= TQt::AlignLeft;
          txt = TDEGlobal::locale()->formatDate(m_transaction.postDate(), true);
          break;

        case DetailColumn:
          align |= TQt::AlignLeft;
          txt = m_payee;
          if(txt.isEmpty() && m_rowsRegister < 3) {
            singleLineMemo(txt, m_split);
          }
          if(txt.isEmpty() && m_rowsRegister < 2) {
            if(m_account.accountType() != MyMoneyAccount::Income
            && m_account.accountType() != MyMoneyAccount::Expense) {
              txt = m_category;
              if(txt.isEmpty() && !m_split.value().isZero()) {
                txt = i18n("*** UNASSIGNED ***");
                if(painter)
                  painter->setPen(KMyMoneyGlobalSettings::listErronousTransactionColor());
              }
            }
          }
          break;

        case ReconcileFlagColumn:
          align |= TQt::AlignHCenter;
          txt = reconcileState(false);
          break;

        case PaymentColumn:
          align |= TQt::AlignRight;
          if(m_split.value().isNegative()) {
            txt = (-m_split.value(m_transaction.commodity(), m_splitCurrencyId)).formatMoney(m_account.fraction());
          }
          break;

        case DepositColumn:
          align |= TQt::AlignRight;
          if(!m_split.value().isNegative()) {
            txt = m_split.value(m_transaction.commodity(), m_splitCurrencyId).formatMoney(m_account.fraction());
          }
          break;

        case BalanceColumn:
          align |= TQt::AlignRight;
          if(m_showBalance)
            txt = m_balance.formatMoney(m_account.fraction());
          else
            txt = "----";
          break;

        case AccountColumn:
          // txt = m_objects->account(m_transaction.splits()[0].accountId()).name();
          txt = MyMoneyFile::instance()->account(m_split.accountId()).name();
          break;

        default:
          break;
      }
      break;

    case 1:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          txt = m_category;
          if(txt.isEmpty() && !m_split.value().isZero()) {
            txt = i18n("*** UNASSIGNED ***");
            if(painter)
              painter->setPen(KMyMoneyGlobalSettings::listErronousTransactionColor());
          }
          break;

        default:
          break;
      }
      break;

    case 2:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          singleLineMemo(txt, m_split);
          break;

        default:
          break;
      }
      break;
  }
}

int StdTransaction::registerColWidth(int col, const TQFontMetrics& cellFontMetrics)
{
  TQString txt;
  int firstRow = 0, lastRow = 0;

  int nw = 0;
  for(int i = firstRow; i <= lastRow; ++i) {
    int align;
    registerCellText(txt, align, i, col, 0);
    int w = cellFontMetrics.width(txt+"   ");
    if(w > nw)
      nw = w;
  }
  return nw;
}

void StdTransaction::arrangeWidgetsInForm(TQMap<TQString, TQWidget*>& editWidgets)
{
  if(!m_form || !m_parent)
    return;

  setupFormPalette(editWidgets);

  arrangeWidget(m_form, 0, ValueColumn1, editWidgets["account"]);
  arrangeWidget(m_form, 1, LabelColumn1, editWidgets["cashflow"]);
  arrangeWidget(m_form, 1, ValueColumn1, editWidgets["payee"]);
  arrangeWidget(m_form, 2, ValueColumn1, editWidgets["category"]->parentWidget());
  arrangeWidget(m_form, 3, ValueColumn1, editWidgets["memo"]);
  if(haveNumberField()) {
    arrangeWidget(m_form, 1, LabelColumn2, editWidgets["number-label"]);
    arrangeWidget(m_form, 1, ValueColumn2, editWidgets["number"]);
  }
  arrangeWidget(m_form, 2, LabelColumn2, editWidgets["date-label"]);
  arrangeWidget(m_form, 2, ValueColumn2, editWidgets["postdate"]);
  arrangeWidget(m_form, 3, ValueColumn2, editWidgets["amount"]);
  arrangeWidget(m_form, 5, ValueColumn2, editWidgets["status"]);
  arrangeWidget(m_form, 2, LabelColumn1, editWidgets["category-label"]);

  // get rid of the hints. we don't need them for the form
  TQMap<TQString, TQWidget*>::iterator it;
  for(it = editWidgets.begin(); it != editWidgets.end(); ++it) {
    KMyMoneyCombo* combo = dynamic_cast<KMyMoneyCombo*>(*it);
    kMyMoneyLineEdit* edit = dynamic_cast<kMyMoneyLineEdit*>(*it);
    KMyMoneyPayeeCombo* payee = dynamic_cast<KMyMoneyPayeeCombo*>(*it);
    if(combo)
      combo->setHint(TQString());
    if(edit)
      edit->setHint(TQString());
    if(payee)
      payee->setHint(TQString());
  }

  // drop the tabbar on top of the original
  KMyMoneyTransactionForm::TransactionForm* form = dynamic_cast<KMyMoneyTransactionForm::TransactionForm*>(m_form);
  TabBar* w = dynamic_cast<TabBar*>(editWidgets["tabbar"]);
  if(w) {
    w->reparent(form->tabBar(), TQPoint(0, 0), true);
  }
}

void StdTransaction::tabOrderInForm(TQWidgetList& tabOrderWidgets) const
{
  TQStringList taborder = TQStringList::split(",", KMyMoneyGlobalSettings::stdTransactionFormTabOrder());
  TQStringList::const_iterator it_s = taborder.constBegin();
  TQWidget* w;
  while(it_s != taborder.constEnd()) {
    if(*it_s == "account") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(0, ValueColumn1)));
    } else if(*it_s == "cashflow") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(1, LabelColumn1)));
    } else if(*it_s == "payee") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(1, ValueColumn1)));
    } else if(*it_s == "category") {
      // make sure to have the category field and the split button as seperate tab order widgets
      // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
      // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
      // go haywire when someone changes the KMyMoneyCategory object ...
      w = m_form->cellWidget(2, ValueColumn1);
      tabOrderWidgets.append(focusWidget(w));
      w = dynamic_cast<TQWidget*>(w->child("splitButton"));
      if(w)
        tabOrderWidgets.append(w);
    } else if(*it_s == "memo") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(3, ValueColumn1)));
    } else if(*it_s == "number") {
      if(haveNumberField()) {
        if((w = focusWidget(m_form->cellWidget(1, ValueColumn2))))
          tabOrderWidgets.append(w);
      }
    } else if(*it_s == "date") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(2, ValueColumn2)));
    } else if(*it_s == "amount") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(3, ValueColumn2)));
    } else if(*it_s == "state") {
      tabOrderWidgets.append(focusWidget(m_form->cellWidget(5, ValueColumn2)));
    }
    ++it_s;
  }
}

void StdTransaction::arrangeWidgetsInRegister(TQMap<TQString, TQWidget*>& editWidgets)
{
  if(!m_parent)
    return;

  setupRegisterPalette(editWidgets);

  if(haveNumberField())
    arrangeWidget(m_parent, m_startRow+0, NumberColumn, editWidgets["number"]);
  arrangeWidget(m_parent, m_startRow + 0, DateColumn, editWidgets["postdate"]);
  arrangeWidget(m_parent, m_startRow + 1, DateColumn, editWidgets["status"]);
  arrangeWidget(m_parent, m_startRow + 0, DetailColumn, editWidgets["payee"]);
  arrangeWidget(m_parent, m_startRow + 1, DetailColumn, editWidgets["category"]->parentWidget());
  arrangeWidget(m_parent, m_startRow + 2, DetailColumn, editWidgets["memo"]);
  arrangeWidget(m_parent, m_startRow + 0, PaymentColumn, editWidgets["payment"]);
  arrangeWidget(m_parent, m_startRow + 0, DepositColumn, editWidgets["deposit"]);

  // increase the height of the row containing the memo widget
  m_parent->setRowHeight(m_startRow+2, m_parent->rowHeightHint() * 3);
}

void StdTransaction::tabOrderInRegister(TQWidgetList& tabOrderWidgets) const
{
  TQStringList taborder = TQStringList::split(",", KMyMoneyGlobalSettings::stdTransactionRegisterTabOrder());
  TQStringList::const_iterator it_s = taborder.constBegin();
  TQWidget* w;
  while(it_s != taborder.constEnd()) {
    if(*it_s == "number") {
      if(haveNumberField()) {
        if((w = focusWidget(m_parent->cellWidget(m_startRow + 0, NumberColumn))))
          tabOrderWidgets.append(w);
      }
    } else if(*it_s == "date") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, DateColumn)));
    } else if(*it_s == "payee") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, DetailColumn)));
    } else if(*it_s == "category") {
      // make sure to have the category field and the split button as seperate tab order widgets
      // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
      // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
      // go haywire when someone changes the KMyMoneyCategory object ...
      w = m_parent->cellWidget(m_startRow + 1, DetailColumn);
      tabOrderWidgets.append(focusWidget(w));
      w = dynamic_cast<TQWidget*>(w->child("splitButton"));
      if(w)
        tabOrderWidgets.append(w);
    } else if(*it_s == "memo") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 2, DetailColumn)));
    } else if(*it_s == "payment") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, PaymentColumn)));
    } else if(*it_s == "deposit") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, DepositColumn)));
    } else if(*it_s == "state") {
      tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 1, DateColumn)));
    }
    ++it_s;
  }
}

int StdTransaction::numRowsRegister(bool expanded) const
{
  int numRows = 1;
  if(expanded) {
    numRows = 3;
    if(!m_inEdit) {
      if(m_payee.isEmpty()) {
        numRows--;
      }
      if(m_split.memo().isEmpty()) {
        numRows--;
      }
      // For income and expense accounts that only have
      // two splits we only show one line, because the
      // account name is already contained in the account column.
      if(m_account.accountType() == MyMoneyAccount::Income
      || m_account.accountType() == MyMoneyAccount::Expense) {
        if(numRows > 2 && m_transaction.splitCount() == 2)
          numRows = 1;
      }
    }
  }
  return numRows;
}

TransactionEditor* StdTransaction::createEditor(TransactionEditorContainer* regForm, const KMyMoneyRegister::SelectedTransactions& list, const TQDate& lastPostDate)
{
  m_inRegisterEdit = regForm == m_parent;
  return new StdTransactionEditor(regForm, this, list, lastPostDate);
}

InvestTransaction::InvestTransaction(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId) :
  Transaction(parent, transaction, split, uniqueId)
{
  // dissect the transaction into its type, splits, currency, security etc.
  InvestTransactionEditor::dissectTransaction(m_transaction, m_split,
                     m_assetAccountSplit,
                     m_feeSplits,
                     m_interestSplits,
                     m_security,
                     m_currency,
                     m_transactionType);

  TQValueList<MyMoneySplit>::ConstIterator it_s;
  for(it_s = m_feeSplits.begin(); it_s != m_feeSplits.end(); ++it_s) {
    m_feeAmount += (*it_s).value();
  }
  for(it_s = m_interestSplits.begin(); it_s != m_interestSplits.end(); ++it_s) {
    m_interestAmount += (*it_s).value();
  }

  // check the count of the fee splits and setup the text
  switch(m_feeSplits.count()) {
    case 0:
      break;

    case 1:
      m_feeCategory = MyMoneyFile::instance()->accountToCategory(m_feeSplits[0].accountId());
      break;

    default:
      m_feeCategory = i18n("Split transaction (category replacement)", "Split transaction");
      break;
  }

  // check the count of the interest splits and setup the text
  switch(m_interestSplits.count()) {
    case 0:
      break;

    case 1:
      m_interestCategory = MyMoneyFile::instance()->accountToCategory(m_interestSplits[0].accountId());
      break;

    default:
      m_interestCategory = i18n("Split transaction (category replacement)", "Split transaction");
      break;
  }

  m_rowsForm = 7;

  // setup initial size
  setNumRowsRegister(numRowsRegister(KMyMoneyGlobalSettings::showRegisterDetailed()));

  emit parent->itemAdded(this);
}

void InvestTransaction::setupForm(TransactionForm* form)
{
  Transaction::setupForm(form);

  TQTableItem* memo = form->item(5, 1);
  memo->setSpan(2, 1);
}

void InvestTransaction::activity(TQString& txt, MyMoneySplit::investTransactionTypeE type) const
{
  switch(type) {
    case MyMoneySplit::AddShares:
      txt = i18n("Add shares");
      break;
    case MyMoneySplit::RemoveShares:
      txt = i18n("Remove shares");
      break;
    case MyMoneySplit::BuyShares:
      txt = i18n("Buy shares");
      break;
    case MyMoneySplit::SellShares:
      txt = i18n("Sell shares");
      break;
    case MyMoneySplit::Dividend:
      txt = i18n("Dividend");
      break;
    case MyMoneySplit::ReinvestDividend:
      txt = i18n("Reinvest Dividend");
      break;
    case MyMoneySplit::Yield:
      txt = i18n("Yield");
      break;
    case MyMoneySplit::SplitShares:
      txt = i18n("Split shares");
      break;
    default:
      txt = i18n("Unknown");
      break;
  }
}

bool InvestTransaction::formCellText(TQString& txt, int& align, int row, int col, TQPainter* /* painter */)
{
  bool fieldEditable = false;

  switch(row) {
    case 0:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          txt = i18n("Activity");
          break;

        case ValueColumn1:
          align |= TQt::AlignLeft;
          fieldEditable = true;
          activity(txt, m_transactionType);
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          txt = i18n("Date");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          fieldEditable = true;
          if(m_transaction != MyMoneyTransaction())
            txt = TDEGlobal::locale()->formatDate(m_transaction.postDate(), true);
          break;
      }
      break;

    case 1:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          txt = i18n("Security");
          break;

        case ValueColumn1:
          align |= TQt::AlignLeft;
          fieldEditable = true;
          if(m_account.isInvest())
            txt = m_security.name();
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          if(haveShares()) {
            txt = i18n("Shares");
          } else if(haveSplitRatio()) {
            txt = i18n("Ratio");
          }
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          if((fieldEditable = haveShares()) == true) {
            txt = m_split.shares().abs().formatMoney("", MyMoneyMoney::denomToPrec(m_security.smallestAccountFraction()));
          } else if(haveSplitRatio()) {
            txt = TQString("1 / %1").arg(m_split.shares().abs().formatMoney("", -1));
          }
          break;
      }
      break;

    case 2:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          if(haveAssetAccount())
            txt = i18n("Account");
          break;

        case ValueColumn1:
          align |= TQt::AlignLeft;
          if((fieldEditable = haveAssetAccount()) == true) {
            txt = MyMoneyFile::instance()->accountToCategory(m_assetAccountSplit.accountId());
          }
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          if(havePrice())
            txt = i18n("Price/share");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          if((fieldEditable = havePrice()) == true && !m_split.shares().isZero()) {
            txt = m_split.price().formatMoney("", KMyMoneyGlobalSettings::pricePrecision());
          }
          break;
      }
      break;

    case 3:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          if(haveFees())
            txt = i18n("Fees");
          break;

        case ValueColumn1:
          align |= TQt::AlignLeft;
          if((fieldEditable = haveFees()) == true) {
            txt = m_feeCategory;
          }
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          if(haveFees() && !m_feeCategory.isEmpty())
            txt = i18n("Amount");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          if(haveFees()) {
            if((fieldEditable = !m_feeCategory.isEmpty()) == true) {
              txt = m_feeAmount.formatMoney(m_currency);
            }
          }
          break;
      }
      break;

    case 4:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          if(haveInterest())
            txt = i18n("Interest");
          break;

        case ValueColumn1:
          align |= TQt::AlignLeft;
          if((fieldEditable = haveInterest()) == true) {
            txt = m_interestCategory;
          }
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          if(haveInterest() && !m_interestCategory.isEmpty())
            txt = i18n("Amount");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          if(haveInterest()) {
            if((fieldEditable = !m_interestCategory.isEmpty()) == true) {
              txt = (-m_interestAmount).formatMoney(m_currency);
            }
          }
          break;
      }
      break;

    case 5:
      switch(col) {
        case LabelColumn1:
          align |= TQt::AlignLeft;
          txt = i18n("Memo");
          break;

        case ValueColumn1:
          align &= ~TQt::AlignVCenter;
          align |= TQt::AlignTop;
          align |= TQt::AlignLeft;
          fieldEditable = true;
          if(m_transaction != MyMoneyTransaction())
            txt = m_split.memo().section('\n', 0, 2);
          break;

        case LabelColumn2:
          align |= TQt::AlignLeft;
          if(haveAmount())
            txt = i18n("Total");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          if((fieldEditable = haveAmount()) == true) {
            txt = m_assetAccountSplit.value().abs().formatMoney(m_currency);
          }
      }
      break;

    case 6:
      switch(col) {
        case LabelColumn2:
          align |= TQt::AlignLeft;
          txt = i18n("Status");
          break;

        case ValueColumn2:
          align |= TQt::AlignRight;
          fieldEditable = true;
          txt = reconcileState();
          break;
      }
  }

  return fieldEditable;
}

void InvestTransaction::registerCellText(TQString& txt, int& align, int row, int col, TQPainter* /* painter */)
{
  switch(row) {
    case 0:
      switch(col) {
        case DateColumn:
          align |= TQt::AlignLeft;
          txt = TDEGlobal::locale()->formatDate(m_transaction.postDate(), true);
          break;

        case DetailColumn:
          align |= TQt::AlignLeft;
          activity(txt, m_transactionType);
          break;

        case SecurityColumn:
          align |= TQt::AlignLeft;
          if(m_account.isInvest())
            txt = m_security.name();
          break;

        case ReconcileFlagColumn:
          align |= TQt::AlignHCenter;
          txt = reconcileState(false);
          break;

        case QuantityColumn:
          align |= TQt::AlignRight;
          if(haveShares())
            txt = m_split.shares().abs().formatMoney("", MyMoneyMoney::denomToPrec(m_security.smallestAccountFraction()));
          else if(haveSplitRatio()) {
            txt = TQString("1 / %1").arg(m_split.shares().abs().formatMoney("", -1));
          }
          break;

        case PriceColumn:
          align |= TQt::AlignRight;
          if(havePrice() && !m_split.shares().isZero()) {
            txt = m_split.price().formatMoney(m_currency.tradingSymbol(), KMyMoneyGlobalSettings::pricePrecision());
          }
          break;

        case ValueColumn:
          align |= TQt::AlignRight;
          if(haveAmount()) {
            txt = m_assetAccountSplit.value().abs().formatMoney(m_currency);

          } else if(haveInterest()) {
            txt = (-m_interestAmount).formatMoney(m_currency);
          }
          break;

        case BalanceColumn:
          align |= TQt::AlignRight;
          if(m_showBalance)
            txt = m_balance.formatMoney("", MyMoneyMoney::denomToPrec(m_security.smallestAccountFraction()));
          else
            txt = "----";
          break;

        default:
          break;
      }
      break;

    case 1:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()) {
            txt = MyMoneyFile::instance()->accountToCategory(m_assetAccountSplit.accountId());
          } else if(haveInterest() && m_interestSplits.count()) {
            txt = m_interestCategory;
          } else if(haveFees() && m_feeSplits.count()) {
            txt = m_feeCategory;
          } else
            singleLineMemo(txt, m_split);
          break;

        case QuantityColumn:
          align |= TQt::AlignRight;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()) {
            // txt = m_interestAmount.abs().formatMoney(m_currency);
          } else if(haveInterest() && m_interestSplits.count()) {
            txt = (-m_interestAmount).formatMoney(m_currency);
          } else if(haveFees() && m_feeSplits.count()) {
            txt = m_feeAmount.formatMoney(m_currency);
          }
          break;

        default:
          break;
      }
      break;

    case 2:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()
          && haveInterest() && m_interestSplits.count()) {
            txt = m_interestCategory;
          } else if(haveFees() && m_feeSplits.count()) {
            txt = m_feeCategory;
          } else
            singleLineMemo(txt, m_split);
          break;

        case QuantityColumn:
          align |= TQt::AlignRight;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()
          && haveInterest() && m_interestSplits.count()) {
            txt = (-m_interestAmount).formatMoney(m_currency);
          } else if(haveFees() && m_feeSplits.count()) {
            txt = m_feeAmount.formatMoney(m_currency);
          }
          break;

        default:
          break;
      }
      break;

    case 3:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()
          && haveInterest() && m_interestSplits.count()
          && haveFees() && m_feeSplits.count()) {
            txt = m_feeCategory;
          } else
            singleLineMemo(txt, m_split);
          break;

        case QuantityColumn:
          align |= TQt::AlignRight;
          if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty()
          && haveInterest() && m_interestSplits.count()
          && haveFees() && m_feeSplits.count()) {
            txt = m_feeAmount.formatMoney(m_currency);
          }
          break;

        default:
          break;
      }
      break;

    case 4:
      switch(col) {
        case DetailColumn:
          align |= TQt::AlignLeft;
          singleLineMemo(txt, m_split);
          break;

        default:
          break;
      }
      break;
  }
}

int InvestTransaction::registerColWidth(int col, const TQFontMetrics& cellFontMetrics)
{
  TQString txt;
  MyMoneyMoney amount;
  int nw = 0;

  // for now just check all rows in that column
  for(int row = 0; row < m_rowsRegister; ++row) {
    int w;
    Transaction::registerCellText(txt, row, col);
    w = cellFontMetrics.width(txt+"  ");
    nw = TQMAX(nw, w);
  }

  // TODO the optimized way would be to base the size on the contents of a single row
  //      as we do it in StdTransaction::registerColWidth()
#if 0
  switch(col) {
    default:
      break;

    case PriceColumn:
      if(havePrice()) {
        txt = (m_split.value() / m_split.shares()).formatMoney("", KMyMoneyGlobalSettings::pricePrecision());
        nw = cellFontMetrics.width(txt+"  ");
      }
      break;
  }
#endif
  return nw;
}

void InvestTransaction::arrangeWidgetsInForm(TQMap<TQString, TQWidget*>& editWidgets)
{
  if(!m_form || !m_parent)
    return;

  setupFormPalette(editWidgets);

  // arrange the edit widgets
  arrangeWidget(m_form, 0, ValueColumn1, editWidgets["activity"]);
  arrangeWidget(m_form, 0, ValueColumn2, editWidgets["postdate"]);
  arrangeWidget(m_form, 1, ValueColumn1, editWidgets["security"]);
  arrangeWidget(m_form, 1, ValueColumn2, editWidgets["shares"]);
  arrangeWidget(m_form, 2, ValueColumn1, editWidgets["asset-account"]);
  arrangeWidget(m_form, 2, ValueColumn2, editWidgets["price"]);
  arrangeWidget(m_form, 3, ValueColumn1, editWidgets["fee-account"]->parentWidget());
  arrangeWidget(m_form, 3, ValueColumn2, editWidgets["fee-amount"]);
  arrangeWidget(m_form, 4, ValueColumn1, editWidgets["interest-account"]->parentWidget());
  arrangeWidget(m_form, 4, ValueColumn2, editWidgets["interest-amount"]);
  arrangeWidget(m_form, 5, ValueColumn1, editWidgets["memo"]);
  arrangeWidget(m_form, 5, ValueColumn2, editWidgets["total"]);
  arrangeWidget(m_form, 6, ValueColumn2, editWidgets["status"]);

  // arrange dynamic labels
  arrangeWidget(m_form, 1, LabelColumn2, editWidgets["shares-label"]);
  arrangeWidget(m_form, 2, LabelColumn1, editWidgets["asset-label"]);
  arrangeWidget(m_form, 2, LabelColumn2, editWidgets["price-label"]);
  arrangeWidget(m_form, 3, LabelColumn1, editWidgets["fee-label"]);
  arrangeWidget(m_form, 3, LabelColumn2, editWidgets["fee-amount-label"]);
  arrangeWidget(m_form, 4, LabelColumn1, editWidgets["interest-label"]);
  arrangeWidget(m_form, 4, LabelColumn2, editWidgets["interest-amount-label"]);
  arrangeWidget(m_form, 5, LabelColumn2, editWidgets["total-label"]);

  // get rid of the hints. we don't need them for the form
  TQMap<TQString, TQWidget*>::iterator it;
  for(it = editWidgets.begin(); it != editWidgets.end(); ++it) {
    KMyMoneyCombo* combo = dynamic_cast<KMyMoneyCombo*>(*it);
    kMyMoneyLineEdit* lineedit = dynamic_cast<kMyMoneyLineEdit*>(*it);
    kMyMoneyEdit* edit = dynamic_cast<kMyMoneyEdit*>(*it);
    KMyMoneyPayeeCombo* payee = dynamic_cast<KMyMoneyPayeeCombo*>(*it);
    if(combo)
      combo->setHint(TQString());
    if(edit)
      edit->setHint(TQString());
    if(lineedit)
      lineedit->setHint(TQString());
    if(payee)
      payee->setHint(TQString());
  }
}

void InvestTransaction::tabOrderInForm(TQWidgetList& tabOrderWidgets) const
{
  // activity
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(0, ValueColumn1)));

  // date
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(0, ValueColumn2)));

  // security
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(1, ValueColumn1)));

  // shares
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(1, ValueColumn2)));

  // account
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(2, ValueColumn1)));

  // price
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(2, ValueColumn2)));

  // make sure to have the fee category field and the split button as seperate tab order widgets
  // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
  // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
  // go haywire when someone changes the KMyMoneyCategory object ...
  TQWidget* w = m_form->cellWidget(3, ValueColumn1);
  tabOrderWidgets.append(focusWidget(w));
  w = dynamic_cast<TQWidget*>(w->child("splitButton"));
  if(w)
    tabOrderWidgets.append(w);

  // fee amount
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(3, ValueColumn2)));

  // the same applies for the interest categories
  w = m_form->cellWidget(4, ValueColumn1);
  tabOrderWidgets.append(focusWidget(w));
  w = dynamic_cast<TQWidget*>(w->child("splitButton"));
  if(w)
    tabOrderWidgets.append(w);

  // interest amount
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(4, ValueColumn2)));

  // memo
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(5, ValueColumn1)));

  // total
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(5, ValueColumn2)));

  // state
  tabOrderWidgets.append(focusWidget(m_form->cellWidget(6, ValueColumn2)));
}

void InvestTransaction::arrangeWidgetsInRegister(TQMap<TQString, TQWidget*>& editWidgets)
{
  if(!m_parent)
    return;

  setupRegisterPalette(editWidgets);

  arrangeWidget(m_parent, m_startRow + 0, DateColumn, editWidgets["postdate"]);
  arrangeWidget(m_parent, m_startRow + 0, SecurityColumn, editWidgets["security"]);
  arrangeWidget(m_parent, m_startRow + 0, DetailColumn, editWidgets["activity"]);
  arrangeWidget(m_parent, m_startRow + 1, DetailColumn, editWidgets["asset-account"]);
  arrangeWidget(m_parent, m_startRow + 2, DetailColumn, editWidgets["interest-account"]->parentWidget());
  arrangeWidget(m_parent, m_startRow + 3, DetailColumn, editWidgets["fee-account"]->parentWidget());
  arrangeWidget(m_parent, m_startRow + 4, DetailColumn, editWidgets["memo"]);
  arrangeWidget(m_parent, m_startRow + 0, QuantityColumn, editWidgets["shares"]);
  arrangeWidget(m_parent, m_startRow + 0, PriceColumn, editWidgets["price"]);
  arrangeWidget(m_parent, m_startRow + 2, QuantityColumn, editWidgets["interest-amount"]);
  arrangeWidget(m_parent, m_startRow + 3, QuantityColumn, editWidgets["fee-amount"]);
  arrangeWidget(m_parent, m_startRow + 0, ValueColumn, editWidgets["total"]);
  arrangeWidget(m_parent, m_startRow + 1, DateColumn, editWidgets["status"]);

  // increase the height of the row containing the memo widget
  m_parent->setRowHeight(m_startRow+4, m_parent->rowHeightHint() * 3);
}

void InvestTransaction::tabOrderInRegister(TQWidgetList& tabOrderWidgets) const
{
  TQWidget* w;

  // date
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, DateColumn)));
  // security
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, SecurityColumn)));
  // activity
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, DetailColumn)));
  // shares
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, QuantityColumn)));
  // price
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 0, PriceColumn)));
  // asset account
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 1, DetailColumn)));

  // make sure to have the category fields and the split button as seperate tab order widgets
  // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
  // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
  // go haywire when someone changes the KMyMoneyCategory object ...
  w = m_parent->cellWidget(m_startRow + 2, DetailColumn);    // interest account
  tabOrderWidgets.append(focusWidget(w));
  w = dynamic_cast<TQWidget*>(w->child("splitButton"));
  if(w)
    tabOrderWidgets.append(w);

  // interest amount
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 2, QuantityColumn)));

  w = m_parent->cellWidget(m_startRow + 3, DetailColumn);    // fee account
  tabOrderWidgets.append(focusWidget(w));
  w = dynamic_cast<TQWidget*>(w->child("splitButton"));
  if(w)
    tabOrderWidgets.append(w);

  // fee amount
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 3, QuantityColumn)));

  // memo
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 4, DetailColumn)));

  // status
  tabOrderWidgets.append(focusWidget(m_parent->cellWidget(m_startRow + 1, DateColumn)));
}

int InvestTransaction::numRowsRegister(bool expanded) const
{
  int numRows = 1;
  if(expanded) {
    if(!m_inEdit) {
      if(haveAssetAccount() && !m_assetAccountSplit.accountId().isEmpty())
        ++numRows;
      if(haveInterest() && m_interestSplits.count())
        ++numRows;
      if(haveFees() && m_feeSplits.count())
        ++numRows;
      if(!m_split.memo().isEmpty())
        ++numRows;
    } else
      numRows = 5;
  }
  return numRows;
}

bool InvestTransaction::haveShares(void) const
{
  bool rc = true;
  switch(m_transactionType) {
    case MyMoneySplit::Dividend:
    case MyMoneySplit::Yield:
    case MyMoneySplit::SplitShares:
      rc = false;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::haveFees(void) const
{
  bool rc = true;
  switch(m_transactionType) {
    case MyMoneySplit::AddShares:
    case MyMoneySplit::RemoveShares:
    case MyMoneySplit::SplitShares:
      rc = false;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::haveInterest(void) const
{
  bool rc = false;
  switch(m_transactionType) {
    case MyMoneySplit::BuyShares:
    case MyMoneySplit::SellShares:
    case MyMoneySplit::Dividend:
    case MyMoneySplit::ReinvestDividend:
    case MyMoneySplit::Yield:
      rc = true;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::havePrice(void) const
{
  bool rc = false;
  switch(m_transactionType) {
    case MyMoneySplit::BuyShares:
    case MyMoneySplit::SellShares:
    case MyMoneySplit::ReinvestDividend:
      rc = true;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::haveAmount(void) const
{
  bool rc = false;
  switch(m_transactionType) {
    case MyMoneySplit::BuyShares:
    case MyMoneySplit::SellShares:
    case MyMoneySplit::Dividend:
    case MyMoneySplit::Yield:
      rc = true;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::haveAssetAccount(void) const
{
  bool rc = true;
  switch(m_transactionType) {
    case MyMoneySplit::AddShares:
    case MyMoneySplit::RemoveShares:
    case MyMoneySplit::SplitShares:
    case MyMoneySplit::ReinvestDividend:
      rc = false;
      break;

    default:
      break;
  }
  return rc;
}

bool InvestTransaction::haveSplitRatio(void) const
{
  return m_transactionType == MyMoneySplit::SplitShares;
}

void InvestTransaction::splits(MyMoneySplit& assetAccountSplit, TQValueList<MyMoneySplit>& interestSplits, TQValueList<MyMoneySplit>& feeSplits) const
{
  assetAccountSplit = m_assetAccountSplit;
  interestSplits = m_interestSplits;
  feeSplits = m_feeSplits;
}

TransactionEditor* InvestTransaction::createEditor(TransactionEditorContainer* regForm, const KMyMoneyRegister::SelectedTransactions& list, const TQDate& lastPostDate)
{
  m_inRegisterEdit = regForm == m_parent;
  return new InvestTransactionEditor(regForm, this, list, lastPostDate);
}

