/***************************************************************************
 *   Copyright (C) 2008 by Hanna K.                                        *
 *   hanna_k@fmgirl.com                                                    *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

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

#include "transactioneditwidget.h"
#include "budget.h"
#include "recurrence.h"
#include "eqonomizevalueedit.h"

#include <math.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kdeversion.h>
#include <kstatusbar.h>
#include <kio/netaccess.h>
#include <kfiledialog.h>
#include <kconfig.h>
#include <kurl.h>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QVBoxLayout>
#include <kmessagebox.h>
#include <qlayout.h>
#include <klineedit.h>
#include <kcombobox.h>
#include "kdateedit.h"
#include <qlabel.h>
#include <KDialogButtonBox>
#include <kstdguiitem.h>
#include <kstdaccel.h>
#include <kaction.h>
#include <kstandardaction.h>
#include <qobject.h>
#include <qpushbutton.h>
#include <ktemporaryfile.h>
#include <qlabel.h>
#include <kseparator.h>
#include <qcheckbox.h>
#include <kpagewidget.h>
#include <qradiobutton.h>
#include <kpushbutton.h>
#include <ktextedit.h>
#include <khbox.h>

extern double monthsBetweenDates(const QDate &date1, const QDate &d2);

#define TEROWCOL(row, col)	row % rows, ((row / rows) * 2) + col

TransactionEditWidget::TransactionEditWidget(bool auto_edit, bool extra_parameters, int transaction_type, bool split, bool transfer_to, Security *sec, SecurityValueDefineType security_value_type, bool select_security, Budget *budg, QWidget *parent) : QWidget(parent), transtype(transaction_type), budget(budg), security(sec), b_autoedit(auto_edit), b_extra(extra_parameters) {
	value_set = false; shares_set = false; sharevalue_set = false;
	b_sec = (transtype == TRANSACTION_TYPE_SECURITY_BUY || transtype == TRANSACTION_TYPE_SECURITY_SELL);
	QVBoxLayout *editVLayout = new QVBoxLayout(this);
	editVLayout->setContentsMargins(0, 0, 0, 0);
	int cols = 1;
	if(auto_edit) cols = 2;
	int rows = 6;
	if(b_sec && security_value_type == SECURITY_ALL_VALUES) rows = 7;
	else if(b_extra && !security && !select_security && (transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME)) rows = 8;
	if(rows % cols > 0) rows += rows / cols + 1;
	else rows = rows / cols;	
	QGridLayout *editLayout = new QGridLayout();
	editVLayout->addLayout(editLayout);
	dateEdit = NULL;
	sharesEdit = NULL;
	quotationEdit = NULL;
	valueEdit = NULL;
	descriptionEdit = NULL;
	payeeEdit = NULL;
	quantityEdit = NULL;
	toCombo = NULL;
	fromCombo = NULL;
	securityCombo = NULL;
	int i = 0;
	if(b_sec) {
		int decimals = 4;		
		editLayout->addWidget(new QLabel(i18n("Security:"), this), TEROWCOL(i, 0));
		if(select_security) {
			securityCombo = new KComboBox(this);
			securityCombo->setEditable(false);
			Security *c_sec = budget->securities.first();
			int i2 = 0;
			while(c_sec) {
				securityCombo->addItem(c_sec->name());
				if(c_sec == security) securityCombo->setCurrentIndex(i2);
				c_sec = budget->securities.next();
				i2++;
			}
			editLayout->addWidget(securityCombo, TEROWCOL(i, 1));
			if(!security) security = selectedSecurity();
		} else {
			editLayout->addWidget(new QLabel(security->name(), this), TEROWCOL(i, 1));
		}		
		if(security) decimals = security->decimals();
		i++;
		if(security_value_type != SECURITY_SHARES_AND_QUOTATION) {
			if(transtype == TRANSACTION_TYPE_SECURITY_BUY) editLayout->addWidget(new QLabel(i18n("Cost:"), this), TEROWCOL(i, 0));
			else editLayout->addWidget(new QLabel(i18n("Income:"), this), TEROWCOL(i, 0));
			valueEdit = new EqonomizeValueEdit(false, this);
			editLayout->addWidget(valueEdit, TEROWCOL(i, 1));
			i++;
		}
		if(security_value_type != SECURITY_VALUE_AND_QUOTATION) {
			if(transtype == TRANSACTION_TYPE_SECURITY_BUY) {
				editLayout->addWidget(new QLabel(i18n("Shares bought:"), this), TEROWCOL(i, 0));
				sharesEdit = new EqonomizeValueEdit(0.0, decimals, false, false, this);
				editLayout->addWidget(sharesEdit, TEROWCOL(i, 1));
				i++;
			} else {
				editLayout->addWidget(new QLabel(i18n("Shares sold:"), this), TEROWCOL(i, 0));
				QHBoxLayout *sharesLayout = new QHBoxLayout();
				sharesEdit = new EqonomizeValueEdit(0.0, decimals, false, false, this);
				sharesEdit->setSizePolicy(QSizePolicy::Expanding, sharesEdit->sizePolicy().verticalPolicy());
				sharesLayout->addWidget(sharesEdit);
				maxSharesButton = new QPushButton(i18n("All"), this);
				maxSharesButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
				sharesLayout->addWidget(maxSharesButton);
				editLayout->addLayout(sharesLayout, TEROWCOL(i, 1));
				i++;
			}
		}
		if(security_value_type != SECURITY_VALUE_AND_SHARES) {
			editLayout->addWidget(new QLabel(i18n("Price per share:"), this), TEROWCOL(i, 0));
			quotationEdit = new EqonomizeValueEdit(false, this);			
			editLayout->addWidget(quotationEdit, TEROWCOL(i, 1));
			i++;
		}
		if(!split) {
			editLayout->addWidget(new QLabel(i18n("Date:"), this), TEROWCOL(i, 0));
			dateEdit = new KDateEdit(this);
			dateEdit->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
			editLayout->addWidget(dateEdit, TEROWCOL(i, 1));
		}
		i++;
	} else {
		if(transtype == TRANSACTION_TYPE_INCOME && (security || select_security)) {
			editLayout->addWidget(new QLabel(i18n("Security:"), this), TEROWCOL(i, 0));
			if(select_security) {
				securityCombo = new KComboBox(this);
				securityCombo->setEditable(false);
				Security *c_sec = budget->securities.first();
				int i2 = 0;
				while(c_sec) {
					securityCombo->addItem(c_sec->name());
					if(c_sec == security) securityCombo->setCurrentIndex(i2);
					c_sec = budget->securities.next();
					i2++;
				}
				editLayout->addWidget(securityCombo, TEROWCOL(i, 1));
				if(!security) security = selectedSecurity();
			} else {
				editLayout->addWidget(new QLabel(security->name(), this), TEROWCOL(i, 1));
			}
		} else {
			editLayout->addWidget(new QLabel(i18n("Description:"), this), TEROWCOL(i, 0));
			descriptionEdit = new KLineEdit(this);
			descriptionEdit->setCompletionMode(KGlobalSettings::CompletionPopup);
			editLayout->addWidget(descriptionEdit, TEROWCOL(i, 1));
		}		
		i++;
		if(transtype == TRANSACTION_TYPE_TRANSFER) {
			editLayout->addWidget(new QLabel(i18n("Amount:"), this), TEROWCOL(i, 0));
		} else if(transtype == TRANSACTION_TYPE_INCOME) {
			editLayout->addWidget(new QLabel(i18n("Income:"), this), TEROWCOL(i, 0));
		} else {
			editLayout->addWidget(new QLabel(i18n("Cost:"), this), TEROWCOL(i, 0));
			
		}
		valueEdit = new EqonomizeValueEdit(true, this);
		editLayout->addWidget(valueEdit, TEROWCOL(i, 1));
		i++;
		if(b_extra && !select_security && !security && (transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME)) {
			editLayout->addWidget(new QLabel(i18n("Quantity:"), this), TEROWCOL(i, 0));
			quantityEdit = new EqonomizeValueEdit(INT_MIN / 100 + 1.0, INT_MAX / 100 - 1.0, 1.0, 1.0, 2, false, this);
			editLayout->addWidget(quantityEdit, TEROWCOL(i, 1));
			i++;
		}
		if(!split) {
			editLayout->addWidget(new QLabel(i18n("Date:"), this), TEROWCOL(i, 0));
			dateEdit = new KDateEdit(this);
			dateEdit->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
			editLayout->addWidget(dateEdit, TEROWCOL(i, 1));
			i++;
		}
	}
	switch(transtype) {
		case TRANSACTION_TYPE_TRANSFER: {
			if(!split || transfer_to) {
				editLayout->addWidget(new QLabel(i18n("From:"), this), TEROWCOL(i, 0));
				fromCombo = new KComboBox(this);
				fromCombo->setEditable(false);
				editLayout->addWidget(fromCombo, TEROWCOL(i, 1));
				i++;
			}
			if(!split || !transfer_to) {
				editLayout->addWidget(new QLabel(i18n("To:"), this), TEROWCOL(i, 0));
				toCombo = new KComboBox(this);
				toCombo->setEditable(false);
				editLayout->addWidget(toCombo, TEROWCOL(i, 1));
				i++;
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			editLayout->addWidget(new QLabel(i18n("Category:"), this), TEROWCOL(i, 0));
			fromCombo = new KComboBox(this);
			fromCombo->setEditable(false);
			editLayout->addWidget(fromCombo, TEROWCOL(i, 1));
			i++;
			if(!split) {
				editLayout->addWidget(new QLabel(i18n("To account:"), this), TEROWCOL(i, 0));
				toCombo = new KComboBox(this);
				toCombo->setEditable(false);
				editLayout->addWidget(toCombo, TEROWCOL(i, 1));
				i++;
			}
			if(b_extra && !select_security && !security) {
				editLayout->addWidget(new QLabel(i18n("Payer:"), this), TEROWCOL(i, 0));
				payeeEdit = new KLineEdit(this);
				payeeEdit->setCompletionMode(KGlobalSettings::CompletionPopup);
				editLayout->addWidget(payeeEdit, TEROWCOL(i, 1));
				i++;
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {
			if(!split) {
				editLayout->addWidget(new QLabel(i18n("From account:"), this), TEROWCOL(i, 0));
				fromCombo = new KComboBox(this);
				fromCombo->setEditable(false);
				editLayout->addWidget(fromCombo, TEROWCOL(i, 1));
				i++;
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			if(!split) {
				editLayout->addWidget(new QLabel(i18n("To account:"), this), TEROWCOL(i, 0));
				toCombo = new KComboBox(this);
				toCombo->setEditable(false);
				editLayout->addWidget(toCombo, TEROWCOL(i, 1));
				i++;
			}
			break;
		}
		default: {
			editLayout->addWidget(new QLabel(i18n("Category:"), this), TEROWCOL(i, 0));
			toCombo = new KComboBox(this);
			toCombo->setEditable(false);
			editLayout->addWidget(toCombo, TEROWCOL(i, 1));
			i++;
			if(!split) {
				editLayout->addWidget(new QLabel(i18n("From account:"), this), TEROWCOL(i, 0));
				fromCombo = new KComboBox(this);
				fromCombo->setEditable(false);
				editLayout->addWidget(fromCombo, TEROWCOL(i, 1));
				i++;
			}
			if(b_extra) {
				editLayout->addWidget(new QLabel(i18n("Payee:"), this), TEROWCOL(i, 0));
				payeeEdit = new KLineEdit(this);
				payeeEdit->setCompletionMode(KGlobalSettings::CompletionPopup);
				editLayout->addWidget(payeeEdit, TEROWCOL(i, 1));
				i++;
			}
		}
	}
	editLayout->addWidget(new QLabel(i18n("Comments:"), this), TEROWCOL(i, 0));
	commentsEdit = new KLineEdit(this);
	editLayout->addWidget(commentsEdit, TEROWCOL(i, 1));
	i++;
	bottom_widget = new KHBox(this);
	editVLayout->addWidget(bottom_widget);
	editVLayout->addStretch(1);

	description_changed = false;
	if(descriptionEdit) descriptionEdit->completionObject()->setIgnoreCase(true);
	if(payeeEdit) payeeEdit->completionObject()->setIgnoreCase(true);

	if(dateEdit) connect(dateEdit, SIGNAL(dateChanged(const QDate&)), this, SIGNAL(dateChanged(const QDate&)));
	if(b_sec) {
		switch(security_value_type) {
			case SECURITY_ALL_VALUES: {
				connect(valueEdit, SIGNAL(returnPressed()), sharesEdit, SLOT(setFocus()));
				connect(valueEdit, SIGNAL(returnPressed()), sharesEdit, SLOT(selectAll()));
				connect(sharesEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(setFocus()));
				connect(sharesEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(selectAll()));
				if(dateEdit) {
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
				}
				if(transtype == TRANSACTION_TYPE_SECURITY_SELL) connect(maxSharesButton, SIGNAL(clicked()), this, SLOT(maxShares()));
				break;
			}
			case SECURITY_SHARES_AND_QUOTATION: {
				connect(sharesEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(setFocus()));
				connect(sharesEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(selectAll()));
				if(dateEdit) {
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
				}
				if(transtype == TRANSACTION_TYPE_SECURITY_SELL) connect(maxSharesButton, SIGNAL(clicked()), this, SLOT(maxShares()));
				break;
			}
			case SECURITY_VALUE_AND_SHARES: {
				connect(valueEdit, SIGNAL(returnPressed()), sharesEdit, SLOT(setFocus()));
				connect(valueEdit, SIGNAL(returnPressed()), sharesEdit, SLOT(selectAll()));
				if(dateEdit) {
					connect(sharesEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
					connect(sharesEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
				}
				if(transtype == TRANSACTION_TYPE_SECURITY_SELL) connect(maxSharesButton, SIGNAL(clicked()), this, SLOT(maxShares()));
				break;
			}
			case SECURITY_VALUE_AND_QUOTATION: {
				connect(valueEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(setFocus()));
				connect(valueEdit, SIGNAL(returnPressed()), quotationEdit, SLOT(selectAll()));
				if(dateEdit) {
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
					connect(quotationEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
				}
				break;
			}
		}
		if(valueEdit) connect(valueEdit, SIGNAL(valueChanged(double)), this, SLOT(valueChanged(double)));
		if(sharesEdit) connect(sharesEdit, SIGNAL(valueChanged(double)), this, SLOT(sharesChanged(double)));
		if(quotationEdit) connect(quotationEdit, SIGNAL(valueChanged(double)), this, SLOT(quotationChanged(double)));
	} else {
		if(quantityEdit) {
			connect(valueEdit, SIGNAL(returnPressed()), quantityEdit, SLOT(setFocus()));
			connect(valueEdit, SIGNAL(returnPressed()), quantityEdit, SLOT(selectAll()));
			if(dateEdit) {
				connect(quantityEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
				connect(quantityEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
			}
		} else  {
			if(dateEdit) {
				connect(valueEdit, SIGNAL(returnPressed()), dateEdit, SLOT(setFocus()));
				connect(valueEdit, SIGNAL(returnPressed()), dateEdit->lineEdit(), SLOT(selectAll()));
			}
		}
		if(descriptionEdit) {
			connect(descriptionEdit, SIGNAL(returnPressed()), valueEdit, SLOT(setFocus()));
			connect(descriptionEdit, SIGNAL(returnPressed()), valueEdit, SLOT(selectAll()));
			connect(descriptionEdit, SIGNAL(lostFocus()), this, SLOT(setDefaultValue()));
			connect(descriptionEdit, SIGNAL(textChanged(const QString&)), this, SLOT(descriptionChanged(const QString&)));
		}		
	}
	if(b_autoedit && dateEdit) connect(dateEdit->lineEdit(), SIGNAL(returnPressed()), this, SIGNAL(addmodify()));
	if(payeeEdit) connect(payeeEdit, SIGNAL(returnPressed()), commentsEdit, SLOT(setFocus()));
	if(b_autoedit) connect(commentsEdit, SIGNAL(returnPressed()), this, SIGNAL(addmodify()));
	if(securityCombo) connect(securityCombo, SIGNAL(activated(int)), this, SLOT(securityChanged()));
}
void TransactionEditWidget::currentDateChanged(const QDate &olddate, const QDate &newdate) {
	if(dateEdit && olddate == dateEdit->date() && valueEdit && valueEdit->value() == 0.0 && descriptionEdit && descriptionEdit->text().isEmpty()) {
		dateEdit->setDate(newdate);
	}
}
void TransactionEditWidget::securityChanged() {
	security = selectedSecurity();
	if(security) {
		if(sharesEdit) sharesEdit->setPrecision(security->decimals());
		if(sharesEdit && security && shares_date.isValid()) sharesEdit->setMaxValue(security->shares(shares_date));
	}
}
void TransactionEditWidget::valueChanged(double value) {
	if(!quotationEdit || !sharesEdit || !valueEdit) return;
	value_set = true;
	if(shares_set && !sharevalue_set) {
		quotationEdit->blockSignals(true);
		quotationEdit->setValue(value / sharesEdit->value());
		quotationEdit->blockSignals(false);
	} else if(!shares_set && sharevalue_set) {
		sharesEdit->blockSignals(true);
		sharesEdit->setValue(value / quotationEdit->value());
		sharesEdit->blockSignals(false);
	}
}
void TransactionEditWidget::sharesChanged(double value) {
	if(!quotationEdit || !sharesEdit || !valueEdit) return;
	shares_set = true;
	if(value_set && !sharevalue_set) {
		quotationEdit->blockSignals(true);
		quotationEdit->setValue(valueEdit->value() / value);
		quotationEdit->blockSignals(false);
	} else if(!value_set && sharevalue_set) {
		valueEdit->blockSignals(true);
		valueEdit->setValue(value * quotationEdit->value());
		valueEdit->blockSignals(false);
	}
}
void TransactionEditWidget::quotationChanged(double value) {
	if(!quotationEdit || !sharesEdit || !valueEdit) return;
	sharevalue_set = true;
	if(value_set && !shares_set) {
		sharesEdit->blockSignals(true);
		sharesEdit->setValue(valueEdit->value() / value);
		sharesEdit->blockSignals(false);
	} else if(!value_set && shares_set) {
		valueEdit->blockSignals(true);
		valueEdit->setValue(value * sharesEdit->value());
		valueEdit->blockSignals(false);
	}
}
void TransactionEditWidget::setMaxShares(double max) {
	if(sharesEdit) sharesEdit->setMaxValue(max);
}
void TransactionEditWidget::setMaxSharesDate(QDate quotation_date) {
	shares_date = quotation_date;
	if(sharesEdit && security && shares_date.isValid()) sharesEdit->setMaxValue(security->shares(shares_date));
}
void TransactionEditWidget::maxShares() {
	if(selectedSecurity() && sharesEdit) sharesEdit->setValue(selectedSecurity()->shares(dateEdit->date()));
}
QWidget *TransactionEditWidget::bottomWidget() {
	return bottom_widget;
}
void TransactionEditWidget::focusDescription() {
	if(!descriptionEdit) {
		if(valueEdit) valueEdit->setFocus();
		else sharesEdit->setFocus();
	} else {
		descriptionEdit->setFocus();
	}
}
QDate TransactionEditWidget::date() {
	if(!dateEdit) return QDate();
	return dateEdit->date();
}
void TransactionEditWidget::descriptionChanged(const QString&) {
	description_changed = true;
}
void TransactionEditWidget::setDefaultValue() {
	if(descriptionEdit && description_changed && !descriptionEdit->text().isEmpty() && valueEdit && valueEdit->value() == 0.0) {
		Transaction *trans = default_values[descriptionEdit->text()];
		if(trans) {
			valueEdit->setValue(trans->value());
			if(toCombo) {
				for(QVector<Account*>::size_type i = 0; i < tos.size(); i++) {
					if(trans->toAccount() == tos[i]) {
						toCombo->setCurrentIndex(i);
						break;
					}
				}
			}
			if(fromCombo) {
				for(QVector<Account*>::size_type i = 0; i < froms.size(); i++) {
					if(trans->fromAccount() == froms[i]) {
						fromCombo->setCurrentIndex(i);
						break;
					}
				}
			}
			if(quantityEdit) {
				if(trans->quantity() <= 0.0) quantityEdit->setValue(1.0);
				else quantityEdit->setValue(trans->quantity());
			}
			if(payeeEdit && trans->type() == TRANSACTION_TYPE_EXPENSE) payeeEdit->setText(((Expense*) trans)->payee());
			if(payeeEdit && trans->type() == TRANSACTION_TYPE_INCOME) payeeEdit->setText(((Income*) trans)->payer());
		}
	}
}
void TransactionEditWidget::updateFromAccounts(Account *exclude_account) {
	if(!fromCombo) return;
	fromCombo->clear();
	froms.clear();
	Account *account;
	switch(transtype) {
		case TRANSACTION_TYPE_TRANSFER: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && (b_autoedit || ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES)) {
					fromCombo->addItem(account->name());
					froms.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			for(QVector<Account*>::size_type i = 0; i < froms.size(); i++) {
				if(froms[i] != budget->balancingAccount && ((AssetsAccount*) froms[i])->accountType() != ASSETS_TYPE_SECURITIES) {
					fromCombo->setCurrentIndex((int) i);
					break;
				}
			}
			break;
		}
		case TRANSACTION_TYPE_EXPENSE: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && account != budget->balancingAccount && ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES) {
					fromCombo->addItem(account->name());
					froms.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			for(QVector<Account*>::size_type i = 0; i < froms.size(); i++) {
				if(froms[i] != budget->balancingAccount && ((AssetsAccount*) froms[i])->accountType() != ASSETS_TYPE_SECURITIES) {
					fromCombo->setCurrentIndex((int) i);
					break;
				}
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			account = budget->incomesAccounts.first();
			while(account) {
				if(account != exclude_account) {
					fromCombo->addItem(account->name());
					froms.push_back(account);
				}
				account = budget->incomesAccounts.next();
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && account != budget->balancingAccount && ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES) {
					fromCombo->addItem(account->name());
					froms.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			account = budget->incomesAccounts.first();
			while(account) {
				if(account != exclude_account) {
					fromCombo->addItem(account->name());
					froms.push_back(account);
					account = budget->incomesAccounts.next();
				}
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			break;
		}
	}
}
void TransactionEditWidget::updateToAccounts(Account *exclude_account) {
	if(!toCombo) return;
	toCombo->clear();
	tos.clear();
	Account *account;
	switch(transtype) {
		case TRANSACTION_TYPE_TRANSFER: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && (b_autoedit || ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES)) {
					toCombo->addItem(account->name());
					tos.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			for(QVector<Account*>::size_type i = 0; i < tos.size(); i++) {
				if(tos[i] != budget->balancingAccount && ((AssetsAccount*) tos[i])->accountType() != ASSETS_TYPE_SECURITIES) {
					toCombo->setCurrentIndex((int) i);
					break;
				}
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && account != budget->balancingAccount && (b_autoedit || ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES)) {
					toCombo->addItem(account->name());
					tos.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			for(QVector<Account*>::size_type i = 0; i < tos.size(); i++) {
				if(tos[i] != budget->balancingAccount && ((AssetsAccount*) tos[i])->accountType() != ASSETS_TYPE_SECURITIES) {
					toCombo->setCurrentIndex((int) i);
					break;
				}
			}
			break;
		}
		case TRANSACTION_TYPE_EXPENSE: {
			account = budget->expensesAccounts.first();
			while(account) {
				if(account != exclude_account) {
					toCombo->addItem(account->name());
					tos.push_back(account);
				}
				account = budget->expensesAccounts.next();
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {
			break;
		}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			account = budget->assetsAccounts.first();
			while(account) {
				if(account != exclude_account && account != budget->balancingAccount && ((AssetsAccount*) account)->accountType() != ASSETS_TYPE_SECURITIES) {
					toCombo->addItem(account->name());
					tos.push_back(account);
				}
				account = budget->assetsAccounts.next();
			}
			break;
		}
	}
}
void TransactionEditWidget::updateAccounts(Account *exclude_account) {
	updateFromAccounts(exclude_account);
	updateToAccounts(exclude_account);
}
void TransactionEditWidget::transactionAdded(Transaction *trans) {
	if(descriptionEdit && trans->type() == transtype && (transtype != TRANSACTION_TYPE_INCOME || !((Income*) trans)->security())) {
		if(!trans->description().isEmpty()) {
			descriptionEdit->completionObject()->addItem(trans->description());
			default_values[trans->description()] = trans;
		}
		if(payeeEdit && transtype == TRANSACTION_TYPE_EXPENSE && !((Expense*) trans)->payee().isEmpty()) payeeEdit->completionObject()->addItem(((Expense*) trans)->payee());
		if(payeeEdit && transtype == TRANSACTION_TYPE_INCOME && !((Income*) trans)->security() && !((Income*) trans)->payer().isEmpty()) payeeEdit->completionObject()->addItem(((Income*) trans)->payer());
	}
}
void TransactionEditWidget::transactionModified(Transaction *trans) {
	if(descriptionEdit && trans->type() == transtype && (transtype != TRANSACTION_TYPE_INCOME || !((Income*) trans)->security())) {
		if(!trans->description().isEmpty()) {
			descriptionEdit->completionObject()->addItem(trans->description());
			default_values[trans->description()] = trans;
		}
		if(payeeEdit && transtype == TRANSACTION_TYPE_EXPENSE && !((Expense*) trans)->payee().isEmpty()) payeeEdit->completionObject()->addItem(((Expense*) trans)->payee());
		if(payeeEdit && transtype == TRANSACTION_TYPE_INCOME && !((Income*) trans)->security() && !((Income*) trans)->payer().isEmpty()) payeeEdit->completionObject()->addItem(((Income*) trans)->payer());
	}
}
bool TransactionEditWidget::checkAccounts() {
	switch(transtype) {
		case TRANSACTION_TYPE_TRANSFER: {
			if(fromCombo && fromCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account available."));
				return false;
			}
			if(toCombo && toCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account available."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			if(fromCombo && fromCombo->count() == 0) {
				KMessageBox::error(this, i18n("No income category available."));
				return false;
			}
			if(toCombo && toCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account available."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {
			if(fromCombo && fromCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account or income category available."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			if(toCombo && toCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account available."));
				return false;
			}
			break;
		}
		default: {
			if(toCombo && toCombo->count() == 0) {
				KMessageBox::error(this, i18n("No expense category available."));
				return false;
			}
			if(fromCombo && fromCombo->count() == 0) {
				KMessageBox::error(this, i18n("No suitable account available."));
				return false;
			}
			break;
		}
	}
	if(securityCombo && securityCombo->count() == 0) {
		KMessageBox::error(this, i18n("No security available."));
		return false;
	}
	return true;
}
bool TransactionEditWidget::validValues(bool) {
	if(dateEdit && !dateEdit->date().isValid()) {
		KMessageBox::error(this, i18n("Invalid date."));
		dateEdit->setFocus();
		dateEdit->lineEdit()->selectAll();
		return false;
	}
	if(!checkAccounts()) return false;
	if(toCombo && fromCombo && tos[toCombo->currentIndex()] == froms[fromCombo->currentIndex()]) {
		KMessageBox::error(this, i18n("Cannot transfer money to and from the same account."));
		return false;
	}
	switch(transtype) {
		case TRANSACTION_TYPE_TRANSFER: {
			if((toCombo && tos[toCombo->currentIndex()]->type() == ACCOUNT_TYPE_ASSETS && ((AssetsAccount*) tos[toCombo->currentIndex()])->accountType() == ASSETS_TYPE_SECURITIES) || (fromCombo && froms[fromCombo->currentIndex()]->type() == ACCOUNT_TYPE_ASSETS && ((AssetsAccount*) froms[fromCombo->currentIndex()])->accountType() == ASSETS_TYPE_SECURITIES)) {
				KMessageBox::error(this, i18n("Cannot create a regular transfer to/from a securities account."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			if(toCombo && tos[toCombo->currentIndex()]->type() == ACCOUNT_TYPE_ASSETS && ((AssetsAccount*) tos[toCombo->currentIndex()])->accountType() == ASSETS_TYPE_SECURITIES) {
				KMessageBox::error(this, i18n("Cannot create a regular income to a securities account."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			if(sharesEdit && sharesEdit->value() == 0.0) {
				KMessageBox::error(this, i18n("Zero shares not allowed."));
				return false;
			}
			if(valueEdit && valueEdit->value() == 0.0) {
				KMessageBox::error(this, i18n("Zero value not allowed."));
				return false;
			}
			if(quotationEdit && quotationEdit->value() == 0.0) {
				KMessageBox::error(this, i18n("Zero price per share not allowed."));
				return false;
			}
			/*if(ask_questions && sharesEdit && selectedSecurity() && sharesEdit->value() > selectedSecurity()->shares(dateEdit->date())) {
				if(KMessageBox::warningContinueCancel(this, i18n("Number of sold shares are greater than available shares at selected date. Do you want to create the transaction nevertheless?")) == KMessageBox::Cancel) {
					return false;
				}
			}*/
			break;
		}
		default: {			
			if(fromCombo && froms[fromCombo->currentIndex()]->type() == ACCOUNT_TYPE_ASSETS && ((AssetsAccount*) froms[fromCombo->currentIndex()])->accountType() == ASSETS_TYPE_SECURITIES) {
				KMessageBox::error(this, i18n("Cannot create a regular expense from a securities account."));
				return false;
			}
			break;
		}
	}
	return true;
}
bool TransactionEditWidget::modifyTransaction(Transaction *trans) {
	if(!validValues()) return false;
	bool b_transsec = (trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL);
	if(b_sec) {
		if(trans->type() != transtype) return false;
		if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY) {
			if(fromCombo) ((SecurityTransaction*) trans)->setAccount(froms[fromCombo->currentIndex()]);
		} else {
			if(toCombo) ((SecurityTransaction*) trans)->setAccount(tos[toCombo->currentIndex()]);
		}
		if(dateEdit) trans->setDate(dateEdit->date());
		double shares = 0.0, value = 0.0, share_value = 0.0;
		if(valueEdit) value = valueEdit->value();
		if(sharesEdit) shares = sharesEdit->value();
		if(quotationEdit) share_value = quotationEdit->value();
		if(!quotationEdit) share_value = value / shares;
		else if(!sharesEdit) shares = value / share_value;
		else if(!valueEdit) value = shares * share_value;
		((SecurityTransaction*) trans)->setValue(value);
		((SecurityTransaction*) trans)->setShares(shares);
		((SecurityTransaction*) trans)->setShareValue(share_value);
		trans->setComment(commentsEdit->text());
		return true;
	} else if(b_transsec) {
		return false;
	}
	if(dateEdit) trans->setDate(dateEdit->date());
	if(fromCombo) trans->setFromAccount(froms[fromCombo->currentIndex()]);
	if(toCombo) trans->setToAccount(tos[toCombo->currentIndex()]);
	trans->setValue(valueEdit->value());
	if(descriptionEdit && (trans->type() != TRANSACTION_TYPE_INCOME || !((Income*) trans)->security())) trans->setDescription(descriptionEdit->text());
	trans->setComment(commentsEdit->text());
	if(quantityEdit) trans->setQuantity(quantityEdit->value());
	if(payeeEdit && trans->type() == TRANSACTION_TYPE_EXPENSE) ((Expense*) trans)->setPayee(payeeEdit->text());
	if(payeeEdit && trans->type() == TRANSACTION_TYPE_INCOME) ((Income*) trans)->setPayer(payeeEdit->text());
	return true;
}
Security *TransactionEditWidget::selectedSecurity() {
	if(securityCombo) {
		int i = securityCombo->currentIndex();
		if(i >= 0) {
			Security *c_sec = budget->securities.first();
			while(i > 0 && c_sec) {
				c_sec = budget->securities.next();
				i--;
			}
			return c_sec;
		}
	}
	return security;
}
Transaction *TransactionEditWidget::createTransaction() {
	if(!validValues()) return NULL;
	Transaction *trans;
	if(transtype == TRANSACTION_TYPE_TRANSFER) {
		Transfer *transfer = new Transfer(budget, valueEdit->value(), dateEdit ? dateEdit->date() : QDate(), fromCombo ? (AssetsAccount*) froms[fromCombo->currentIndex()] : NULL, toCombo ? (AssetsAccount*) tos[toCombo->currentIndex()] : NULL, descriptionEdit->text(), commentsEdit->text());
		trans = transfer;
	} else if(transtype == TRANSACTION_TYPE_INCOME) {
		Income *income = new Income(budget, valueEdit->value(), dateEdit ? dateEdit->date() : QDate(), fromCombo ? (IncomesAccount*) froms[fromCombo->currentIndex()] : NULL, toCombo ? (AssetsAccount*) tos[toCombo->currentIndex()] : NULL, descriptionEdit ? descriptionEdit->text() : QString::null, commentsEdit->text());
		if(selectedSecurity()) income->setSecurity(selectedSecurity());
		if(quantityEdit) income->setQuantity(quantityEdit->value());
		if(payeeEdit) income->setPayer(payeeEdit->text());
		trans = income;
	} else if(transtype == TRANSACTION_TYPE_SECURITY_BUY) {		
		if(!selectedSecurity()) return NULL;
		double shares = 0.0, value = 0.0, share_value = 0.0;
		if(valueEdit) value = valueEdit->value();
		if(sharesEdit) shares = sharesEdit->value();
		if(quotationEdit) share_value = quotationEdit->value();
		if(!quotationEdit) share_value = value / shares;
		else if(!sharesEdit) shares = value / share_value;
		else if(!valueEdit) value = shares * share_value;
		SecurityBuy *secbuy = new SecurityBuy(selectedSecurity(), value, shares, share_value, dateEdit ? dateEdit->date() : QDate(), fromCombo ? froms[fromCombo->currentIndex()] : NULL, commentsEdit->text());
		trans = secbuy;
	} else if(transtype == TRANSACTION_TYPE_SECURITY_SELL) {
		if(!selectedSecurity()) return NULL;
		double shares = 0.0, value = 0.0, share_value = 0.0;
		if(valueEdit) value = valueEdit->value();
		if(sharesEdit) shares = sharesEdit->value();
		if(quotationEdit) share_value = quotationEdit->value();
		if(!quotationEdit) share_value = value / shares;
		else if(!sharesEdit) shares = value / share_value;
		else if(!valueEdit) value = shares * share_value;
		SecuritySell *secsell = new SecuritySell(selectedSecurity(), value, shares, share_value, dateEdit ? dateEdit->date() : QDate(), toCombo ? tos[toCombo->currentIndex()] : NULL, commentsEdit->text());
		trans = secsell;
	} else {
		Expense *expense = new Expense(budget, valueEdit->value(), dateEdit ? dateEdit->date() : QDate(), toCombo ? (ExpensesAccount*) tos[toCombo->currentIndex()] : NULL, fromCombo ? (AssetsAccount*) froms[fromCombo->currentIndex()] : NULL, descriptionEdit->text(), commentsEdit->text());
		if(quantityEdit) expense->setQuantity(quantityEdit->value());
		if(payeeEdit) expense->setPayee(payeeEdit->text());
		trans = expense;
	}
	return trans;
}
void TransactionEditWidget::transactionRemoved(Transaction *trans) {
	if(descriptionEdit && trans->type() == transtype && !trans->description().isEmpty() && default_values[trans->description()] == trans) {
		switch(transtype) {
			case TRANSACTION_TYPE_EXPENSE: {
				Expense *expense = budget->expenses.first();
				while(expense) {
					if(expense != trans && expense->description() == trans->description()) {
						default_values[expense->description()] = expense;
						break;
					}
					expense = budget->expenses.next();
				}
				break;
			}
			case TRANSACTION_TYPE_INCOME: {
				Income *income = budget->incomes.first();
				while(income) {
					if(income != trans && income->description() == trans->description()) {
						default_values[income->description()] = income;
						break;
					}
					income = budget->incomes.next();
				}
				break;
			}
			case TRANSACTION_TYPE_TRANSFER: {
				Transfer *transfer= budget->transfers.first();
				while(transfer) {
					if(transfer != trans && transfer->description() == trans->description()) {
						default_values[transfer->description()] = transfer;
						break;
					}
					transfer = budget->transfers.next();
				}
				break;
			}
			default: {}
		}
	}
}
void TransactionEditWidget::transactionsReset() {
	if(!descriptionEdit) return;
	descriptionEdit->completionObject()->clear();
	if(payeeEdit) payeeEdit->completionObject()->clear();
	default_values.clear();
	switch(transtype) {
		case TRANSACTION_TYPE_EXPENSE: {
			Expense *expense = budget->expenses.first();
			while(expense) {
				if(!expense->description().isEmpty()) {
					descriptionEdit->completionObject()->addItem(expense->description());
					default_values[expense->description()] = expense;
				}
				if(payeeEdit && !expense->payee().isEmpty()) {
					payeeEdit->completionObject()->addItem(expense->payee());
				}
				expense = budget->expenses.next();
			}
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			Income *income = budget->incomes.first();
			while(income) {
				if(!income->security() && !income->description().isEmpty()) {
					descriptionEdit->completionObject()->addItem(income->description());
					default_values[income->description()] = income;
				}
				if(payeeEdit && !income->security() && !income->payer().isEmpty()) {
					payeeEdit->completionObject()->addItem(income->payer());
				}
				income = budget->incomes.next();
			}
			break;
		}
		case TRANSACTION_TYPE_TRANSFER: {
			Transfer *transfer= budget->transfers.first();
			while(transfer) {
				if(!transfer->description().isEmpty()) {
					descriptionEdit->completionObject()->addItem(transfer->description());
					default_values[transfer->description()] = transfer;
				}
				transfer = budget->transfers.next();
			}
			break;
		}
		default: {}
	}
}
void TransactionEditWidget::setCurrentToItem(int index) {
	if(toCombo) toCombo->setCurrentIndex(index);
}
void TransactionEditWidget::setCurrentFromItem(int index) {
	if(fromCombo) fromCombo->setCurrentIndex(index);
}
void TransactionEditWidget::setAccount(Account *account) {
	if(fromCombo && (transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_TRANSFER || transtype == TRANSACTION_TYPE_SECURITY_BUY)) {
		for(QVector<Account*>::size_type i = 0; i < froms.size(); i++) {
			if(account == froms[i]) {
				fromCombo->setCurrentIndex(i);
				break;
			}
		}
	} else if(toCombo) {
		for(QVector<Account*>::size_type i = 0; i < tos.size(); i++) {
			if(account == tos[i]) {
				toCombo->setCurrentIndex(i);
				break;
			}
		}
	}
}
int TransactionEditWidget::currentToItem() {
	if(!toCombo) return -1;
	return toCombo->currentIndex();
}
int TransactionEditWidget::currentFromItem() {
	if(!fromCombo) return -1;
	return fromCombo->currentIndex();
}
void TransactionEditWidget::setTransaction(Transaction *trans) {
	if(valueEdit) valueEdit->blockSignals(true);
	if(sharesEdit) sharesEdit->blockSignals(true);
	if(quotationEdit) quotationEdit->blockSignals(true);
	if(trans == NULL) {
		value_set = false; shares_set = false; sharevalue_set = false;
		description_changed = false;
		if(dateEdit) dateEdit->setDate(QDate::currentDate());
		if(b_sec) {
			if(sharesEdit) sharesEdit->setValue(0.0);
			if(quotationEdit) quotationEdit->setValue(0.0);
			if(valueEdit) valueEdit->setValue(0.0);
			if(valueEdit) valueEdit->setFocus();
			else sharesEdit->setFocus();
		} else {
			if(descriptionEdit) {
				descriptionEdit->clear();
				descriptionEdit->setFocus();
			} else {
				valueEdit->setFocus();
			}
			valueEdit->setValue(0.0);
		}
		commentsEdit->clear();
		if(quantityEdit) quantityEdit->setValue(1.0);
		if(payeeEdit) payeeEdit->clear();
		if(dateEdit) emit dateChanged(trans->date());
	} else {
		value_set = true; shares_set = true; sharevalue_set = true;
		if(dateEdit) dateEdit->setDate(trans->date());
		commentsEdit->setText(trans->comment());
		if(toCombo && (!b_sec || transtype == TRANSACTION_TYPE_SECURITY_SELL)) {
			for(QVector<Account*>::size_type i = 0; i < tos.size(); i++) {
				if(trans->toAccount() == tos[i]) {
					toCombo->setCurrentIndex(i);
					break;
				}
			}
		}
		if(fromCombo && (!b_sec || transtype == TRANSACTION_TYPE_SECURITY_BUY)) {
			for(QVector<Account*>::size_type i = 0; i < froms.size(); i++) {
				if(trans->fromAccount() == froms[i]) {
					fromCombo->setCurrentIndex(i);
					break;
				}
			}
		}
		if(b_sec) {
			if(transtype != trans->type()) return;
			//if(transtype == TRANSACTION_TYPE_SECURITY_SELL) setMaxShares(((SecurityTransaction*) trans)->security()->shares(QDate::currentDate()) + ((SecurityTransaction*) trans)->shares());
			if(sharesEdit) sharesEdit->setValue(((SecurityTransaction*) trans)->shares());
			if(quotationEdit) quotationEdit->setValue(((SecurityTransaction*) trans)->shareValue());
			if(valueEdit) valueEdit->setValue(trans->value());
			if(valueEdit) valueEdit->setFocus();
			else sharesEdit->setFocus();
		} else {
			if(descriptionEdit) {
				descriptionEdit->setText(trans->description());
				description_changed = false;
				descriptionEdit->setFocus();
				descriptionEdit->selectAll();
			} else {
				valueEdit->setFocus();
			}
			valueEdit->setValue(trans->value());
			if(quantityEdit) quantityEdit->setValue(trans->quantity());
			if(payeeEdit && trans->type() == TRANSACTION_TYPE_EXPENSE) payeeEdit->setText(((Expense*) trans)->payee());
			if(payeeEdit && trans->type() == TRANSACTION_TYPE_INCOME) payeeEdit->setText(((Income*) trans)->payer());
		}
		if(dateEdit) emit dateChanged(trans->date());
	}
	if(valueEdit) valueEdit->blockSignals(false);
	if(sharesEdit) sharesEdit->blockSignals(false);
	if(quotationEdit) quotationEdit->blockSignals(false);
}
void TransactionEditWidget::setScheduledTransaction(ScheduledTransaction *strans, const QDate &date) {
	if(strans == NULL) {
		setTransaction(NULL);
	} else {
		setTransaction(strans->transaction());
		if(dateEdit) dateEdit->setDate(date);
	}
}

TransactionEditDialog::TransactionEditDialog(bool extra_parameters, int transaction_type, bool split, bool transfer_to, Security *security, SecurityValueDefineType security_value_type, bool select_security, Budget *budg, QWidget *parent) : KDialog(parent, 0){
	setButtons(KDialog::Ok | KDialog::Cancel);
	setDefaultButton(KDialog::Cancel);
	setModal(true);
	switch(transaction_type) {
		case TRANSACTION_TYPE_EXPENSE: {setPlainCaption(i18n("Edit Expense")); break;}
		case TRANSACTION_TYPE_INCOME: {
			if(security || select_security) setPlainCaption(i18n("Edit Dividend"));
			else setPlainCaption(i18n("Edit Income"));
			break;
		}
		case TRANSACTION_TYPE_TRANSFER: {setPlainCaption(i18n("Edit Transfer")); break;}
		case TRANSACTION_TYPE_SECURITY_BUY: {setPlainCaption(i18n("Edit Securities Bought")); break;}
		case TRANSACTION_TYPE_SECURITY_SELL: {setPlainCaption(i18n("Edit Securities Sold")); break;}
	}
	editWidget = new TransactionEditWidget(false, extra_parameters, transaction_type, split, transfer_to, security, security_value_type, select_security, budg, this);
	editWidget->transactionsReset();
	setMainWidget(editWidget);
}
void TransactionEditDialog::slotButtonClicked(int button) {
	if(button != KDialog::Ok || editWidget->validValues(true)) {
		KDialog::slotButtonClicked(button);
	}
}

MultipleTransactionsEditDialog::MultipleTransactionsEditDialog(bool extra_parameters, int transaction_type, Budget *budg, QWidget *parent)  : KDialog(parent), transtype(transaction_type), budget(budg), b_extra(extra_parameters) {
	
	setCaption(i18n("Modify Transactions"));	
	setButtons(KDialog::Ok | KDialog::Cancel);
	setDefaultButton(KDialog::Cancel);
	setModal(true);
	
	setMainWidget(new QWidget(this));

	int rows = 4;
	if(b_extra && (transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME)) rows= 5;
	else if(transtype == TRANSACTION_TYPE_TRANSFER) rows = 3;
	else rows = 2;
	QGridLayout *editLayout = new QGridLayout(mainWidget());

	descriptionButton = new QCheckBox(i18n("Description:"), mainWidget());
	descriptionButton->setChecked(false);
	editLayout->addWidget(descriptionButton, 0, 0);
	descriptionEdit = new KLineEdit(mainWidget());
	descriptionEdit->setEnabled(false);
	editLayout->addWidget(descriptionEdit, 0, 1);

	valueButton = NULL;
	valueEdit = NULL;
	if(transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME || transtype == TRANSACTION_TYPE_TRANSFER) {
		if(transtype == TRANSACTION_TYPE_TRANSFER) valueButton = new QCheckBox(i18n("Amount:"), mainWidget());
		else if(transtype == TRANSACTION_TYPE_INCOME) valueButton = new QCheckBox(i18n("Income:"), mainWidget());
		else valueButton = new QCheckBox(i18n("Cost:"), mainWidget());
		valueButton->setChecked(false);
		editLayout->addWidget(valueButton, 1, 0);
		valueEdit = new EqonomizeValueEdit(false, mainWidget());
		valueEdit->setEnabled(false);
		editLayout->addWidget(valueEdit, 1, 1);
	}

	dateButton = new QCheckBox(i18n("Date:"), mainWidget());
	dateButton->setChecked(false);
	editLayout->addWidget(dateButton, 2, 0);
	dateEdit = new KDateEdit(mainWidget());
	dateEdit->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
	dateEdit->setEnabled(false);
	editLayout->addWidget(dateEdit, 2, 1);

	categoryButton = NULL;
	categoryCombo = NULL;
	if(transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME) {
		categoryButton = new QCheckBox(i18n("Category:"), mainWidget());
		categoryButton->setChecked(false);
		editLayout->addWidget(categoryButton, 3, 0);
		categoryCombo = new KComboBox(mainWidget());
		categoryCombo->setEditable(false);
		categoryCombo->setEnabled(false);
		updateAccounts();
		editLayout->addWidget(categoryCombo, 3, 1);
		connect(categoryButton, SIGNAL(toggled(bool)), categoryCombo, SLOT(setEnabled(bool)));
	}

	payeeButton = NULL;
	payeeEdit = NULL;
	if(b_extra && (transtype == TRANSACTION_TYPE_EXPENSE || transtype == TRANSACTION_TYPE_INCOME)) {
		if(transtype == TRANSACTION_TYPE_INCOME) payeeButton = new QCheckBox(i18n("Payer:"), mainWidget());
		else payeeButton = new QCheckBox(i18n("Payee:"), mainWidget());
		payeeButton->setChecked(false);
		editLayout->addWidget(payeeButton, 4, 0);
		payeeEdit = new KLineEdit(mainWidget());
		payeeEdit->setEnabled(false);
		editLayout->addWidget(payeeEdit, 4, 1);
		connect(payeeButton, SIGNAL(toggled(bool)), payeeEdit, SLOT(setEnabled(bool)));
	}

	connect(descriptionButton, SIGNAL(toggled(bool)), descriptionEdit, SLOT(setEnabled(bool)));
	if(valueButton) connect(valueButton, SIGNAL(toggled(bool)), valueEdit, SLOT(setEnabled(bool)));
	connect(dateButton, SIGNAL(toggled(bool)), dateEdit, SLOT(setEnabled(bool)));
	
}

void MultipleTransactionsEditDialog::setTransaction(Transaction *trans) {
	if(trans) {
		descriptionEdit->setText(trans->description());
		dateEdit->setDate(trans->date());
		if(valueEdit) valueEdit->setValue(trans->value());
		if(transtype == TRANSACTION_TYPE_EXPENSE) {
			for(QVector<Account*>::size_type i = 0; i < categories.size(); i++) {
				if(((Expense*) trans)->category() == categories[i]) {
					categoryCombo->setCurrentIndex(i);
					break;
				}
			}
			if(payeeEdit) payeeEdit->setText(((Expense*) trans)->payee());
		} else if(transtype == TRANSACTION_TYPE_INCOME) {
			for(QVector<Account*>::size_type i = 0; i < categories.size(); i++) {
				if(((Income*) trans)->category() == categories[i]) {
					categoryCombo->setCurrentIndex(i);
					break;
				}
			}
			if(payeeEdit) payeeEdit->setText(((Income*) trans)->payer());
		}
	} else {
		descriptionEdit->clear();
		dateEdit->setDate(QDate::currentDate());
		if(valueEdit) valueEdit->setValue(0.0);
		if(payeeEdit) payeeEdit->clear();
	}
}
void MultipleTransactionsEditDialog::setScheduledTransaction(ScheduledTransaction *strans, const QDate &date) {
	if(strans) setTransaction(strans->transaction());
	else setTransaction(NULL);
	dateEdit->setDate(date);
}
void MultipleTransactionsEditDialog::updateAccounts() {
	if(!categoryCombo) return;
	categoryCombo->clear();
	categories.clear();
	switch(transtype) {
		case TRANSACTION_TYPE_INCOME: {
			Account *account = budget->incomesAccounts.first();
			while(account) {
				categoryCombo->addItem(account->name());
				categories.push_back(account);
				account = budget->incomesAccounts.next();
			}
			break;
		}
		case TRANSACTION_TYPE_EXPENSE: {
			Account *account = budget->expensesAccounts.first();
			while(account) {
				categoryCombo->addItem(account->name());
				categories.push_back(account);
				account = budget->expensesAccounts.next();
			}
			break;
		}
		default: {}
	}
}
bool MultipleTransactionsEditDialog::modifyTransaction(Transaction *trans) {
	if(!validValues()) return false;
	bool b_descr = true, b_value = true;
	switch(trans->type()) {
		case TRANSACTION_TYPE_EXPENSE: {
			if(transtype == trans->type() && categoryButton->isChecked()) ((Expense*) trans)->setCategory((ExpensesAccount*) categories[categoryCombo->currentIndex()]);
			if(payeeEdit && payeeButton->isChecked()) ((Expense*) trans)->setPayee(payeeEdit->text());
			break;
		}
		case TRANSACTION_TYPE_INCOME: {
			if(((Income*) trans)->security()) b_descr = false;
			else if(payeeEdit && payeeButton->isChecked()) ((Income*) trans)->setPayer(payeeEdit->text());
			if(transtype == trans->type() && categoryButton->isChecked()) ((Income*) trans)->setCategory((IncomesAccount*) categories[categoryCombo->currentIndex()]);
			break;
		}
		case TRANSACTION_TYPE_TRANSFER: {
			break;
		}
		case TRANSACTION_TYPE_SECURITY_BUY: {
			if(transtype == TRANSACTION_TYPE_INCOME && categoryButton->isChecked()) ((SecurityTransaction*) trans)->setAccount(categories[categoryCombo->currentIndex()]);
			b_descr = false;
			b_value = false;
			break;
		}
		case TRANSACTION_TYPE_SECURITY_SELL: {
			if(transtype == TRANSACTION_TYPE_INCOME && categoryButton->isChecked()) ((SecurityTransaction*) trans)->setAccount(categories[categoryCombo->currentIndex()]);
			b_descr = false;
			b_value = false;
			break;
		}
	}
	if(b_descr && descriptionButton->isChecked()) trans->setDescription(descriptionEdit->text());
	if(valueEdit && b_value && valueButton->isChecked()) trans->setValue(valueEdit->value());
	if(dateButton->isChecked() && !trans->parentSplit()) trans->setDate(dateEdit->date());
	return true;
}

bool MultipleTransactionsEditDialog::checkAccounts() {
	switch(transtype) {
		case TRANSACTION_TYPE_INCOME: {
			if(!categoryButton->isChecked()) return true;
			if(categoryCombo->count() == 0) {
				KMessageBox::error(this, i18n("No income category available."));
				return false;
			}
			break;
		}
		case TRANSACTION_TYPE_EXPENSE: {
			if(!categoryButton->isChecked()) return true;
			if(categoryCombo->count() == 0) {
				KMessageBox::error(this, i18n("No expense category available."));
				return false;
			}
			break;
		}
		default: {}
	}
	return true;
}
bool MultipleTransactionsEditDialog::validValues() {
	if(dateButton->isChecked() && !dateEdit->date().isValid()) {
		KMessageBox::error(this, i18n("Invalid date."));
		dateEdit->setFocus();
		dateEdit->lineEdit()->selectAll();
		return false;
	}
	if(!checkAccounts()) return false;
	return true;
}
void MultipleTransactionsEditDialog::slotButtonClicked(int button) {
	if(button == KDialog::Ok) {
		if(!descriptionButton->isChecked() && (!valueButton || !valueButton->isChecked()) && !dateButton->isChecked() && (!categoryButton || !categoryButton->isChecked()) && (!payeeButton || !payeeButton->isChecked())) {
			KDialog::slotButtonClicked(KDialog::Cancel);
		} else if(validValues()) {
			KDialog::slotButtonClicked(KDialog::Ok);
		}
	} else {
		KDialog::slotButtonClicked(button);
	}
}
QDate MultipleTransactionsEditDialog::date() {
	if(!dateButton->isChecked()) return QDate();
	return dateEdit->date();
}
		
#include "transactioneditwidget.moc"

