/*************************************************************************** * Copyright (C) 2006, 2007 by Niklas Knutsson * * nq@altern.org * * * * 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 #endif #include "eqonomize.h" #include "budget.h" #include "recurrence.h" #include "security.h" #include "transactionlistwidget.h" #include "transactioneditwidget.h" #include "recurrenceeditwidget.h" #include "editscheduledtransactiondialog.h" #include "overtimereport.h" #include "categoriescomparisonreport.h" #include "categoriescomparisonchart.h" #include "overtimechart.h" #include "importcsvdialog.h" #include "eqonomizemonthselector.h" #include "editsplitdialog.h" #include "ledgerdialog.h" #include "eqonomizevalueedit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdateedit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qifimportexport.h" #if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2 #include #else #include #endif QDate addYears(const QDate &date, int nyears) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); if(KGlobal::locale()->calendarType() == "gregorian") { return calSys->addYears(date, nyears); } QDate result = date; int y = calSys->year(date) + nyears; int d = calSys->day(date); int m = calSys->month(date); calSys->setYMD(result, y, 1, 1); if(m > calSys->monthsInYear(result)) { calSys->setYMD(result, y + 1, 1, 1); calSys->addDays(result, -1); } calSys->setYMD(result, y, m, 1); if(d > calSys->daysInMonth(result)) { d = calSys->daysInMonth(result); } calSys->setYMD(result, y, m, d); return result; } QDate addMonths(const QDate &date, int nmonths) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); if(KGlobal::locale()->calendarType() == "gregorian") { return calSys->addMonths(date, nmonths); } QDate result = date; int m = calSys->month(date); int d = calSys->day(date); if(nmonths > 0) { int nMonthsInYear = calSys->monthsInYear(result); while(nmonths > 0 && m + nmonths > nMonthsInYear) { calSys->setYMD(result, calSys->year(result) + 1, 1, 1); nmonths -= nMonthsInYear - m + 1; m = 1; nMonthsInYear = calSys->monthsInYear(result); } if(nmonths > 0) { calSys->setYMD(result, calSys->year(result), m + nmonths, 1); } if(d != 1) { int nDaysInMonth = calSys->daysInMonth(result); if(d > nDaysInMonth) result = calSys->addDays(result, nDaysInMonth - 1); else result = calSys->addDays(result, d - 1); } } else if(nmonths < 0) { while(nmonths < 0 && m + nmonths < 1) { calSys->setYMD(result, calSys->year(result) - 1, 1, 1); int nMonthsInYear = calSys->monthsInYear(result); calSys->setYMD(result, calSys->year(result), nMonthsInYear, 1); nmonths += m; m = nMonthsInYear; } if(nmonths < 0) { calSys->setYMD(result, calSys->year(result), m + nmonths, 1); } if(d != 1) { int nDaysInMonth = calSys->daysInMonth(result); if(d > nDaysInMonth) result = calSys->addDays(result, nDaysInMonth - 1); else result = calSys->addDays(result, d - 1); } } return result; } double averageMonth(const QDate &date1, const QDate &date2) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); double average_month = (double) calSys->daysInYear(date1) / (double) calSys->monthsInYear(date1); int years = 1; QDate ydate; calSys->setYMD(ydate, calSys->year(date1), 1, 1); ydate = addYears(ydate, 1); while(calSys->year(ydate) <= calSys->year(date2)) { average_month += (double) calSys->daysInYear(ydate) / (double) calSys->monthsInYear(ydate); years++; ydate = addYears(ydate, 1); } return average_month / years; } double averageYear(const QDate &date1, const QDate &date2) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); double average_year = calSys->daysInYear(date1); int years = 1; QDate ydate; calSys->setYMD(ydate, calSys->year(date1), 1, 1); ydate = addYears(ydate, 1); while(calSys->year(ydate) <= calSys->year(date2)) { average_year += calSys->daysInYear(ydate); years++; ydate = addYears(ydate, 1); } return average_year / years; } double yearsBetweenDates(const QDate &date1, const QDate &date2) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); double years = 0.0; if(calSys->year(date1) == calSys->year(date2)) { int days = date1.daysTo(date2) + 1; years = (double) days / (double) calSys->daysInYear(date2); } else { QDate yeardate; calSys->setYMD(yeardate, calSys->year(date1), 1, 1); years += (1.0 - (calSys->dayOfYear(date1) - 1.0) / (double) calSys->daysInYear(date1)); yeardate = addYears(yeardate, 1); while(calSys->year(yeardate) != calSys->year(date2)) { years += 1.0; yeardate = addYears(yeardate, 1); } years += (double) calSys->dayOfYear(date2) / (double) calSys->daysInYear(date2); } return years; } double monthsBetweenDates(const QDate &date1, const QDate &date2) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); double months = 0.0; if(calSys->year(date1) == calSys->year(date2)) { if(calSys->month(date1) == calSys->month(date2)) { int days = date1.daysTo(date2) + 1; months = (double) days / (double) calSys->daysInMonth(date2); } else { QDate monthdate; calSys->setYMD(monthdate, calSys->year(date1), calSys->month(date1), 1); months += (1.0 - ((calSys->day(date1) - 1.0) / (double) calSys->daysInMonth(date1))); months += (calSys->month(date2) - calSys->month(date1) - 1); calSys->setYMD(monthdate, calSys->year(date2), calSys->month(date2), 1); months += (double) calSys->day(date2) / (double) calSys->daysInMonth(date2); } } else { QDate monthdate; calSys->setYMD(monthdate, calSys->year(date1), calSys->month(date1), 1); months += (1.0 - ((calSys->day(date1) - 1.0) / (double) calSys->daysInMonth(date1))); months += (calSys->monthsInYear(date1) - calSys->month(date1)); QDate yeardate; calSys->setYMD(yeardate, calSys->year(date1), 1, 1); yeardate = addYears(yeardate, 1); while(calSys->year(yeardate) != calSys->year(date2)) { months += calSys->monthsInYear(yeardate); yeardate = addYears(yeardate, 1); } calSys->setYMD(monthdate, calSys->year(date2), calSys->month(date2), 1); months += (double) calSys->day(date2) / (double) calSys->daysInMonth(date2); months += calSys->month(date2) - 1; } return months; } class SecurityListViewItem : public KListViewItem { protected: Security *o_security; public: SecurityListViewItem(Security *sec, QListView *parent, QString s1, QString s2 = QString::null, QString s3 = QString::null, QString s4 = QString::null, QString s5 = QString::null, QString s6 = QString::null, QString s7 = QString::null, QString s8 = QString::null) : KListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8), o_security(sec) {} int compare(QListViewItem *i, int col, bool ascending) const { if(col >= 2 && col <= 6) { double d1 = text(col).toDouble(); double d2 = i->text(col).toDouble(); if(d1 > d2) return 1; if(d1 < d2) return -1; return 0; } return QListViewItem::compare(i, col, ascending); } Security* security() const {return o_security;} double cost, value, rate, profit; }; class ScheduleListViewItem : public KListViewItem { protected: ScheduledTransaction *o_strans; QDate d_date; public: ScheduleListViewItem(ScheduledTransaction *strans, const QDate &trans_date, QListView *parent, QString, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null); int compare(QListViewItem *i, int col, bool ascending) const; ScheduledTransaction *scheduledTransaction() const; const QDate &date() const; void setDate(const QDate &newdate); }; ScheduleListViewItem::ScheduleListViewItem(ScheduledTransaction *strans, const QDate &trans_date, QListView *parent, QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8) : KListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8), o_strans(strans), d_date(trans_date) {} int ScheduleListViewItem::compare(QListViewItem *i, int col, bool ascending) const { if(col == 0) { if(d_date > ((ScheduleListViewItem*) i)->date()) return 1; if(d_date < ((ScheduleListViewItem*) i)->date()) return -1; return 0; } else if(col == 3) { if(o_strans->transaction()->value() > ((ScheduleListViewItem*) i)->scheduledTransaction()->transaction()->value()) return 1; if(o_strans->transaction()->value() < ((ScheduleListViewItem*) i)->scheduledTransaction()->transaction()->value()) return -1; return 0; } return QListViewItem::compare(i, col, ascending); } ScheduledTransaction *ScheduleListViewItem::scheduledTransaction() const { return o_strans; } const QDate &ScheduleListViewItem::date() const { return d_date; } void ScheduleListViewItem::setDate(const QDate &newdate) { d_date = newdate; } class ConfirmScheduleListViewItem : public KListViewItem { protected: Transaction *o_trans; public: ConfirmScheduleListViewItem(Transaction *trans, QListView *parent, QString, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null); int compare(QListViewItem *i, int col, bool ascending) const; Transaction *transaction() const; }; ConfirmScheduleListViewItem::ConfirmScheduleListViewItem(Transaction *trans, QListView *parent, QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8) : KListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8), o_trans(trans) {} int ConfirmScheduleListViewItem::compare(QListViewItem *i, int col, bool ascending) const { if(col == 0) { if(o_trans->date() > ((ConfirmScheduleListViewItem*) i)->transaction()->date()) return 1; if(o_trans->date() < ((ConfirmScheduleListViewItem*) i)->transaction()->date()) return -1; return 0; } else if(col == 3) { if(o_trans->value() > ((ConfirmScheduleListViewItem*) i)->transaction()->value()) return 1; if(o_trans->value() < ((ConfirmScheduleListViewItem*) i)->transaction()->value()) return -1; return 0; } return QListViewItem::compare(i, col, ascending); } Transaction *ConfirmScheduleListViewItem::transaction() const { return o_trans; } class SecurityTransactionListViewItem : public KListViewItem { public: SecurityTransactionListViewItem(QListView *parent, QString, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null); int compare(QListViewItem *i_pre, int col, bool ascending) const; SecurityTransaction *trans; Income *div; ReinvestedDividend *rediv; ScheduledTransaction *strans, *sdiv; SecurityTrade *ts; QDate date; double shares, value; }; SecurityTransactionListViewItem::SecurityTransactionListViewItem(QListView *parent, QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8) : KListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8), trans(NULL), div(NULL), rediv(NULL), strans(NULL), sdiv(NULL), ts(NULL), shares(-1.0), value(-1.0) {} int SecurityTransactionListViewItem::compare(QListViewItem *i_pre, int col, bool ascending) const { SecurityTransactionListViewItem *i = (SecurityTransactionListViewItem*) i_pre; if(col == 0) { if(date > i->date) return 1; if(date < i->date) return -1; return 0; } else if(col == 2) { if(value > i->value) return 1; if(value < i->value) return -1; return 0; } else if(col == 2) { if(shares > i->shares) return 1; if(shares < i->shares) return -1; return 0; } return QListViewItem::compare(i, col, ascending); } class QuotationListViewItem : public KListViewItem { public: QuotationListViewItem(const QDate &date_, double value_, QListView *parent, QString, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null, QString=QString::null); int compare(QListViewItem *i, int col, bool ascending) const; QDate date; double value; }; QuotationListViewItem::QuotationListViewItem(const QDate &date_, double value_, QListView *parent, QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8) : KListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8), date(date_), value(value_) {} int QuotationListViewItem::compare(QListViewItem *i, int col, bool ascending) const { if(col == 0) { if(date > ((QuotationListViewItem*) i)->date) return 1; if(date < ((QuotationListViewItem*) i)->date) return -1; return 0; } else if(col == 1) { if(value > ((QuotationListViewItem*) i)->value) return 1; if(value < ((QuotationListViewItem*) i)->value) return -1; return 0; } return QListViewItem::compare(i, col, ascending); } RefundDialog::RefundDialog(Transaction *trans, QWidget *parent) : KDialogBase(parent, 0, true, i18n("Refund"), Ok | Cancel, Ok, true), transaction(trans) { if(trans->type() == TRANSACTION_TYPE_INCOME) setCaption(i18n("Repayment")); setMainWidget(new QWidget(this)); QGridLayout *layout = new QGridLayout(mainWidget(), 5, 2, 0, spacingHint()); layout->addWidget(new QLabel(i18n("Date:"), mainWidget()), 0, 0); dateEdit = new KDateEdit(mainWidget()); layout->addWidget(dateEdit, 0, 1); dateEdit->setFocus(); if(trans->type() == TRANSACTION_TYPE_INCOME) layout->addWidget(new QLabel(i18n("Cost:"), mainWidget()), 1, 0); else layout->addWidget(new QLabel(i18n("Income:"), mainWidget()), 1, 0); valueEdit = new EqonomizeValueEdit(trans->value(), false, true, mainWidget()); layout->addWidget(valueEdit, 1, 1); layout->addWidget(new QLabel(i18n("Account:"), mainWidget()), 2, 0); accountCombo = new KComboBox(mainWidget()); accountCombo->setEditable(false); int i = 0; AssetsAccount *account = transaction->budget()->assetsAccounts.first(); while(account) { if(account != transaction->budget()->balancingAccount && account->accountType() != ASSETS_TYPE_SECURITIES) { accountCombo->insertItem(account->name()); if((transaction->type() == TRANSACTION_TYPE_EXPENSE && account == ((Expense*) transaction)->from()) || (transaction->type() == TRANSACTION_TYPE_INCOME && account == ((Income*) transaction)->to())) accountCombo->setCurrentItem(i); i++; } account = transaction->budget()->assetsAccounts.next(); } layout->addWidget(accountCombo, 2, 1); layout->addWidget(new QLabel(i18n("Quantity:"), mainWidget()), 3, 0); quantityEdit = new EqonomizeValueEdit(trans->quantity(), 2, false, false, mainWidget()); layout->addWidget(quantityEdit, 3, 1); layout->addWidget(new QLabel(i18n("Comments:"), mainWidget()), 4, 0); commentsEdit = new KLineEdit(mainWidget()); if(trans->type() == TRANSACTION_TYPE_INCOME) commentsEdit->setText(i18n("Repayment")); else commentsEdit->setText(i18n("Refund")); layout->addWidget(commentsEdit, 4, 1); } Transaction *RefundDialog::createRefund() { if(!validValues()) return NULL; Transaction *trans = NULL; int i = 0; int cur_i = accountCombo->currentItem(); AssetsAccount *account = transaction->budget()->assetsAccounts.first(); while(account) { if(account != transaction->budget()->balancingAccount && account->accountType() != ASSETS_TYPE_SECURITIES) { if(i == cur_i) break; i++; } account = transaction->budget()->assetsAccounts.next(); } trans = transaction->copy(); if(transaction->type() == TRANSACTION_TYPE_EXPENSE) { ((Expense*) trans)->setFrom(account); } else { ((Income*) trans)->setTo(account); } trans->setQuantity(-quantityEdit->value()); trans->setValue(-valueEdit->value()); trans->setDate(dateEdit->date()); trans->setComment(commentsEdit->text()); return trans; } void RefundDialog::slotOk() { if(validValues()) { KDialogBase::slotOk(); } } bool RefundDialog::validValues() { if(!dateEdit->date().isValid()) { KMessageBox::error(this, i18n("Invalid date.")); return false; } return true; } EditReinvestedDividendDialog::EditReinvestedDividendDialog(Budget *budg, Security *sec, bool select_security, QWidget *parent) : KDialogBase(parent, 0, true, i18n("Reinvested Dividend"), Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *layout = new QGridLayout(mainWidget(), 3, 2, 0, spacingHint()); securityCombo = NULL; layout->addWidget(new QLabel(i18n("Security:"), mainWidget()), 0, 0); if(select_security) { securityCombo = new KComboBox(mainWidget()); securityCombo->setEditable(false); Security *c_sec = budget->securities.first(); int i2 = 0; while(c_sec) { securityCombo->insertItem(c_sec->name()); if(c_sec == sec) securityCombo->setCurrentItem(i2); c_sec = budget->securities.next(); i2++; } layout->addWidget(securityCombo, 0, 1); } else { layout->addWidget(new QLabel(sec->name(), mainWidget()), 0, 1); } layout->addWidget(new QLabel(i18n("Shares added:"), mainWidget()), 1, 0); sharesEdit = new EqonomizeValueEdit(0.0, selectedSecurity()->decimals(), false, false, mainWidget()); layout->addWidget(sharesEdit, 1, 1); sharesEdit->setFocus(); layout->addWidget(new QLabel(i18n("Date:"), mainWidget()), 2, 0); dateEdit = new KDateEdit(mainWidget()); layout->addWidget(dateEdit, 2, 1); if(securityCombo) connect(securityCombo, SIGNAL(activated(int)), this, SLOT(securityChanged())); } Security *EditReinvestedDividendDialog::selectedSecurity() { if(securityCombo) { int i = securityCombo->currentItem(); if(i >= 0) { Security *c_sec = budget->securities.first(); while(i > 0 && c_sec) { c_sec = budget->securities.next(); i--; } return c_sec; } } return NULL; } void EditReinvestedDividendDialog::securityChanged() { if(selectedSecurity()) { if(sharesEdit) sharesEdit->setPrecision(selectedSecurity()->decimals()); } } void EditReinvestedDividendDialog::setDividend(ReinvestedDividend *rediv) { dateEdit->setDate(rediv->date); sharesEdit->setValue(rediv->shares); } bool EditReinvestedDividendDialog::modifyDividend(ReinvestedDividend *rediv) { if(!validValues()) return false; rediv->date = dateEdit->date(); rediv->shares = sharesEdit->value(); return true; } ReinvestedDividend *EditReinvestedDividendDialog::createDividend() { if(!validValues()) return NULL; return new ReinvestedDividend(dateEdit->date(), sharesEdit->value()); } void EditReinvestedDividendDialog::slotOk() { if(validValues()) { KDialogBase::slotOk(); } } bool EditReinvestedDividendDialog::validValues() { if(!dateEdit->date().isValid()) { KMessageBox::error(this, i18n("Invalid date.")); return false; } return true; } EditSecurityTradeDialog::EditSecurityTradeDialog(Budget *budg, Security *sec, QWidget *parent) : KDialogBase(parent, 0, true, i18n("Security Trade"), Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *layout = new QGridLayout(mainWidget(), 6, 2, 0, spacingHint()); layout->addWidget(new QLabel(i18n("From security:"), mainWidget()), 0, 0); fromSecurityCombo = new KComboBox(mainWidget()); fromSecurityCombo->setEditable(false); Security *c_sec = budget->securities.first(); if(!sec) sec = c_sec; int i = 0; while(c_sec) { fromSecurityCombo->insertItem(c_sec->name()); if(c_sec == sec) { fromSecurityCombo->setCurrentItem(i); } c_sec = budget->securities.next(); i++; } layout->addWidget(fromSecurityCombo, 0, 1); layout->addWidget(new QLabel(i18n("Shares moved:"), mainWidget()), 1, 0); QHBoxLayout *sharesLayout = new QHBoxLayout(0); fromSharesEdit = new EqonomizeValueEdit(0.0, sec ? sec->shares() : 10000.0, 1.0, 0.0, sec ? sec->decimals() : 4, false, mainWidget()); fromSharesEdit->setSizePolicy(QSizePolicy::Expanding, fromSharesEdit->sizePolicy().verData()); sharesLayout->addWidget(fromSharesEdit); QPushButton *maxSharesButton = new QPushButton(i18n("All"), mainWidget()); maxSharesButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); sharesLayout->addWidget(maxSharesButton); layout->addLayout(sharesLayout, 1, 1); fromSharesEdit->setFocus(); layout->addWidget(new QLabel(i18n("To security:"), mainWidget()), 2, 0); toSecurityCombo = new KComboBox(mainWidget()); toSecurityCombo->setEditable(false); c_sec = budget->securities.first(); bool sel = false; i = 0; while(c_sec) { toSecurityCombo->insertItem(c_sec->name()); if(sec && !sel && c_sec != sec && c_sec->account() == sec->account()) { sel = true; toSecurityCombo->setCurrentItem(i); } c_sec = budget->securities.next(); i++; } layout->addWidget(toSecurityCombo, 2, 1); layout->addWidget(new QLabel(i18n("Shares received:"), mainWidget()), 3, 0); toSharesEdit = new EqonomizeValueEdit(0.0, sec ? sec->decimals() : 4, false, false, mainWidget()); layout->addWidget(toSharesEdit, 3, 1); layout->addWidget(new QLabel(i18n("Value:"), mainWidget()), 4, 0); valueEdit = new EqonomizeValueEdit(false, mainWidget()); layout->addWidget(valueEdit, 4, 1); layout->addWidget(new QLabel(i18n("Date:"), mainWidget()), 5, 0); dateEdit = new KDateEdit(mainWidget()); layout->addWidget(dateEdit, 5, 1); toSecurityChanged(); fromSecurityChanged(); connect(maxSharesButton, SIGNAL(clicked()), this, SLOT(maxShares())); connect(fromSecurityCombo, SIGNAL(activated(int)), this, SLOT(fromSecurityChanged())); connect(toSecurityCombo, SIGNAL(activated(int)), this, SLOT(toSecurityChanged())); } void EditSecurityTradeDialog::maxShares() { fromSharesEdit->setValue(fromSharesEdit->maxValue()); } Security *EditSecurityTradeDialog::selectedFromSecurity() { int index = fromSecurityCombo->currentItem(); Security *sec = budget->securities.first(); int i = 0; while(sec) { if(i == index) { return sec; } i++; sec = budget->securities.next(); } return NULL; } Security *EditSecurityTradeDialog::selectedToSecurity() { int index = toSecurityCombo->currentItem(); Security *sec = budget->securities.first(); int i = 0; while(sec) { if(i == index) { return sec; } i++; sec = budget->securities.next(); } return NULL; } void EditSecurityTradeDialog::fromSecurityChanged() { Security *sec = selectedFromSecurity(); if(sec) { fromSharesEdit->setPrecision(sec->decimals()); fromSharesEdit->setMaxValue(sec->shares()); } } void EditSecurityTradeDialog::toSecurityChanged() { Security *sec = selectedToSecurity(); if(sec) toSharesEdit->setPrecision(sec->decimals()); } void EditSecurityTradeDialog::setSecurityTrade(SecurityTrade *ts) { dateEdit->setDate(ts->date); Security *sec = budget->securities.first(); int i = 0; while(sec) { if(sec == ts->from_security) { fromSecurityCombo->setCurrentItem(i); break; } i++; sec = budget->securities.next(); } fromSharesEdit->setMaxValue(ts->from_security->shares() + ts->from_shares); fromSharesEdit->setValue(ts->from_shares); toSharesEdit->setValue(ts->to_shares); valueEdit->setValue(ts->value); sec = budget->securities.first(); i = 0; while(sec) { if(sec == ts->to_security) { toSecurityCombo->setCurrentItem(i); break; } i++; sec = budget->securities.next(); } } SecurityTrade *EditSecurityTradeDialog::createSecurityTrade() { if(!validValues()) return NULL; return new SecurityTrade(dateEdit->date(), valueEdit->value(), fromSharesEdit->value(), selectedFromSecurity(), toSharesEdit->value(), selectedToSecurity()); } bool EditSecurityTradeDialog::checkSecurities() { if(toSecurityCombo->count() < 2) { KMessageBox::error(this, i18n("No other security available for trade in the account.")); return false; } return true; } void EditSecurityTradeDialog::slotOk() { if(validValues()) { KDialogBase::slotOk(); } } bool EditSecurityTradeDialog::validValues() { if(selectedFromSecurity() == selectedToSecurity()) { KMessageBox::error(this, i18n("Selected to and from securities are the same.")); return false; } if(!dateEdit->date().isValid()) { KMessageBox::error(this, i18n("Invalid date.")); return false; } if(fromSharesEdit->value() == 0.0 || toSharesEdit->value() == 0.0) { KMessageBox::error(this, i18n("Zero shares not allowed.")); return false; } if(valueEdit->value() == 0.0) { KMessageBox::error(this, i18n("Zero value not allowed.")); return false; } return true; } EditQuotationsDialog::EditQuotationsDialog(QWidget *parent) : KDialogBase(parent, 0, true, i18n("Quotations"), Ok | Cancel, Ok, true) { setMainWidget(new QWidget(this)); QVBoxLayout *quotationsVLayout = new QVBoxLayout(mainWidget(), 0, spacingHint()); titleLabel = new QLabel(i18n("Quotations"), mainWidget()); quotationsVLayout->addWidget(titleLabel); QHBoxLayout *quotationsLayout = new QHBoxLayout(quotationsVLayout); quotationsView = new KListView(mainWidget()); quotationsView->setSorting(0, false); quotationsView->setAllColumnsShowFocus(true); quotationsView->addColumn(i18n("Date")); quotationsView->addColumn(i18n("Price per Share")); quotationsView->setColumnAlignment(0, Qt::AlignRight); quotationsView->setColumnAlignment(1, Qt::AlignRight); quotationsView->setRootIsDecorated(false); quotationsView->header()->setClickEnabled(false); QSizePolicy sp = quotationsView->sizePolicy(); sp.setHorData(QSizePolicy::MinimumExpanding); quotationsView->setSizePolicy(sp); quotationsLayout->addWidget(quotationsView); QVBoxLayout *buttonsLayout = new QVBoxLayout(quotationsLayout); quotationEdit = new EqonomizeValueEdit(0.01, INT_MAX / pow(10, KGlobal::locale()->fracDigits()) - 1.0, 1.0, 0.01, KGlobal::locale()->fracDigits(), true, mainWidget()); buttonsLayout->addWidget(quotationEdit); dateEdit = new KDateEdit(mainWidget()); dateEdit->setDate(QDate::currentDate()); buttonsLayout->addWidget(dateEdit); addButton = new QPushButton(i18n("Add"), mainWidget()); buttonsLayout->addWidget(addButton); changeButton = new QPushButton(i18n("Change"), mainWidget()); changeButton->setEnabled(false); buttonsLayout->addWidget(changeButton); deleteButton = new QPushButton(i18n("Delete"), mainWidget()); deleteButton->setEnabled(false); buttonsLayout->addWidget(deleteButton); buttonsLayout->addStretch(1); connect(quotationsView, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); connect(addButton, SIGNAL(clicked()), this, SLOT(addQuotation())); connect(changeButton, SIGNAL(clicked()), this, SLOT(changeQuotation())); connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteQuotation())); } void EditQuotationsDialog::setSecurity(Security *security) { quotationsView->clear(); QMap::const_iterator it_end = security->quotations.end(); for(QMap::const_iterator it = security->quotations.begin(); it != it_end; ++it) { new QuotationListViewItem(it.key(), it.data(), quotationsView, KGlobal::locale()->formatDate(it.key(), true), KGlobal::locale()->formatMoney(it.data())); } titleLabel->setText(i18n("Quotations for %1").arg(security->name())); } void EditQuotationsDialog::modifyQuotations(Security *security) { security->quotations.clear(); QuotationListViewItem *i = (QuotationListViewItem*) quotationsView->firstChild(); while(i) { security->quotations[i->date] = i->value; security->quotations_auto[i->date] = false; i = (QuotationListViewItem*) i->nextSibling(); } } void EditQuotationsDialog::onSelectionChanged() { QuotationListViewItem *i = (QuotationListViewItem*) quotationsView->selectedItem(); if(i) { changeButton->setEnabled(true); deleteButton->setEnabled(true); dateEdit->setDate(i->date); quotationEdit->setValue(i->value); } else { changeButton->setEnabled(false); deleteButton->setEnabled(false); } } void EditQuotationsDialog::addQuotation() { QDate date = dateEdit->date(); if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); return; } QuotationListViewItem *i = (QuotationListViewItem*) quotationsView->firstChild(); while(i) { if(i->date == date) { i->value = quotationEdit->value(); i->setText(1, KGlobal::locale()->formatMoney(i->value)); return; } i = (QuotationListViewItem*) i->nextSibling(); } new QuotationListViewItem(date, quotationEdit->value(), quotationsView, KGlobal::locale()->formatDate(date, true), KGlobal::locale()->formatMoney(quotationEdit->value())); } void EditQuotationsDialog::changeQuotation() { QuotationListViewItem *i = (QuotationListViewItem*) quotationsView->selectedItem(); if(!i) return; QDate date = dateEdit->date(); if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); return; } QuotationListViewItem *i2 = (QuotationListViewItem*) quotationsView->firstChild(); while(i2) { if(i2->date == date) { i2->value = quotationEdit->value(); i2->setText(1, KGlobal::locale()->formatMoney(i2->value)); if(i2 != i) delete i; return; } i2 = (QuotationListViewItem*) i2->nextSibling(); } i->date = date; i->value = quotationEdit->value(); i->setText(0, KGlobal::locale()->formatDate(date, true)); i->setText(1, KGlobal::locale()->formatMoney(i->value)); } void EditQuotationsDialog::deleteQuotation() { QuotationListViewItem *i = (QuotationListViewItem*) quotationsView->selectedItem(); if(i) delete i; } ConfirmScheduleDialog::ConfirmScheduleDialog(bool extra_parameters, Budget *budg, QWidget *parent, QString title) : KDialogBase(parent, 0, true, title, Ok, Ok, true), budget(budg), b_extra(extra_parameters) { setMainWidget(new QWidget(this)); QVBoxLayout *box1 = new QVBoxLayout(mainWidget(), 0, spacingHint()); QLabel *label = new QLabel(i18n("The following transactions was scheduled to occur today or before today.\nConfirm that they have indeed occurred (or will occur today)."), mainWidget()); box1->addWidget(label); QHBoxLayout *box2 = new QHBoxLayout(box1); transactionsView = new KListView(mainWidget()); transactionsView->addColumn(i18n("Date")); transactionsView->addColumn(i18n("Type")); transactionsView->addColumn(i18n("Description")); transactionsView->addColumn(i18n("Amount")); transactionsView->setRootIsDecorated(false); transactionsView->setAllColumnsShowFocus(true); transactionsView->setSorting(0, true); transactionsView->setShowSortIndicator(true); transactionsView->setColumnAlignment(3, Qt::AlignRight); QSizePolicy sp = transactionsView->sizePolicy(); sp.setHorData(QSizePolicy::MinimumExpanding); transactionsView->setSizePolicy(sp); box2->addWidget(transactionsView); KButtonBox *buttons = new KButtonBox(mainWidget(), KButtonBox::Vertical); editButton = buttons->addButton(i18n("Edit...")); editButton->setEnabled(false); postponeButton = buttons->addButton(i18n("Postpone...")); postponeButton->setEnabled(false); #if KDE_VERSION_MAJOR > 3 || KDE_VERSION_MINOR >= 3 removeButton = buttons->addButton(KStdGuiItem::guiItem(KStdGuiItem::Delete)); #else removeButton = buttons->addButton(i18n("Delete")); #endif removeButton->setEnabled(false); box2->addWidget(buttons); buttons->addStretch(); buttons->layout(); connect(transactionsView, SIGNAL(selectionChanged()), this, SLOT(transactionSelectionChanged())); connect(removeButton, SIGNAL(clicked()), this, SLOT(remove())); connect(editButton, SIGNAL(clicked()), this, SLOT(edit())); connect(postponeButton, SIGNAL(clicked()), this, SLOT(postpone())); updateTransactions(); } void ConfirmScheduleDialog::transactionSelectionChanged() { QListViewItem *i = transactionsView->selectedItem(); if(i == NULL) { editButton->setEnabled(false); removeButton->setEnabled(false); postponeButton->setEnabled(false); } else { editButton->setEnabled(true); removeButton->setEnabled(true); postponeButton->setEnabled(true); } } void ConfirmScheduleDialog::remove() { QListViewItem *i = transactionsView->selectedItem(); if(i == NULL) return; Transaction *trans = ((ConfirmScheduleListViewItem*) i)->transaction(); delete trans; delete i; if(transactionsView->childCount() == 0) reject(); } void ConfirmScheduleDialog::postpone() { QListViewItem *i = transactionsView->selectedItem(); if(i == NULL) return; KDialogBase *dialog = new KDialogBase(this, 0, true, i18n("Date"), Ok|Cancel); KDatePicker *datePicker = new KDatePicker(dialog->makeVBoxMainWidget(), KGlobal::locale()->calendar()->addDays(QDate::currentDate(), 1)); if(dialog->exec() == QDialog::Accepted) { if(datePicker->date() > QDate::currentDate()) { Transaction *trans = ((ConfirmScheduleListViewItem*) i)->transaction(); trans->setDate(datePicker->date()); budget->addScheduledTransaction(new ScheduledTransaction(budget, trans, NULL)); delete i; } else { KMessageBox::error(this, i18n("Can only postpone to future dates.")); } } dialog->deleteLater(); if(transactionsView->childCount() == 0) reject(); } void ConfirmScheduleDialog::edit() { QListViewItem *i = transactionsView->selectedItem(); if(i == NULL) return; Transaction *trans = ((ConfirmScheduleListViewItem*) i)->transaction(); Security *security = NULL; if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL) { security = ((SecurityTransaction*) trans)->security(); } else if(trans->type() == TRANSACTION_TYPE_INCOME && ((Income*) trans)->security()) { security = ((Income*) trans)->security(); } TransactionEditDialog *dialog = new TransactionEditDialog(b_extra, trans->type(), false, false, security, SECURITY_ALL_VALUES, security != NULL, budget, this); dialog->editWidget->updateAccounts(); dialog->editWidget->setTransaction(trans); //if(trans->type() == TRANSACTION_TYPE_SECURITY_SELL) dialog->editWidget->setMaxSharesDate(QDate::currentDate()); if(dialog->editWidget->checkAccounts() && dialog->exec() == QDialog::Accepted) { if(dialog->editWidget->modifyTransaction(trans)) { if(trans->date() > QDate::currentDate()) { budget->addScheduledTransaction(new ScheduledTransaction(budget, trans, NULL)); delete i; } else { i->setText(0, KGlobal::locale()->formatDate(trans->date(), true)); switch(trans->type()) { case TRANSACTION_TYPE_TRANSFER: {i->setText(1, i18n("Transfer")); break;} case TRANSACTION_TYPE_INCOME: { if(((Income*) trans)->security()) i->setText(1, i18n("Dividend")); else i->setText(1, i18n("Income")); break;} case TRANSACTION_TYPE_EXPENSE: {i->setText(1, i18n("Expense")); break;} case TRANSACTION_TYPE_SECURITY_BUY: {i->setText(1, i18n("Security Buy")); break;} case TRANSACTION_TYPE_SECURITY_SELL: {i->setText(1, i18n("Security Sell")); break;} } i->setText(2, trans->description()); i->setText(3, KGlobal::locale()->formatMoney(trans->value())); } } } dialog->deleteLater(); if(transactionsView->childCount() == 0) reject(); } void ConfirmScheduleDialog::updateTransactions() { ScheduledTransaction *strans = budget->scheduledTransactions.first(); while(strans) { Transaction *trans = NULL; if(strans->firstOccurrence() < QDate::currentDate() || (QTime::currentTime().hour() >= 18 && strans->firstOccurrence() == QDate::currentDate())) { bool b = strans->isOneTimeTransaction(); trans = strans->realize(strans->firstOccurrence()); if(b) budget->removeScheduledTransaction(strans); strans = budget->scheduledTransactions.first(); } else { strans = budget->scheduledTransactions.next(); } if(trans) { QListViewItem *i = new ConfirmScheduleListViewItem(trans, transactionsView, KGlobal::locale()->formatDate(trans->date(), true), QString::null, trans->description(), KGlobal::locale()->formatMoney(trans->value())); switch(trans->type()) { case TRANSACTION_TYPE_TRANSFER: {i->setText(1, i18n("Transfer")); break;} case TRANSACTION_TYPE_INCOME: { if(((Income*) trans)->security()) i->setText(1, i18n("Dividend")); else i->setText(1, i18n("Income")); break; } case TRANSACTION_TYPE_EXPENSE: {i->setText(1, i18n("Expense")); break;} case TRANSACTION_TYPE_SECURITY_BUY: {i->setText(1, i18n("Security Buy")); break;} case TRANSACTION_TYPE_SECURITY_SELL: {i->setText(1, i18n("Security Sell")); break;} } } } QListViewItem *i = transactionsView->firstChild(); if(i) transactionsView->setSelected(i, true); } Transaction *ConfirmScheduleDialog::firstTransaction() { current_item = (ConfirmScheduleListViewItem*) transactionsView->firstChild(); if(current_item) return current_item->transaction(); return NULL; } Transaction *ConfirmScheduleDialog::nextTransaction() { current_item = (ConfirmScheduleListViewItem*) current_item->nextSibling(); if(current_item) return current_item->transaction(); return NULL; } SecurityTransactionsDialog::SecurityTransactionsDialog(Security *sec, Eqonomize *parent, QString title) : KDialogBase(parent, 0, true, title, Close, Close, true), security(sec), mainWin(parent) { setMainWidget(new QWidget(this)); QVBoxLayout *box1 = new QVBoxLayout(mainWidget(), 0, spacingHint()); box1->addWidget(new QLabel(i18n("Transactions for %1").arg(security->name()), mainWidget())); QHBoxLayout *box2 = new QHBoxLayout(box1); transactionsView = new KListView(mainWidget()); transactionsView->addColumn(i18n("Date")); transactionsView->addColumn(i18n("Type")); transactionsView->addColumn(i18n("Value")); transactionsView->addColumn(i18n("Shares")); transactionsView->setRootIsDecorated(false); transactionsView->setAllColumnsShowFocus(true); transactionsView->setSorting(0, false); transactionsView->setShowSortIndicator(true); transactionsView->setColumnAlignment(2, Qt::AlignRight); transactionsView->setColumnAlignment(3, Qt::AlignRight); QSizePolicy sp = transactionsView->sizePolicy(); sp.setHorData(QSizePolicy::MinimumExpanding); transactionsView->setSizePolicy(sp); box2->addWidget(transactionsView); KButtonBox *buttons = new KButtonBox(mainWidget(), KButtonBox::Vertical); editButton = buttons->addButton(i18n("Edit...")); editButton->setEnabled(false); #if KDE_VERSION_MAJOR > 3 || KDE_VERSION_MINOR >= 3 removeButton = buttons->addButton(KStdGuiItem::guiItem(KStdGuiItem::Delete)); #else removeButton = buttons->addButton(i18n("Delete")); #endif removeButton->setEnabled(false); box2->addWidget(buttons); buttons->addStretch(); buttons->layout(); connect(transactionsView, SIGNAL(selectionChanged()), this, SLOT(transactionSelectionChanged())); connect(transactionsView, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(edit(QListViewItem*))); connect(removeButton, SIGNAL(clicked()), this, SLOT(remove())); connect(editButton, SIGNAL(clicked()), this, SLOT(edit())); updateTransactions(); } void SecurityTransactionsDialog::transactionSelectionChanged() { QListViewItem *i = transactionsView->selectedItem(); if(i == NULL) { editButton->setEnabled(false); removeButton->setEnabled(false); } else { editButton->setEnabled(true); removeButton->setEnabled(true); } } void SecurityTransactionsDialog::remove() { SecurityTransactionListViewItem *i = (SecurityTransactionListViewItem*) transactionsView->selectedItem(); if(i == NULL) return; if(i->trans) { SecurityTransaction *trans = i->trans; security->budget()->removeTransaction(trans, true); mainWin->transactionRemoved(trans); delete trans; } else if(i->div) { Income *div = i->div; security->budget()->removeTransaction(div, true); mainWin->transactionRemoved(div); delete div; } else if(i->rediv) { ReinvestedDividend *rediv = i->rediv; security->reinvestedDividends.removeRef(rediv); mainWin->updateSecurity(security); mainWin->updateSecurityAccount(security->account()); mainWin->setModified(true); } else if(i->strans) { ScheduledTransaction *strans = i->strans; security->budget()->removeScheduledTransaction(strans, true); mainWin->scheduledTransactionRemoved(strans); delete strans; } else if(i->sdiv) { ScheduledTransaction *sdiv = i->sdiv; security->budget()->removeScheduledTransaction(sdiv, true); mainWin->scheduledTransactionRemoved(sdiv); delete sdiv; } else if(i->ts) { SecurityTrade *ts = i->ts; security->budget()->removeSecurityTrade(ts, true); mainWin->updateSecurity(ts->from_security); mainWin->updateSecurity(ts->to_security); mainWin->updateSecurityAccount(ts->from_security->account()); if(ts->to_security->account() != ts->from_security->account()) { mainWin->updateSecurityAccount(ts->to_security->account()); } mainWin->setModified(true); delete ts; } delete i; } void SecurityTransactionsDialog::edit() { edit(transactionsView->selectedItem()); } void SecurityTransactionsDialog::edit(QListViewItem *i_pre) { if(i_pre == NULL) return; SecurityTransactionListViewItem *i = (SecurityTransactionListViewItem*) i_pre; bool b = false; if(i->trans) b = mainWin->editTransaction(i->trans, this); else if(i->div) b = mainWin->editTransaction(i->div, this); else if(i->rediv) b = mainWin->editReinvestedDividend(i->rediv, security, this); else if(i->strans) b = mainWin->editScheduledTransaction(i->strans, this); else if(i->sdiv) b = mainWin->editScheduledTransaction(i->sdiv, this); else if(i->ts) b = mainWin->editSecurityTrade(i->ts, this); if(b) updateTransactions(); } void SecurityTransactionsDialog::updateTransactions() { transactionsView->clear(); SecurityTransaction *trans = security->transactions.first(); while(trans) { SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(trans->date(), true), QString::null, KGlobal::locale()->formatMoney(trans->value()), KGlobal::locale()->formatNumber(trans->shares(), security->decimals())); i->trans = trans; i->date = trans->date(); i->value = trans->value(); i->shares = trans->shares(); if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY) i->setText(1, i18n("Shares Bought")); else i->setText(1, i18n("Shares Sold")); trans = security->transactions.next(); } Income *div = security->dividends.first(); while(div) { SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(div->date(), true), i18n("Dividend"), KGlobal::locale()->formatMoney(div->value()), "-"); i->div = div; i->date = div->date(); i->value = div->value(); div = security->dividends.next(); } ReinvestedDividend *rediv = security->reinvestedDividends.first(); while(rediv) { SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(rediv->date, true), i18n("Reinvested Dividend"), "-", KGlobal::locale()->formatNumber(rediv->shares, security->decimals())); i->rediv = rediv; i->date = rediv->date; i->shares = rediv->shares; rediv = security->reinvestedDividends.next(); } SecurityTrade *ts = security->tradedShares.first(); while(ts) { double shares; if(ts->from_security == security) shares = ts->from_shares; else shares = ts->to_shares; SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(ts->date, true), ts->from_security == security ? i18n("Shares Sold (Traded)") : i18n("Shares Bought (Traded)"), KGlobal::locale()->formatMoney(ts->value), KGlobal::locale()->formatNumber(shares, security->decimals())); i->ts = ts; i->date = ts->date; i->shares = shares; i->value = ts->value; ts = security->tradedShares.next(); } ScheduledTransaction *strans = security->scheduledTransactions.first(); while(strans) { SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(strans->transaction()->date(), true), QString::null, KGlobal::locale()->formatMoney(strans->transaction()->value()), KGlobal::locale()->formatNumber(((SecurityTransaction*) strans->transaction())->shares(), security->decimals())); i->strans = strans; i->date = strans->transaction()->date(); i->value = strans->transaction()->value(); i->shares = ((SecurityTransaction*) strans->transaction())->shares(); if(strans->recurrence()) { if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY) i->setText(1, i18n("Shares Bought (Recurring)")); else i->setText(1, i18n("Shares Sold (Recurring)")); } else { if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY) i->setText(1, i18n("Shares Bought (Scheduled)")); else i->setText(1, i18n("Shares Sold (Scheduled)")); } strans = security->scheduledTransactions.next(); } strans = security->scheduledDividends.first(); while(strans) { SecurityTransactionListViewItem *i = new SecurityTransactionListViewItem(transactionsView, KGlobal::locale()->formatDate(strans->transaction()->date(), true), QString::null, KGlobal::locale()->formatMoney(strans->transaction()->value()), "-"); i->sdiv = strans; i->date = strans->transaction()->date(); i->value = strans->transaction()->value(); if(strans->recurrence()) { i->setText(1, i18n("Recurring Dividend")); } else { i->setText(1, i18n("Scheduled Dividend")); } strans = security->scheduledDividends.next(); } } EditSecurityDialog::EditSecurityDialog(Budget *budg, QWidget *parent, QString title) : KDialogBase(parent, 0, true, title, Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *grid = new QGridLayout(mainWidget(), 9, 2, 0, spacingHint()); grid->addWidget(new QLabel(i18n("Type:"), mainWidget()), 0, 0); typeCombo = new KComboBox(mainWidget()); typeCombo->setEditable(false); typeCombo->insertItem(i18n("Mutual Fund")); typeCombo->insertItem(i18n("Bond")); typeCombo->insertItem(i18n("Stock")); typeCombo->insertItem(i18n("Other")); grid->addWidget(typeCombo, 0, 1); typeCombo->setFocus(); grid->addWidget(new QLabel(i18n("Name:"), mainWidget()), 1, 0); nameEdit = new KLineEdit(mainWidget()); grid->addWidget(nameEdit, 1, 1); grid->addWidget(new QLabel(i18n("Account:"), mainWidget()), 2, 0); accountCombo = new KComboBox(mainWidget()); accountCombo->setEditable(false); AssetsAccount *account = budget->assetsAccounts.first(); while(account) { if(account->accountType() == ASSETS_TYPE_SECURITIES) { accountCombo->insertItem(account->name()); accounts.push_back(account); } account = budget->assetsAccounts.next(); } grid->addWidget(accountCombo, 2, 1); grid->addWidget(new QLabel(i18n("Decimals in Shares:"), mainWidget()), 3, 0); decimalsEdit = new KIntSpinBox(0, 8, 1, 4, 10, mainWidget()); grid->addWidget(decimalsEdit, 3, 1); grid->addWidget(new QLabel(i18n("Initial Shares:"), mainWidget()), 4, 0); sharesEdit = new EqonomizeValueEdit(0.0, 4, false, false, mainWidget()); grid->addWidget(sharesEdit, 4, 1); quotationLabel = new QLabel(i18n("Initial quotation:"), mainWidget()); grid->addWidget(quotationLabel, 5, 0); quotationEdit = new EqonomizeValueEdit(false, mainWidget()); grid->addWidget(quotationEdit, 5, 1); quotationDateLabel = new QLabel(i18n("Date:"), mainWidget()); grid->addWidget(quotationDateLabel, 6, 0); quotationDateEdit = new KDateEdit(mainWidget()); grid->addWidget(quotationDateEdit, 6, 1); grid->addWidget(new QLabel(i18n("Description:"), mainWidget()), 7, 0); descriptionEdit = new KTextEdit(mainWidget()); grid->addMultiCellWidget(descriptionEdit, 8, 8, 0, 1); nameEdit->setFocus(); connect(decimalsEdit, SIGNAL(valueChanged(int)), this, SLOT(decimalsChanged(int))); } bool EditSecurityDialog::checkAccount() { if(accountCombo->count() == 0) { KMessageBox::error(this, i18n("No suitable account or income category available.")); return false; } return true; } void EditSecurityDialog::decimalsChanged(int i) { sharesEdit->setRange(0.0, INT_MAX / pow(10.0, i) - 1, 1.0, i); } Security *EditSecurityDialog::newSecurity() { if(!checkAccount()) return NULL; SecurityType type; switch(typeCombo->currentItem()) { case 1: {type = SECURITY_TYPE_BOND; break;} case 2: {type = SECURITY_TYPE_STOCK; break;} case 3: {type = SECURITY_TYPE_OTHER; break;} default: {type = SECURITY_TYPE_MUTUAL_FUND; break;} } Security *security = new Security(budget, accounts[accountCombo->currentItem()], type, sharesEdit->value(), decimalsEdit->value(), nameEdit->text(), descriptionEdit->text()); if(quotationEdit->value() > 0.0) { security->setQuotation(quotationDateEdit->date(), quotationEdit->value()); } return security; } bool EditSecurityDialog::modifySecurity(Security *security) { if(!checkAccount()) return false; security->setName(nameEdit->text()); security->setInitialShares(sharesEdit->value()); security->setDescription(descriptionEdit->text()); security->setAccount(accounts[accountCombo->currentItem()]); security->setDecimals(decimalsEdit->value()); switch(typeCombo->currentItem()) { case 1: {security->setType(SECURITY_TYPE_BOND); break;} case 2: {security->setType(SECURITY_TYPE_STOCK); break;} case 3: {security->setType(SECURITY_TYPE_OTHER); break;} default: {security->setType(SECURITY_TYPE_MUTUAL_FUND); break;} } return true; } void EditSecurityDialog::setSecurity(Security *security) { nameEdit->setText(security->name()); quotationEdit->hide(); quotationDateEdit->hide(); quotationLabel->hide(); quotationDateLabel->hide(); descriptionEdit->setText(security->description()); decimalsEdit->setValue(security->decimals()); decimalsChanged(security->decimals()); sharesEdit->setValue(security->initialShares()); for(QValueVector::size_type i = 0; i < accounts.size(); i++) { if(security->account() == accounts[i]) { accountCombo->setCurrentItem(i); break; } } switch(security->type()) { case SECURITY_TYPE_BOND: {typeCombo->setCurrentItem(1); break;} case SECURITY_TYPE_STOCK: {typeCombo->setCurrentItem(2); break;} case SECURITY_TYPE_OTHER: {typeCombo->setCurrentItem(3); break;} default: {typeCombo->setCurrentItem(0); break;} } } EditAssetsAccountDialog::EditAssetsAccountDialog(Budget *budg, QWidget *parent, QString title) : KDialogBase(parent, 0, true, title, Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *grid = new QGridLayout(mainWidget(), 6, 2, 0, spacingHint()); grid->addWidget(new QLabel(i18n("Type:"), mainWidget()), 0, 0); typeCombo = new KComboBox(mainWidget()); typeCombo->setEditable(false); typeCombo->insertItem(i18n("Cash")); typeCombo->insertItem(i18n("Current Account")); typeCombo->insertItem(i18n("Savings Account")); typeCombo->insertItem(i18n("Credit Card")); typeCombo->insertItem(i18n("Liabilities")); typeCombo->insertItem(i18n("Securities")); grid->addWidget(typeCombo, 0, 1); grid->addWidget(new QLabel(i18n("Name:"), mainWidget()), 1, 0); nameEdit = new KLineEdit(mainWidget()); grid->addWidget(nameEdit, 1, 1); grid->addWidget(new QLabel(i18n("Initial balance:"), mainWidget()), 2, 0); valueEdit = new EqonomizeValueEdit(true, mainWidget()); grid->addWidget(valueEdit, 2, 1); budgetButton = new QCheckBox(i18n("Default account for budgeted transactions"), mainWidget()); budgetButton->setChecked(false); grid->addMultiCellWidget(budgetButton, 3, 3, 0, 1); grid->addWidget(new QLabel(i18n("Description:"), mainWidget()), 4, 0); descriptionEdit = new KTextEdit(mainWidget()); grid->addMultiCellWidget(descriptionEdit, 5, 5, 0, 1); nameEdit->setFocus(); current_account = NULL; connect(typeCombo, SIGNAL(activated(int)), this, SLOT(typeActivated(int))); } void EditAssetsAccountDialog::typeActivated(int index) { valueEdit->setEnabled(index != 5); budgetButton->setChecked(index == 1); budgetButton->setEnabled(index != 5); } AssetsAccount *EditAssetsAccountDialog::newAccount() { AssetsType type; switch(typeCombo->currentItem()) { case 1: {type = ASSETS_TYPE_CURRENT; break;} case 2: {type = ASSETS_TYPE_SAVINGS; break;} case 3: {type = ASSETS_TYPE_CREDIT_CARD; break;} case 4: {type = ASSETS_TYPE_LIABILITIES; break;} case 5: {type = ASSETS_TYPE_SECURITIES; break;} default: {type = ASSETS_TYPE_CASH; break;} } AssetsAccount *account = new AssetsAccount(budget, type, nameEdit->text(), valueEdit->value(), descriptionEdit->text()); account->setAsBudgetAccount(budgetButton->isChecked()); return account; } void EditAssetsAccountDialog::modifyAccount(AssetsAccount *account) { account->setName(nameEdit->text()); account->setInitialBalance(valueEdit->value()); account->setDescription(descriptionEdit->text()); account->setAsBudgetAccount(budgetButton->isChecked()); switch(typeCombo->currentItem()) { case 1: {account->setAccountType(ASSETS_TYPE_CURRENT); break;} case 2: {account->setAccountType(ASSETS_TYPE_SAVINGS); break;} case 3: {account->setAccountType(ASSETS_TYPE_CREDIT_CARD); break;} case 4: {account->setAccountType(ASSETS_TYPE_LIABILITIES); break;} case 5: {account->setAccountType(ASSETS_TYPE_SECURITIES); break;} default: {account->setAccountType(ASSETS_TYPE_CASH); break;} } } void EditAssetsAccountDialog::setAccount(AssetsAccount *account) { current_account = account; nameEdit->setText(account->name()); valueEdit->setValue(account->initialBalance()); descriptionEdit->setText(account->description()); budgetButton->setChecked(account->isBudgetAccount()); switch(account->accountType()) { case ASSETS_TYPE_CURRENT: {typeCombo->setCurrentItem(1); break;} case ASSETS_TYPE_SAVINGS: {typeCombo->setCurrentItem(2); break;} case ASSETS_TYPE_CREDIT_CARD: {typeCombo->setCurrentItem(3); break;} case ASSETS_TYPE_LIABILITIES: {typeCombo->setCurrentItem(4); break;} case ASSETS_TYPE_SECURITIES: {typeCombo->setCurrentItem(5); break;} default: {typeCombo->setCurrentItem(0); break;} } typeActivated(typeCombo->currentItem()); } void EditAssetsAccountDialog::slotOk() { QString sname = nameEdit->text().stripWhiteSpace(); if(sname.isEmpty()) { nameEdit->setFocus(); KMessageBox::error(this, i18n("Empty name.")); return; } AssetsAccount *aaccount = budget->findAssetsAccount(sname); if(aaccount && aaccount != current_account) { nameEdit->setFocus(); KMessageBox::error(this, i18n("The entered name is used by another account.")); return; } KDialogBase::slotOk(); } EditIncomesAccountDialog::EditIncomesAccountDialog(Budget *budg, QWidget *parent, QString title) : KDialogBase(parent, 0, true, title, Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *grid = new QGridLayout(mainWidget(), 4, 2, 0, spacingHint()); grid->addWidget(new QLabel(i18n("Name:"), mainWidget()), 0, 0); nameEdit = new KLineEdit(mainWidget()); grid->addWidget(nameEdit, 0, 1); budgetButton = new QCheckBox(i18n("Monthly budget:"), mainWidget()); budgetButton->setChecked(false); grid->addWidget(budgetButton, 1, 0); budgetEdit = new EqonomizeValueEdit(false, mainWidget()); budgetEdit->setEnabled(false); grid->addWidget(budgetEdit, 1, 1); grid->addWidget(new QLabel(i18n("Description:"), mainWidget()), 2, 0); descriptionEdit = new KTextEdit(mainWidget()); grid->addMultiCellWidget(descriptionEdit, 3, 3, 0, 1); nameEdit->setFocus(); current_account = NULL; connect(budgetButton, SIGNAL(toggled(bool)), this, SLOT(budgetEnabled(bool))); } IncomesAccount *EditIncomesAccountDialog::newAccount() { IncomesAccount *account = new IncomesAccount(budget, nameEdit->text(), descriptionEdit->text()); if(budgetButton->isChecked()) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); account->setMonthlyBudget(calSys->year(QDate::currentDate()), calSys->month(QDate::currentDate()), budgetEdit->value()); } return account; } void EditIncomesAccountDialog::modifyAccount(IncomesAccount *account) { account->setName(nameEdit->text()); account->setDescription(descriptionEdit->text()); } void EditIncomesAccountDialog::setAccount(IncomesAccount *account) { current_account = account; nameEdit->setText(account->name()); budgetEdit->hide(); budgetButton->hide(); descriptionEdit->setText(account->description()); } void EditIncomesAccountDialog::budgetEnabled(bool b) { budgetEdit->setEnabled(b); } void EditIncomesAccountDialog::slotOk() { QString sname = nameEdit->text().stripWhiteSpace(); if(sname.isEmpty()) { nameEdit->setFocus(); KMessageBox::error(this, i18n("Empty name.")); return; } IncomesAccount *iaccount = budget->findIncomesAccount(sname); if(iaccount && iaccount != current_account) { nameEdit->setFocus(); KMessageBox::error(this, i18n("The entered name is used by another income category.")); return; } KDialogBase::slotOk(); } EditExpensesAccountDialog::EditExpensesAccountDialog(Budget *budg, QWidget *parent, QString title) : KDialogBase(parent, 0, true, title, Ok | Cancel, Ok, true), budget(budg) { setMainWidget(new QWidget(this)); QGridLayout *grid = new QGridLayout(mainWidget(), 4, 2, 0, spacingHint()); grid->addWidget(new QLabel(i18n("Name:"), mainWidget()), 0, 0); nameEdit = new KLineEdit(mainWidget()); grid->addWidget(nameEdit, 0, 1); budgetButton = new QCheckBox(i18n("Monthly budget:"), mainWidget()); budgetButton->setChecked(false); grid->addWidget(budgetButton, 1, 0); budgetEdit = new EqonomizeValueEdit(false, mainWidget()); budgetEdit->setEnabled(false); grid->addWidget(budgetEdit, 1, 1); grid->addWidget(new QLabel(i18n("Description:"), mainWidget()), 2, 0); descriptionEdit = new KTextEdit(mainWidget()); grid->addMultiCellWidget(descriptionEdit, 3, 3, 0, 1); nameEdit->setFocus(); current_account = NULL; connect(budgetButton, SIGNAL(toggled(bool)), this, SLOT(budgetEnabled(bool))); } ExpensesAccount *EditExpensesAccountDialog::newAccount() { ExpensesAccount *account = new ExpensesAccount(budget, nameEdit->text(), descriptionEdit->text()); if(budgetButton->isChecked()) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); account->setMonthlyBudget(calSys->year(QDate::currentDate()), calSys->month(QDate::currentDate()), budgetEdit->value()); } return account; } void EditExpensesAccountDialog::modifyAccount(ExpensesAccount *account) { account->setName(nameEdit->text()); account->setDescription(descriptionEdit->text()); } void EditExpensesAccountDialog::setAccount(ExpensesAccount *account) { current_account = account; nameEdit->setText(account->name()); budgetEdit->hide(); budgetButton->hide(); descriptionEdit->setText(account->description()); } void EditExpensesAccountDialog::budgetEnabled(bool b) { budgetEdit->setEnabled(b); } void EditExpensesAccountDialog::slotOk() { QString sname = nameEdit->text().stripWhiteSpace(); if(sname.isEmpty()) { nameEdit->setFocus(); KMessageBox::error(this, i18n("Empty name.")); return; } ExpensesAccount *eaccount = budget->findExpensesAccount(sname); if(eaccount && eaccount != current_account) { nameEdit->setFocus(); KMessageBox::error(this, i18n("The entered name is used by another expense category.")); return; } KDialogBase::slotOk(); } #define CHANGE_COLUMN 2 #define BUDGET_COLUMN 1 #define VALUE_COLUMN 3 class MinimumWidget : public QWidget { protected: QSize sizeHint() const { return QSize(minimumSizeHint().width(), QWidget::sizeHint().height()); } public: MinimumWidget(QWidget *parent) : QWidget(parent) {} }; class TotalListViewItem : public QListViewItem { public: TotalListViewItem(QListView *parent, QString label1, QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null, QString label5 = QString::null, QString label6 = QString::null, QString label7 = QString::null, QString label8 = QString::null) : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) {} TotalListViewItem(QListView *parent, QListViewItem *after, QString label1, QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null, QString label5 = QString::null, QString label6 = QString::null, QString label7 = QString::null, QString label8 = QString::null) : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) {} void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) { QColorGroup _cg = cg; QListView* lv = listView(); const QPixmap *pm = lv->viewport()->backgroundPixmap(); if (pm && !pm->isNull()) { _cg.setBrush(QColorGroup::Base, QBrush(static_cast< KListView* >(lv)->alternateBackground(), *pm)); QPoint o = p->brushOrigin(); p->setBrushOrigin(o.x()-lv->contentsX(), o.y()-lv->contentsY()); } else { _cg.setColor((lv->viewport()->backgroundMode() == Qt::FixedColor) ? QColorGroup::Background : QColorGroup::Base, static_cast< KListView* >(lv)->alternateBackground()); } QListViewItem::paintCell(p, _cg, column, width, alignment); } }; class AccountsListView : public KListView { public: AccountsListView(QWidget *parent) : KListView(parent) { setMargins(25, 25, 25, 25); } }; Eqonomize::Eqonomize() : KMainWindow(0, "Eqonomize") { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); expenses_budget = 0.0; expenses_budget_diff = 0.0; incomes_budget = 0.0; incomes_budget_diff = 0.0; incomes_accounts_value = 0.0; incomes_accounts_change = 0.0; expenses_accounts_value = 0.0; expenses_accounts_change = 0.0; assets_accounts_value = 0.0; assets_accounts_change = 0.0; total_value = 0.0; total_cost = 0.0; total_profit = 0.0; total_rate = 0.0; partial_budget = false; modified = false; modified_auto_save = false; budget = new Budget(); config = kapp->config(); config->setGroup("General Options"); b_extra = config->readBoolEntry("useExtraProperties", false); int initial_period_pre = config->readNumEntry("initialPeriod", INITIAL_PERIOD_CURRENT_MONTH); if(initial_period_pre < INITIAL_PERIOD_CURRENT_MONTH || initial_period_pre > INITIAL_PERIOD_LAST) initial_period_pre = INITIAL_PERIOD_CURRENT_MONTH; InitialPeriod initial_period = (InitialPeriod) initial_period_pre; prev_cur_date = QDate::currentDate(); QDate curdate = prev_cur_date; bool from_enabled = true; switch(initial_period) { case INITIAL_PERIOD_CURRENT_MONTH: { calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); to_date = curdate; break; } case INITIAL_PERIOD_CURRENT_YEAR: { calSys->setYMD(from_date, calSys->year(curdate), 1, 1); to_date = curdate; break; } case INITIAL_PERIOD_CURRENT_WHOLE_MONTH: { calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); to_date = calSys->addDays(from_date, calSys->daysInMonth(curdate) - 1); break; } case INITIAL_PERIOD_CURRENT_WHOLE_YEAR: { calSys->setYMD(from_date, calSys->year(curdate), 1, 1); to_date = calSys->addDays(from_date, calSys->daysInYear(curdate) - 1); break; } case INITIAL_PERIOD_LAST: { from_date = QDate::fromString(config->readEntry("initialFromDate"), Qt::ISODate); if(!from_date.isValid()) calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); from_enabled = config->readBoolEntry("initialFromDateEnabled"); to_date = QDate::fromString(config->readEntry("initialToDate"), Qt::ISODate); if(!to_date.isValid()) to_date = calSys->addDays(from_date, calSys->daysInMonth(from_date) - 1); break; } } calSys->setYMD(frommonth_begin, calSys->year(from_date), calSys->month(from_date), 1); prevmonth_begin = addMonths(to_date, -1); prevmonth_begin = calSys->addDays(prevmonth_begin, -(calSys->day(prevmonth_begin) - 1)); setAcceptDrops(true); QWidget *w_top = new QWidget(this); setCentralWidget(w_top); QVBoxLayout *topLayout = new QVBoxLayout(w_top, 6, 6); tabs = new KJanusWidget(w_top, 0, KJanusWidget::IconList); topLayout->addWidget(tabs); accounts_page = tabs->addPage(i18n("Accounts"), i18n("Accounts & Categories"), KApplication::kApplication()->iconLoader()->loadIcon("gohome", KIcon::NoGroup, 32)); expenses_page = tabs->addPage(i18n("Expenses"), i18n("Expenses"), KApplication::kApplication()->iconLoader()->loadIcon("back", KIcon::NoGroup, 32)); incomes_page = tabs->addPage(i18n("Incomes"), i18n("Incomes"), KApplication::kApplication()->iconLoader()->loadIcon("forward", KIcon::NoGroup, 32)); transfers_page = tabs->addPage(i18n("Transfers"), i18n("Transfers"), KApplication::kApplication()->iconLoader()->loadIcon("reload", KIcon::NoGroup, 32)); securities_page = tabs->addPage(i18n("Securities"), i18n("Securities"), KApplication::kApplication()->iconLoader()->loadIcon("contents", KIcon::NoGroup, 32)); schedule_page = tabs->addPage(i18n("Schedule"), i18n("Scheduled Transactions"), KApplication::kApplication()->iconLoader()->loadIcon("clock", KIcon::NoGroup, 32)); #if KDE_VERSION_MAJOR > 3 || KDE_VERSION_MINOR >= 4 connect(tabs, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT(onPageChange(QWidget*))); #endif QVBoxLayout *accountsLayout = new QVBoxLayout(accounts_page, 0, 6); QVBoxLayout *accountsLayoutView = new QVBoxLayout(accountsLayout, 0); accountsView = new AccountsListView(accounts_page); accountsView->setAllColumnsShowFocus(true); accountsView->addColumn(i18n("Account / Category")); accountsView->addColumn(i18n("Remaining Budget (%1)").arg(KGlobal::locale()->currencySymbol())); accountsView->addColumn(i18n("Change (%1)").arg(KGlobal::locale()->currencySymbol())); accountsView->addColumn(i18n("Total (%1)").arg(KGlobal::locale()->currencySymbol())); accountsView->setRootIsDecorated(false); accountsView->setColumnAlignment(BUDGET_COLUMN, Qt::AlignRight); accountsView->setColumnAlignment(CHANGE_COLUMN, Qt::AlignRight); accountsView->setColumnAlignment(VALUE_COLUMN, Qt::AlignRight); accountsView->setSorting(-1); accountsView->header()->setClickEnabled(false); QSizePolicy sp = accountsView->sizePolicy(); sp.setVerData(QSizePolicy::MinimumExpanding); accountsView->setSizePolicy(sp); QFontMetrics fm(accountsView->font()); int w = fm.width(i18n("%2 remains of %1 budget", "%2 of %1").arg(KGlobal::locale()->formatNumber(10000.0, KGlobal::locale()->fracDigits())).arg(KGlobal::locale()->formatNumber(100000.0, KGlobal::locale()->fracDigits()))); if(accountsView->columnWidth(BUDGET_COLUMN) < w) accountsView->setColumnWidth(BUDGET_COLUMN, w); w = fm.width(KGlobal::locale()->formatNumber(999999999.99, KGlobal::locale()->fracDigits())); if(accountsView->columnWidth(CHANGE_COLUMN) < w) accountsView->setColumnWidth(CHANGE_COLUMN, w); w = fm.width(KGlobal::locale()->formatNumber(999999999.99, KGlobal::locale()->fracDigits()) + " "); if(accountsView->columnWidth(VALUE_COLUMN) < w) accountsView->setColumnWidth(VALUE_COLUMN, w); w = fm.width(i18n("Account / Category")); if(accountsView->columnWidth(0) < w) accountsView->setColumnWidth(0, w); accountsView->header()->setStretchEnabled(true, 0); assetsItem = new TotalListViewItem(accountsView, i18n("Accounts"), QString::null, KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()) + " "); incomesItem = new TotalListViewItem(accountsView, assetsItem, i18n("Incomes"), "-", KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()) + " "); expensesItem = new TotalListViewItem(accountsView, incomesItem, i18n("Expenses"), "-", KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()) + " "); accountsLayoutView->addWidget(accountsView); QHBoxLayout *accountsLayoutFooter = new QHBoxLayout(accountsLayoutView, 0, 0); accountsLayoutFooter->addStretch(1); footer1 = new QLabel(QString("* ") + i18n("Includes budgeted transactions"), accounts_page); accountsLayoutFooter->addWidget(footer1); footer1->hide(); #if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2 accountsTabs = new QTabWidget(accounts_page); #else accountsTabs = new KTabWidget(accounts_page); #endif accountsTabs->setMargin(12); accountsTabs->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); QWidget *periodWidget = new QWidget(accounts_page); accountsTabs->addTab(periodWidget, i18n("Period")); QVBoxLayout *accountsPeriodLayout = new QVBoxLayout(periodWidget, 0, 6); QHBoxLayout *accountsPeriodLayout2 = new QHBoxLayout(accountsPeriodLayout); accountsPeriodFromButton = new QCheckBox(i18n("From"), periodWidget); accountsPeriodFromButton->setChecked(from_enabled); accountsPeriodLayout2->addWidget(accountsPeriodFromButton); accountsPeriodFromEdit = new KDateEdit(periodWidget); accountsPeriodFromEdit->setDate(from_date); accountsPeriodFromEdit->setEnabled(true); sp = accountsPeriodFromEdit->sizePolicy(); sp.setHorData(QSizePolicy::Expanding); accountsPeriodFromEdit->setSizePolicy(sp); accountsPeriodLayout2->addWidget(accountsPeriodFromEdit); accountsPeriodLayout2->addWidget(new QLabel(i18n("To"), periodWidget)); accountsPeriodToEdit = new KDateEdit(periodWidget); accountsPeriodToEdit->setDate(to_date); accountsPeriodToEdit->setEnabled(true); accountsPeriodToEdit->setSizePolicy(sp); accountsPeriodLayout2->addWidget(accountsPeriodToEdit); QHBoxLayout *accountsPeriodLayout3 = new QHBoxLayout(accountsPeriodLayout); QPushButton *prevYearButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("2leftarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); accountsPeriodLayout2->addWidget(prevYearButton); QPushButton *prevMonthButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("1leftarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); accountsPeriodLayout2->addWidget(prevMonthButton); QPushButton *nextMonthButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("1rightarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); accountsPeriodLayout2->addWidget(nextMonthButton); QPushButton *nextYearButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("2rightarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); accountsPeriodLayout2->addWidget(nextYearButton); QPushButton *accountsPeriodButton = new KPushButton(i18n("Select Period"), periodWidget); QPopupMenu *accountsPeriodMenu = new QPopupMenu(this); accountsPeriodMenu->insertItem(i18n("Current Month"), 1); accountsPeriodMenu->insertItem(i18n("Current Year"), 2); accountsPeriodMenu->insertItem(i18n("Current Whole Month"), 3); accountsPeriodMenu->insertItem(i18n("Current Whole Year"), 4); accountsPeriodMenu->insertItem(i18n("Whole Past Month"), 5); accountsPeriodMenu->insertItem(i18n("Whole Past Year"), 6); accountsPeriodMenu->insertItem(i18n("Previous Month"), 7); accountsPeriodMenu->insertItem(i18n("Previous Year"), 8); accountsPeriodButton->setPopup(accountsPeriodMenu); accountsPeriodLayout3->addWidget(accountsPeriodButton); partialBudgetButton = new QCheckBox(i18n("Show partial budget"), periodWidget); accountsPeriodLayout3->addWidget(partialBudgetButton); accountsPeriodLayout3->addStretch(1); QWidget *budgetWidget = new QWidget(accounts_page); accountsTabs->addTab(budgetWidget, i18n("Edit Budget")); QVBoxLayout *budgetLayout = new QVBoxLayout(budgetWidget, 0, 6); QHBoxLayout *budgetLayout2 = new QHBoxLayout(budgetLayout); budgetButton = new QCheckBox(i18n("Budget:"), budgetWidget); budgetButton->setChecked(false); budgetLayout2->addWidget(budgetButton); budgetEdit = new EqonomizeValueEdit(false, budgetWidget); budgetEdit->setEnabled(false); sp = budgetEdit->sizePolicy(); sp.setHorData(QSizePolicy::Expanding); budgetEdit->setSizePolicy(sp); budgetEdit->setFocus(); budgetLayout2->addWidget(budgetEdit); budgetLayout2->addWidget(new QLabel(i18n("Month:"), budgetWidget)); budgetMonthEdit = new EqonomizeMonthSelector(budgetWidget); sp = budgetMonthEdit->sizePolicy(); sp.setHorData(QSizePolicy::Expanding); budgetMonthEdit->setSizePolicy(sp); budgetLayout2->addWidget(budgetMonthEdit); QHBoxLayout *budgetLayout3 = new QHBoxLayout(budgetLayout); budgetLayout3->addWidget(new QLabel(i18n("Result previous month:"), budgetWidget)); prevMonthBudgetLabel = new QLabel("-", budgetWidget); budgetLayout3->addWidget(prevMonthBudgetLabel); budgetLayout3->addStretch(1); accountsLayout->addWidget(accountsTabs); accountPopupMenu = NULL; connect(budgetMonthEdit, SIGNAL(dateChanged(const QDate&)), this, SLOT(budgetMonthChanged(const QDate&))); connect(budgetEdit, SIGNAL(valueChanged(double)), this, SLOT(budgetChanged(double))); connect(budgetEdit, SIGNAL(returnPressed()), this, SLOT(budgetEditReturnPressed())); connect(budgetButton, SIGNAL(toggled(bool)), this, SLOT(budgetToggled(bool))); connect(budgetButton, SIGNAL(toggled(bool)), budgetEdit, SLOT(setEnabled(bool))); connect(partialBudgetButton, SIGNAL(toggled(bool)), this, SLOT(setPartialBudget(bool))); connect(accountsPeriodMenu, SIGNAL(activated(int)), this, SLOT(periodSelected(int))); connect(prevMonthButton, SIGNAL(clicked()), this, SLOT(prevMonth())); connect(nextMonthButton, SIGNAL(clicked()), this, SLOT(nextMonth())); connect(prevYearButton, SIGNAL(clicked()), this, SLOT(prevYear())); connect(nextYearButton, SIGNAL(clicked()), this, SLOT(nextYear())); connect(accountsPeriodFromButton, SIGNAL(toggled(bool)), accountsPeriodFromEdit, SLOT(setEnabled(bool))); connect(accountsPeriodFromButton, SIGNAL(toggled(bool)), this, SLOT(filterAccounts())); connect(accountsPeriodFromEdit, SIGNAL(dateChanged(const QDate&)), this, SLOT(accountsPeriodFromChanged(const QDate&))); connect(accountsPeriodToEdit, SIGNAL(dateChanged(const QDate&)), this, SLOT(accountsPeriodToChanged(const QDate&))); connect(accountsView, SIGNAL(selectionChanged()), this, SLOT(accountsSelectionChanged())); connect(accountsView, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(accountExecuted(QListViewItem*, const QPoint&, int))); connect(accountsView, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(accountExecuted(QListViewItem*))); connect(accountsView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(popupAccountsMenu(KListView*, QListViewItem*, const QPoint&))); expensesLayout = new QVBoxLayout(expenses_page, 0, 6); expensesWidget = new TransactionListWidget(b_extra, TRANSACTION_TYPE_EXPENSE, budget, this, expenses_page); expensesLayout->addWidget(expensesWidget); incomesLayout = new QVBoxLayout(incomes_page, 0, 6); incomesWidget = new TransactionListWidget(b_extra, TRANSACTION_TYPE_INCOME, budget, this, incomes_page); incomesLayout->addWidget(incomesWidget); transfersLayout = new QVBoxLayout(transfers_page, 0, 6); transfersWidget = new TransactionListWidget(b_extra, TRANSACTION_TYPE_TRANSFER, budget, this, transfers_page); transfersLayout->addWidget(transfersWidget); QWidget *securities_page_bak = securities_page; QVBoxLayout *securitiesLayout_pre = new QVBoxLayout(securities_page, 0, 0); securities_page = new MinimumWidget(securities_page); securitiesLayout_pre->addWidget(securities_page); QVBoxLayout *securitiesLayout = new QVBoxLayout(securities_page, 0, 6); KButtonBox *securitiesButtons = new KButtonBox(securities_page); newSecurityButton = securitiesButtons->addButton(i18n("New Security...")); newSecurityButton->setEnabled(true); newSecurityTransactionButton = securitiesButtons->addButton(i18n("New Transaction")); QPopupMenu *newSecurityTransactionMenu = new QPopupMenu(this); newSecurityTransactionButton->setPopup(newSecurityTransactionMenu); setQuotationButton = securitiesButtons->addButton(i18n("Set Quotation...")); setQuotationButton->setEnabled(false); securitiesButtons->layout(); securitiesLayout->addWidget(securitiesButtons); QVBoxLayout *securitiesViewLayout = new QVBoxLayout(securitiesLayout, 2); securitiesView = new KListView(securities_page); securitiesView->addColumn(i18n("Name")); securitiesView->addColumn(i18n("Value")); securitiesView->addColumn(i18n("Shares")); securitiesView->addColumn(i18n("Quotation")); securitiesView->addColumn(i18n("Cost")); securitiesView->addColumn(i18n("Profit")); securitiesView->addColumn(i18n("Yearly Rate")); securitiesView->addColumn(i18n("Type")); securitiesView->addColumn(i18n("Account")); securitiesView->setRootIsDecorated(false); securitiesView->setAllColumnsShowFocus(true); securitiesView->setSorting(0, true); securitiesView->setShowSortIndicator(true); securitiesView->setColumnAlignment(1, Qt::AlignRight); securitiesView->setColumnAlignment(2, Qt::AlignRight); securitiesView->setColumnAlignment(3, Qt::AlignRight); securitiesView->setColumnAlignment(4, Qt::AlignRight); securitiesView->setColumnAlignment(5, Qt::AlignRight); securitiesView->setColumnAlignment(6, Qt::AlignRight); securitiesView->setColumnAlignment(7, Qt::AlignCenter); securitiesView->setColumnAlignment(8, Qt::AlignCenter); sp = securitiesView->sizePolicy(); sp.setVerData(QSizePolicy::MinimumExpanding); securitiesView->setSizePolicy(sp); securitiesViewLayout->addWidget(securitiesView); securitiesStatLabel = new QLabel(securities_page); securitiesViewLayout->addWidget(securitiesStatLabel); QGroupBox *periodGroup = new QGroupBox(1, Qt::Horizontal, i18n("Statistics Period"), securities_page); periodWidget = new QWidget(periodGroup); QVBoxLayout *securitiesPeriodLayout = new QVBoxLayout(periodWidget, 0, 6); QHBoxLayout *securitiesPeriodLayout2 = new QHBoxLayout(securitiesPeriodLayout); securitiesPeriodFromButton = new QCheckBox(i18n("From"), periodWidget); securitiesPeriodFromButton->setChecked(false); securitiesPeriodLayout2->addWidget(securitiesPeriodFromButton); securitiesPeriodFromEdit = new KDateEdit(periodWidget); calSys->setYMD(securities_from_date, calSys->year(curdate), 1, 1); securitiesPeriodFromEdit->setDate(securities_from_date); securitiesPeriodFromEdit->setEnabled(false); sp = securitiesPeriodFromEdit->sizePolicy(); sp.setHorData(QSizePolicy::Expanding); securitiesPeriodFromEdit->setSizePolicy(sp); securitiesPeriodLayout2->addWidget(securitiesPeriodFromEdit); securitiesPeriodLayout2->addWidget(new QLabel(i18n("To"), periodWidget)); securitiesPeriodToEdit = new KDateEdit(periodWidget); securities_to_date = curdate; securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodToEdit->setEnabled(true); securitiesPeriodToEdit->setSizePolicy(sp); securitiesPeriodLayout2->addWidget(securitiesPeriodToEdit); securitiesLayout->addWidget(periodGroup); QHBoxLayout *securitiesPeriodLayout3 = new QHBoxLayout(securitiesPeriodLayout2); QPushButton *securitiesPrevYearButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("2leftarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); securitiesPeriodLayout3->addWidget(securitiesPrevYearButton); QPushButton *securitiesPrevMonthButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("1leftarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); securitiesPeriodLayout3->addWidget(securitiesPrevMonthButton); QPushButton *securitiesNextMonthButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("1rightarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); securitiesPeriodLayout3->addWidget(securitiesNextMonthButton); QPushButton *securitiesNextYearButton = new KPushButton(KApplication::kApplication()->iconLoader()->loadIconSet("2rightarrow", KIcon::Small, KIcon::SizeSmall), "", periodWidget); securitiesPeriodLayout3->addWidget(securitiesNextYearButton); securities_page = securities_page_bak; securitiesPopupMenu = NULL; updateSecuritiesStatistics(); connect(securitiesPrevMonthButton, SIGNAL(clicked()), this, SLOT(securitiesPrevMonth())); connect(securitiesNextMonthButton, SIGNAL(clicked()), this, SLOT(securitiesNextMonth())); connect(securitiesPrevYearButton, SIGNAL(clicked()), this, SLOT(securitiesPrevYear())); connect(securitiesNextYearButton, SIGNAL(clicked()), this, SLOT(securitiesNextYear())); connect(securitiesPeriodFromButton, SIGNAL(toggled(bool)), securitiesPeriodFromEdit, SLOT(setEnabled(bool))); connect(securitiesPeriodFromButton, SIGNAL(toggled(bool)), this, SLOT(updateSecurities())); connect(securitiesPeriodFromEdit, SIGNAL(dateChanged(const QDate&)), this, SLOT(securitiesPeriodFromChanged(const QDate&))); connect(securitiesPeriodToEdit, SIGNAL(dateChanged(const QDate&)), this, SLOT(securitiesPeriodToChanged(const QDate&))); connect(newSecurityButton, SIGNAL(clicked()), this, SLOT(newSecurity())); connect(setQuotationButton, SIGNAL(clicked()), this, SLOT(setQuotation())); connect(securitiesView, SIGNAL(selectionChanged()), this, SLOT(securitiesSelectionChanged())); connect(securitiesView, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(securitiesExecuted(QListViewItem*, const QPoint&, int))); connect(securitiesView, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(securitiesExecuted(QListViewItem*))); connect(securitiesView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(popupSecuritiesMenu(KListView*, QListViewItem*, const QPoint&))); QVBoxLayout *scheduleLayout = new QVBoxLayout(schedule_page, 0, 6); KButtonBox *scheduleButtons = new KButtonBox(schedule_page); newScheduleButton = scheduleButtons->addButton(i18n("New Schedule")); QPopupMenu *newScheduleMenu = new QPopupMenu(this); newScheduleButton->setPopup(newScheduleMenu); editScheduleButton = scheduleButtons->addButton(i18n("Edit")); editScheduleMenu = new QPopupMenu(this); editScheduleButton->setPopup(editScheduleMenu); editScheduleButton->setEnabled(false); removeScheduleButton = scheduleButtons->addButton(i18n("Remove")); removeScheduleMenu = new QPopupMenu(this); removeScheduleButton->setPopup(removeScheduleMenu); removeScheduleButton->setEnabled(false); scheduleButtons->layout(); scheduleLayout->addWidget(scheduleButtons); scheduleView = new KListView(schedule_page); scheduleView->addColumn(i18n("Next Occurrence")); scheduleView->addColumn(i18n("Type")); scheduleView->addColumn(i18n("Description")); scheduleView->addColumn(i18n("Amount")); scheduleView->addColumn(i18n("From")); scheduleView->addColumn(i18n("To")); scheduleView->addColumn(i18n("Comments")); scheduleView->setRootIsDecorated(false); scheduleView->setAllColumnsShowFocus(true); scheduleView->setSorting(0, true); scheduleView->setShowSortIndicator(true); scheduleView->setColumnAlignment(3, Qt::AlignRight); scheduleView->setColumnAlignment(4, Qt::AlignCenter); scheduleView->setColumnAlignment(5, Qt::AlignCenter); sp = scheduleView->sizePolicy(); sp.setVerData(QSizePolicy::MinimumExpanding); scheduleView->setSizePolicy(sp); scheduleLayout->addWidget(scheduleView); schedulePopupMenu = NULL; connect(scheduleView, SIGNAL(selectionChanged()), this, SLOT(scheduleSelectionChanged())); connect(scheduleView, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), this, SLOT(scheduleExecuted(QListViewItem*))); connect(scheduleView, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(scheduleExecuted(QListViewItem*))); connect(scheduleView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(popupScheduleMenu(KListView*, QListViewItem*, const QPoint&))); connect(scheduleView, SIGNAL(selectionChanged()), this, SLOT(updateTransactionActions())); setupActions(); ActionSelectInitialPeriod->setCurrentItem(initial_period_pre); ActionNewExpense->plug(newScheduleMenu); ActionNewIncome->plug(newScheduleMenu); ActionNewTransfer->plug(newScheduleMenu); editScheduleMenu->insertItem(ActionEditScheduledTransaction->iconSet(), i18n("Edit Schedule..."), this, SLOT(editScheduledTransaction()), 0, 0); editScheduleMenu->insertItem(ActionEditTransaction->iconSet(), i18n("Edit Occurrence..."), this, SLOT(editOccurrence()), 0, 1); removeScheduleMenu->insertItem(ActionDeleteScheduledTransaction->iconSet(), i18n("Delete Schedule"), this, SLOT(removeScheduledTransaction()), 0, 0); removeScheduleMenu->insertItem(ActionDeleteTransaction->iconSet(), i18n("Remove Occurrence"), this, SLOT(removeOccurrence()), 0, 1); ActionBuyShares->plug(newSecurityTransactionMenu); ActionSellShares->plug(newSecurityTransactionMenu); ActionNewSecurityTrade->plug(newSecurityTransactionMenu); ActionNewDividend->plug(newSecurityTransactionMenu); ActionNewReinvestedDividend->plug(newSecurityTransactionMenu); #if KDE_VERSION_MAJOR > 3 || KDE_VERSION_MINOR >= 3 setupGUI(ToolBar | Keys | Save | Create); #else setStandardToolBarMenuEnabled(true); createGUI(); if(initialGeometrySet()) { // Do nothing... } else if(!isShown()) { adjustSize(); } setAutoSaveSettings(); #endif readOptions(); QDesktopWidget desktop; if(first_run && !initialGeometrySet()) { resize(QSize(750, 650).boundedTo(desktop.availableGeometry(this).size())); } QTimer *scheduleTimer = new QTimer(); connect(scheduleTimer, SIGNAL(timeout()), this, SLOT(checkSchedule())); scheduleTimer->start(1000 * 60 * 30); auto_save_timeout = true; QTimer *autoSaveTimer = new QTimer(); connect(autoSaveTimer, SIGNAL(timeout()), this, SLOT(onAutoSaveTimeout())); autoSaveTimer->start(1000 * 60 * 1); QTimer *dateTimer = new QTimer(); connect(dateTimer, SIGNAL(timeout()), this, SLOT(checkDate())); dateTimer->start(1000 * 60); current_page = tabs->activePageIndex(); #if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 4 QTimer *pageCheckTimer = new QTimer(); connect(pageCheckTimer, SIGNAL(timeout()), this, SLOT(checkForPageChange())); pageCheckTimer->start(100); #endif } Eqonomize::~Eqonomize() {} void Eqonomize::useExtraProperties(bool b) { b_extra = b; delete expensesWidget; expensesWidget = new TransactionListWidget(b_extra, TRANSACTION_TYPE_EXPENSE, budget, this, expenses_page); expensesLayout->addWidget(expensesWidget); expensesWidget->updateAccounts(); expensesWidget->transactionsReset(); if(tabs->activePageIndex() == 1) { expensesWidget->onDisplay(); updateTransactionActions(); } expensesWidget->show(); delete incomesWidget; incomesWidget = new TransactionListWidget(b_extra, TRANSACTION_TYPE_INCOME, budget, this, incomes_page); incomesLayout->addWidget(incomesWidget); incomesWidget->updateAccounts(); incomesWidget->transactionsReset(); if(tabs->activePageIndex() == 2) { incomesWidget->onDisplay(); updateTransactionActions(); } incomesWidget->show(); } void Eqonomize::checkDate() { if(QDate::currentDate() != prev_cur_date) { QDate prev_cur_date_bak = prev_cur_date; prev_cur_date = QDate::currentDate(); if(to_date == prev_cur_date_bak) { accountsPeriodToEdit->setDate(prev_cur_date); accountsPeriodToChanged(prev_cur_date); } if(securities_to_date == prev_cur_date_bak) { securitiesPeriodToEdit->setDate(prev_cur_date); securitiesPeriodToChanged(prev_cur_date); } expensesWidget->currentDateChanged(prev_cur_date_bak, prev_cur_date); incomesWidget->currentDateChanged(prev_cur_date_bak, prev_cur_date); transfersWidget->currentDateChanged(prev_cur_date_bak, prev_cur_date); } } void Eqonomize::showExpenses() { tabs->showPage(1); onPageChange(expenses_page); } void Eqonomize::showIncomes() { tabs->showPage(2); onPageChange(incomes_page); } void Eqonomize::showTransfers() { tabs->showPage(3); onPageChange(transfers_page); } void Eqonomize::setPartialBudget(bool b) { partial_budget = b; filterAccounts(); } void Eqonomize::budgetEditReturnPressed() { QListViewItem *i = accountsView->selectedItem(); if(!i) return; i = i->nextSibling(); if(!i && account_items.contains(i) && account_items[i]->type() == ACCOUNT_TYPE_INCOMES) i = expensesItem->firstChild(); if(i) { accountsView->setSelected(i, true); if(budgetEdit->isEnabled()) budgetEdit->lineEdit()->selectAll(); else budgetButton->setFocus(); } } void Eqonomize::budgetMonthChanged(const QDate &date) { accountsPeriodFromEdit->blockSignals(true); accountsPeriodFromButton->blockSignals(true); accountsPeriodToEdit->blockSignals(true); const KCalendarSystem *calSys = KGlobal::locale()->calendar(); from_date = date; to_date = calSys->addDays(from_date, calSys->daysInMonth(from_date) - 1); accountsPeriodFromButton->setChecked(true); accountsPeriodFromEdit->setDate(from_date); accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodFromButton->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::budgetChanged(double value) { QListViewItem *i = accountsView->selectedItem(); if(!account_items.contains(i)) return; Account *account = account_items[i]; if(account->type() == ACCOUNT_TYPE_ASSETS) return; CategoryAccount *ca = (CategoryAccount*) account; QDate month = budgetMonthEdit->date(); ca->mbudgets[month] = value; ca = budget->incomesAccounts.first(); while(ca) { if(!ca->mbudgets.contains(month)) { value = ca->monthlyBudget(month); ca->mbudgets[month] = value; } ca = budget->incomesAccounts.next(); } ca = budget->expensesAccounts.first(); while(ca) { if(!ca->mbudgets.contains(month)) { value = ca->monthlyBudget(month); ca->mbudgets[month] = value; } ca = budget->expensesAccounts.next(); } setModified(true); filterAccounts(); } void Eqonomize::budgetToggled(bool b) { QListViewItem *i = accountsView->selectedItem(); if(!account_items.contains(i)) return; Account *account = account_items[i]; if(account->type() == ACCOUNT_TYPE_ASSETS) return; CategoryAccount *ca = (CategoryAccount*) account; QDate month = budgetMonthEdit->date(); if(b) ca->mbudgets[month] = budgetEdit->value(); else ca->mbudgets[month] = -1; ca = budget->incomesAccounts.first(); while(ca) { if(!ca->mbudgets.contains(month)) { double value = ca->monthlyBudget(month); ca->mbudgets[month] = value; } ca = budget->incomesAccounts.next(); } ca = budget->expensesAccounts.first(); while(ca) { if(!ca->mbudgets.contains(month)) { double value = ca->monthlyBudget(month); ca->mbudgets[month] = value; } ca = budget->expensesAccounts.next(); } setModified(true); filterAccounts(); } void Eqonomize::periodSelected(int index) { accountsPeriodFromEdit->blockSignals(true); accountsPeriodFromButton->blockSignals(true); accountsPeriodToEdit->blockSignals(true); const KCalendarSystem *calSys = KGlobal::locale()->calendar(); QDate curdate = QDate::currentDate(); switch(index) { case 1: { calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); to_date = curdate; break; } case 2: { calSys->setYMD(from_date, calSys->year(curdate), 1, 1); to_date = curdate; break; } case 3: { calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); to_date = calSys->addDays(from_date, calSys->daysInMonth(curdate) - 1); break; } case 4: { calSys->setYMD(from_date, calSys->year(curdate), 1, 1); to_date = calSys->addDays(from_date, calSys->daysInYear(curdate) - 1); break; } case 5: { to_date = curdate; from_date = calSys->addDays(addMonths(to_date, -1), 1); break; } case 6: { to_date = curdate; from_date = calSys->addDays(addYears(to_date, -1), 1); break; } case 7: { curdate = addMonths(curdate, -1); calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); to_date = calSys->addDays(from_date, calSys->daysInMonth(curdate) - 1); break; } case 8: { curdate = addYears(curdate, -1); calSys->setYMD(from_date, calSys->year(curdate), 1, 1); to_date = calSys->addDays(from_date, calSys->daysInYear(curdate) - 1); break; } } accountsPeriodFromButton->setChecked(true); accountsPeriodFromEdit->setEnabled(true); accountsPeriodFromEdit->setDate(from_date); accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodFromButton->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::checkForPageChange() { if(tabs->activePageIndex() != current_page) { current_page = tabs->activePageIndex(); switch(current_page) { case 0: {onPageChange(accounts_page); break;} case 1: {onPageChange(expenses_page); break;} case 2: {onPageChange(incomes_page); break;} case 3: {onPageChange(transfers_page); break;} case 4: {onPageChange(securities_page); break;} case 5: {onPageChange(schedule_page); break;} } } } void Eqonomize::newSecurity() { EditSecurityDialog *dialog = new EditSecurityDialog(budget, this, i18n("New Security")); if(dialog->checkAccount() && dialog->exec() == QDialog::Accepted) { Security *security = dialog->newSecurity(); if(security) { budget->addSecurity(security); appendSecurity(security); updateSecurityAccount(security->account()); setModified(true); } } dialog->deleteLater(); } void Eqonomize::editSecurity(QListViewItem *i) { if(!i) return; Security *security = ((SecurityListViewItem*) i)->security(); EditSecurityDialog *dialog = new EditSecurityDialog(budget, this, i18n("Edit Security")); dialog->setSecurity(security); if(dialog->checkAccount() && dialog->exec() == QDialog::Accepted) { if(dialog->modifySecurity(security)) { updateSecurity(i); updateSecurityAccount(security->account()); setModified(true); incomesWidget->filterTransactions(); transfersWidget->filterTransactions(); } } dialog->deleteLater(); } void Eqonomize::editSecurity() { QListViewItem *i = securitiesView->selectedItem(); if(i == NULL) return; editSecurity(i); } void Eqonomize::updateSecuritiesStatistics() { securitiesStatLabel->setText(QString("
%1 %5   %2 %6   %3 %7   %4 %8\%
").arg(i18n("Total value:")).arg(i18n("Cost:")).arg(i18n("Profit:")).arg(i18n("Rate:")).arg(KGlobal::locale()->formatMoney(total_value)).arg(KGlobal::locale()->formatMoney(total_cost)).arg(KGlobal::locale()->formatMoney(total_profit)).arg(KGlobal::locale()->formatNumber(total_rate * 100))); } void Eqonomize::deleteSecurity() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); if(i == NULL) return; Security *security = i->security(); bool has_trans = budget->securityHasTransactions(security); if(!has_trans || KMessageBox::warningContinueCancel(this, i18n("Are you sure you want to delete the security \"%1\" and all associated transactions?").arg(security->name())) == KMessageBox::Continue) { total_value -= i->value; total_rate *= total_cost; total_cost -= i->cost; total_rate -= i->cost * i->rate; if(total_cost != 0.0) total_rate /= total_cost; total_profit -= i->profit; updateSecuritiesStatistics(); delete i; budget->removeSecurity(security); if(has_trans) { filterAccounts(); updateScheduledTransactions(); expensesWidget->filterTransactions(); incomesWidget->filterTransactions(); transfersWidget->filterTransactions(); emit transactionsModified(); } else { updateSecurityAccount(security->account()); } setModified(true); } } void Eqonomize::buySecurities() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); newScheduledTransaction(TRANSACTION_TYPE_SECURITY_BUY, i == NULL ? NULL : i->security(), true); } void Eqonomize::sellSecurities() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); newScheduledTransaction(TRANSACTION_TYPE_SECURITY_SELL, i == NULL ? NULL : i->security(), true); } void Eqonomize::newDividend() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); newScheduledTransaction(TRANSACTION_TYPE_INCOME, i == NULL ? NULL : i->security(), true); } void Eqonomize::editReinvestedDividend(ReinvestedDividend *rediv, Security *security) { editReinvestedDividend(rediv, security, this); } bool Eqonomize::editReinvestedDividend(ReinvestedDividend *rediv, Security *security, QWidget *parent) { EditReinvestedDividendDialog *dialog = new EditReinvestedDividendDialog(budget, security, true, parent); dialog->setDividend(rediv); if(dialog->exec() == QDialog::Accepted) { if(dialog->modifyDividend(rediv)) { security->reinvestedDividends.setAutoDelete(false); security->reinvestedDividends.removeRef(rediv); security->reinvestedDividends.setAutoDelete(true); updateSecurity(security); updateSecurityAccount(security->account()); security = dialog->selectedSecurity(); security->reinvestedDividends.inSort(rediv); updateSecurity(security); updateSecurityAccount(security->account()); setModified(true); dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } void Eqonomize::newReinvestedDividend() { if(budget->securities.count() == 0) { KMessageBox::error(this, i18n("No security available.")); return; } SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); Security *security = NULL; if(i) security = i->security(); EditReinvestedDividendDialog *dialog = new EditReinvestedDividendDialog(budget, security, true, this); if(dialog->exec() == QDialog::Accepted) { ReinvestedDividend *rediv = dialog->createDividend(); if(rediv) { security = dialog->selectedSecurity(); security->reinvestedDividends.inSort(rediv); updateSecurity(security); updateSecurityAccount(security->account()); setModified(true); } } dialog->deleteLater(); } void Eqonomize::editSecurityTrade(SecurityTrade *ts) { editSecurityTrade(ts, this); } bool Eqonomize::editSecurityTrade(SecurityTrade *ts, QWidget *parent) { EditSecurityTradeDialog *dialog = new EditSecurityTradeDialog(budget, ts->from_security, parent); dialog->setSecurityTrade(ts); if(dialog->exec() == QDialog::Accepted) { SecurityTrade *ts_new = dialog->createSecurityTrade(); if(ts_new) { budget->removeSecurityTrade(ts, true); budget->addSecurityTrade(ts_new); updateSecurity(ts_new->from_security); updateSecurity(ts_new->to_security); if(ts->to_security != ts_new->to_security) updateSecurity(ts->to_security); if(ts->from_security != ts_new->from_security) updateSecurity(ts->from_security); updateSecurityAccount(ts_new->from_security->account()); if(ts_new->to_security->account() != ts_new->from_security->account()) { updateSecurityAccount(ts_new->to_security->account()); } if(ts->to_security->account() != ts_new->to_security->account() && ts->to_security->account() != ts_new->from_security->account()) { updateSecurityAccount(ts->to_security->account()); } setModified(true); delete ts; dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } void Eqonomize::newSecurityTrade() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); EditSecurityTradeDialog *dialog = new EditSecurityTradeDialog(budget, i == NULL ? NULL : i->security(), this); if(dialog->checkSecurities() && dialog->exec() == QDialog::Accepted) { SecurityTrade *ts = dialog->createSecurityTrade(); if(ts) { budget->addSecurityTrade(ts); updateSecurity(ts->from_security); updateSecurity(ts->to_security); updateSecurityAccount(ts->from_security->account()); if(ts->to_security->account() != ts->from_security->account()) { updateSecurityAccount(ts->to_security->account()); } setModified(true); } } dialog->deleteLater(); } void Eqonomize::setQuotation() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); if(i == NULL) return; KDialogBase *dialog = new KDialogBase(this, 0, true, i18n("Set Quotation (%1)").arg(i->security()->name()), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true); dialog->setMainWidget(new QWidget(dialog)); QGridLayout *grid = new QGridLayout(dialog->mainWidget(), 2, 2, 0, dialog->spacingHint()); grid->addWidget(new QLabel(i18n("Price per share:"), dialog->mainWidget()), 0, 0); EqonomizeValueEdit *quotationEdit = new EqonomizeValueEdit(0.01, INT_MAX / pow(10, KGlobal::locale()->fracDigits()) - 1.0, pow(10, -KGlobal::locale()->fracDigits()), i->security()->getQuotation(QDate::currentDate()), KGlobal::locale()->fracDigits(), true, dialog->mainWidget()); quotationEdit->setFocus(); grid->addWidget(quotationEdit, 0, 1); grid->addWidget(new QLabel(i18n("Date:"), dialog->mainWidget()), 1, 0); KDateEdit *dateEdit = new KDateEdit(dialog->mainWidget()); grid->addWidget(dateEdit, 1, 1); while(dialog->exec() == QDialog::Accepted) { QDate date = dateEdit->date(); if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); } else if(date > QDate::currentDate()) { KMessageBox::error(this, i18n("Future dates are not allowed.")); } else { i->security()->setQuotation(date, quotationEdit->value()); updateSecurity(i); updateSecurityAccount(i->security()->account(), true); setModified(true); break; } } dialog->deleteLater(); } void Eqonomize::editQuotations() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); if(!i) return; Security *security = i->security(); EditQuotationsDialog *dialog = new EditQuotationsDialog(this); dialog->setSecurity(security); if(dialog->exec() == QDialog::Accepted) { dialog->modifyQuotations(security); updateSecurity(i); updateSecurityAccount(security->account()); setModified(true); } dialog->deleteLater(); } void Eqonomize::editSecurityTransactions() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); if(!i) return; SecurityTransactionsDialog *dialog = new SecurityTransactionsDialog(i->security(), this, i18n("Security Transactions")); dialog->exec(); dialog->deleteLater(); } void Eqonomize::securitiesSelectionChanged() { SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->selectedItem(); setQuotationButton->setEnabled(i != NULL); ActionEditSecurity->setEnabled(i != NULL); ActionDeleteSecurity->setEnabled(i != NULL); ActionSetQuotation->setEnabled(i != NULL); ActionEditQuotations->setEnabled(i != NULL); ActionEditSecurityTransactions->setEnabled(i != NULL); } void Eqonomize::securitiesExecuted(QListViewItem *i) { if(i == NULL) return; editSecurity(i); } void Eqonomize::securitiesExecuted(QListViewItem *i, const QPoint&, int c) { if(i == NULL) return; switch(c) { case 4: {} case 5: {} case 6: {} case 1: {} case 2: { editSecurityTransactions(); break; } case 3: { setQuotation(); break; } case 8: { if(((SecurityListViewItem*) i)->security()) { editAccount(((SecurityListViewItem*) i)->security()->account()); } break; } default: { editSecurity(i); break; } } } void Eqonomize::popupSecuritiesMenu(KListView*, QListViewItem*, const QPoint &p) { if(!securitiesPopupMenu) { securitiesPopupMenu = new QPopupMenu(this); ActionNewSecurity->plug(securitiesPopupMenu); ActionEditSecurity->plug(securitiesPopupMenu); ActionDeleteSecurity->plug(securitiesPopupMenu); securitiesPopupMenu->insertSeparator(); ActionBuyShares->plug(securitiesPopupMenu); ActionSellShares->plug(securitiesPopupMenu); ActionNewSecurityTrade->plug(securitiesPopupMenu); ActionNewDividend->plug(securitiesPopupMenu); ActionNewReinvestedDividend->plug(securitiesPopupMenu); ActionEditSecurityTransactions->plug(securitiesPopupMenu); securitiesPopupMenu->insertSeparator(); ActionSetQuotation->plug(securitiesPopupMenu); ActionEditQuotations->plug(securitiesPopupMenu); } securitiesPopupMenu->popup(p); } void Eqonomize::appendSecurity(Security *security) { double value = 0.0, cost = 0.0, rate = 0.0, profit = 0.0, quotation = 0.0, shares = 0.0; value = security->value(securities_to_date, true); cost = security->cost(securities_to_date); if(securities_to_date > QDate::currentDate()) quotation = security->expectedQuotation(securities_to_date); else quotation = security->getQuotation(securities_to_date); shares = security->shares(securities_to_date, true); if(securitiesPeriodFromButton->isChecked()) { rate = security->yearlyRate(securities_from_date, securities_to_date); profit = security->profit(securities_from_date, securities_to_date, true); } else { rate = security->yearlyRate(securities_to_date); profit = security->profit(securities_to_date, true); } SecurityListViewItem *i = new SecurityListViewItem(security, securitiesView, security->name(), KGlobal::locale()->formatMoney(value), KGlobal::locale()->formatNumber(shares, security->decimals()), KGlobal::locale()->formatMoney(quotation), KGlobal::locale()->formatMoney(cost), KGlobal::locale()->formatMoney(profit), KGlobal::locale()->formatNumber(rate * 100) + "%"); i->setText(8, security->account()->name()); i->value = value; i->cost = cost; i->rate = rate; i->profit = profit; switch(security->type()) { case SECURITY_TYPE_BOND: {i->setText(7, i18n("Bond")); break;} case SECURITY_TYPE_STOCK: {i->setText(7, i18n("Stock")); break;} case SECURITY_TYPE_MUTUAL_FUND: {i->setText(7, i18n("Mutual Fund")); break;} case SECURITY_TYPE_OTHER: {i->setText(7, i18n("Other")); break;} } total_rate *= total_value; total_value += value; total_cost += cost; total_rate += value * rate; if(total_cost != 0.0) total_rate /= total_value; total_profit += profit; updateSecuritiesStatistics(); } void Eqonomize::updateSecurity(Security *security) { QListViewItem *i = securitiesView->firstChild(); while(i != NULL) { if(((SecurityListViewItem*) i)->security() == security) { updateSecurity(i); break; } i = i->nextSibling(); } } void Eqonomize::updateSecurity(QListViewItem *i) { Security *security = ((SecurityListViewItem*) i)->security(); total_rate *= total_value; total_value -= ((SecurityListViewItem*) i)->value; total_cost -= ((SecurityListViewItem*) i)->cost; total_rate -= ((SecurityListViewItem*) i)->value * ((SecurityListViewItem*) i)->rate; if(total_cost != 0.0) total_rate /= total_value; total_profit -= ((SecurityListViewItem*) i)->profit; double value = 0.0, cost = 0.0, rate = 0.0, profit = 0.0, quotation = 0.0, shares = 0.0; value = security->value(securities_to_date, true); cost = security->cost(securities_to_date); if(securities_to_date > QDate::currentDate()) quotation = security->expectedQuotation(securities_to_date); else quotation = security->getQuotation(securities_to_date); shares = security->shares(securities_to_date, true); if(securitiesPeriodFromButton->isChecked()) { rate = security->yearlyRate(securities_from_date, securities_to_date); profit = security->profit(securities_from_date, securities_to_date, true); } else { rate = security->yearlyRate(securities_to_date); profit = security->profit(securities_to_date, true); } ((SecurityListViewItem*) i)->value = value; ((SecurityListViewItem*) i)->cost = cost; ((SecurityListViewItem*) i)->rate = rate; ((SecurityListViewItem*) i)->profit = profit; total_rate *= total_value; total_value += value; total_cost += cost; total_rate += value * rate; if(total_cost != 0.0) total_rate /= total_value; total_profit += profit; i->setText(0, security->name()); switch(security->type()) { case SECURITY_TYPE_BOND: {i->setText(7, i18n("Bond")); break;} case SECURITY_TYPE_STOCK: {i->setText(7, i18n("Stock")); break;} case SECURITY_TYPE_MUTUAL_FUND: {i->setText(7, i18n("Mutual Fund")); break;} case SECURITY_TYPE_OTHER: {i->setText(7, i18n("Other")); break;} } i->setText(1, KGlobal::locale()->formatMoney(value)); i->setText(2, KGlobal::locale()->formatNumber(shares, security->decimals())); i->setText(3, KGlobal::locale()->formatMoney(quotation)); i->setText(4, KGlobal::locale()->formatMoney(cost)); i->setText(5, KGlobal::locale()->formatMoney(profit)); i->setText(6, KGlobal::locale()->formatNumber(rate * 100) + "%"); i->setText(8, security->account()->name()); updateSecuritiesStatistics(); } void Eqonomize::updateSecurities() { securitiesView->clear(); total_value = 0.0; total_cost = 0.0; total_profit = 0.0; total_rate = 0.0; Security *security = budget->securities.first(); while(security) { appendSecurity(security); security = budget->securities.next(); } } void Eqonomize::newSplitTransaction() { newSplitTransaction(this); } bool Eqonomize::newSplitTransaction(QWidget *parent, AssetsAccount *account) { EditSplitDialog *dialog = new EditSplitDialog(budget, parent, account, b_extra); if(dialog->checkAccounts() && dialog->exec() == QDialog::Accepted) { SplitTransaction *split = dialog->createSplitTransaction(); if(split) { budget->addSplitTransaction(split); splitTransactionAdded(split); dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } bool Eqonomize::editSplitTransaction(SplitTransaction *split) { return editSplitTransaction(split, this); } bool Eqonomize::editSplitTransaction(SplitTransaction *split, QWidget *parent) { EditSplitDialog *dialog = new EditSplitDialog(budget, parent, NULL, b_extra); dialog->setSplitTransaction(split); if(dialog->exec() == QDialog::Accepted) { SplitTransaction *new_split = dialog->createSplitTransaction(); if(new_split) { removeSplitTransaction(split); budget->addSplitTransaction(new_split); splitTransactionAdded(new_split); dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } bool Eqonomize::splitUpTransaction(SplitTransaction *split) { expensesWidget->onSplitRemoved(split); incomesWidget->onSplitRemoved(split); transfersWidget->onSplitRemoved(split); split->clear(true); budget->removeSplitTransaction(split, true); splitTransactionRemoved(split); delete split; setModified(true); return true; } bool Eqonomize::removeSplitTransaction(SplitTransaction *split) { budget->removeSplitTransaction(split, true); splitTransactionRemoved(split); delete split; return true; } bool Eqonomize::newScheduledTransaction(int transaction_type, Security *security, bool select_security) { return newScheduledTransaction(transaction_type, security, select_security, this); } bool Eqonomize::newScheduledTransaction(int transaction_type, Security *security, bool select_security, QWidget *parent, Account *account) { ScheduledTransaction *strans = EditScheduledTransactionDialog::newScheduledTransaction(transaction_type, budget, parent, security, select_security, account, b_extra); if(strans) { if(!strans->recurrence() && strans->transaction()->date() <= QDate::currentDate()) { Transaction *trans = strans->transaction()->copy(); delete strans; budget->addTransaction(trans); transactionAdded(trans); } else { budget->addScheduledTransaction(strans); scheduledTransactionAdded(strans); checkSchedule(); } return true; } return false; } void Eqonomize::newScheduledExpense() { newScheduledTransaction(TRANSACTION_TYPE_EXPENSE); } void Eqonomize::newScheduledIncome() { newScheduledTransaction(TRANSACTION_TYPE_INCOME); } void Eqonomize::newScheduledTransfer() { newScheduledTransaction(TRANSACTION_TYPE_TRANSFER); } bool Eqonomize::editScheduledTransaction(ScheduledTransaction *strans) { return editScheduledTransaction(strans, this); } bool Eqonomize::editScheduledTransaction(ScheduledTransaction *strans, QWidget *parent) { ScheduledTransaction *old_strans = strans->copy(); if(EditScheduledTransactionDialog::editScheduledTransaction(strans, parent, true, b_extra)) { if(!strans->recurrence() && strans->transaction()->date() <= QDate::currentDate()) { Transaction *trans = strans->transaction()->copy(); budget->removeScheduledTransaction(strans, true); scheduledTransactionRemoved(strans, old_strans); delete strans; budget->addTransaction(trans); transactionAdded(trans); } else { scheduledTransactionModified(strans, old_strans); checkSchedule(); } delete old_strans; return true; } delete old_strans; return false; } bool Eqonomize::editOccurrence(ScheduledTransaction *strans, const QDate &date) { return editOccurrence(strans, date, this); } bool Eqonomize::editOccurrence(ScheduledTransaction *strans, const QDate &date, QWidget *parent) { Security *security = NULL; if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY || strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_SELL) { security = ((SecurityTransaction*) strans->transaction())->security(); } else if(strans->transaction()->type() == TRANSACTION_TYPE_INCOME && ((Income*) strans->transaction())->security()) { security = ((Income*) strans->transaction())->security(); } TransactionEditDialog *dialog = new TransactionEditDialog(b_extra, strans->transaction()->type(), false, false, security, SECURITY_ALL_VALUES, security != NULL, budget, parent); dialog->editWidget->updateAccounts(); dialog->editWidget->setScheduledTransaction(strans, date); if(dialog->editWidget->checkAccounts() && dialog->exec() == QDialog::Accepted) { Transaction *trans = dialog->editWidget->createTransaction(); if(trans) { if(trans->date() > QDate::currentDate()) { ScheduledTransaction *strans_new = new ScheduledTransaction(budget, trans, NULL); budget->addScheduledTransaction(strans_new); scheduledTransactionAdded(strans_new); } else { budget->addTransaction(trans); transactionAdded(trans); } ScheduledTransaction *old_strans = strans->copy(); strans->addException(date); scheduledTransactionModified(strans, old_strans); delete old_strans; dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } void Eqonomize::editScheduledTransaction() { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); if(i == NULL) return; editScheduledTransaction(i->scheduledTransaction()); } void Eqonomize::editOccurrence() { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); if(i == NULL) return; editOccurrence(i->scheduledTransaction(), i->date()); } bool Eqonomize::removeScheduledTransaction(ScheduledTransaction *strans) { budget->removeScheduledTransaction(strans, true); scheduledTransactionRemoved(strans); delete strans; return true; } void Eqonomize::removeScheduledTransaction() { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); if(i == NULL) return; removeScheduledTransaction(i->scheduledTransaction()); } bool Eqonomize::removeOccurrence(ScheduledTransaction *strans, const QDate &date) { if(strans->isOneTimeTransaction()) { removeScheduledTransaction(strans); } else { ScheduledTransaction *oldstrans = strans->copy(); strans->addException(date); scheduledTransactionModified(strans, oldstrans); delete oldstrans; } return true; } void Eqonomize::removeOccurrence() { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); if(i == NULL) return; removeOccurrence(i->scheduledTransaction(), i->date()); } void Eqonomize::scheduleSelectionChanged() { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); if(i == NULL) { editScheduleButton->setEnabled(false); removeScheduleButton->setEnabled(false); } else { editScheduleButton->setEnabled(true); removeScheduleButton->setEnabled(true); editScheduleMenu->setItemEnabled(0, true); removeScheduleMenu->setItemEnabled(0, true); editScheduleMenu->setItemEnabled(1, !i->scheduledTransaction()->isOneTimeTransaction()); removeScheduleMenu->setItemEnabled(1, !i->scheduledTransaction()->isOneTimeTransaction()); } } void Eqonomize::scheduleExecuted(QListViewItem *i) { if(i == NULL) return; editScheduledTransaction(((ScheduleListViewItem*) i)->scheduledTransaction()); } void Eqonomize::popupScheduleMenu(KListView*, QListViewItem*, const QPoint &p) { if(!schedulePopupMenu) { schedulePopupMenu = new QPopupMenu(this); ActionEditScheduledTransaction->plug(schedulePopupMenu); ActionEditTransaction->plug(schedulePopupMenu); schedulePopupMenu->insertSeparator(); ActionDeleteScheduledTransaction->plug(schedulePopupMenu); ActionDeleteTransaction->plug(schedulePopupMenu); } schedulePopupMenu->popup(p); } void Eqonomize::editSelectedScheduledTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {editScheduledTransaction(); return;} } if(!w) return; w->editScheduledTransaction(); } void Eqonomize::editSelectedSplitTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {return;} } if(!w) return; w->editSplitTransaction(); } void Eqonomize::joinSelectedTransactions() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {return;} } if(!w) return; w->joinTransactions(); } void Eqonomize::splitUpSelectedTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {return;} } if(!w) return; w->splitUpTransaction(); } bool Eqonomize::editTransaction(Transaction *trans) { return editTransaction(trans, this); } bool Eqonomize::editTransaction(Transaction *trans, QWidget *parent) { Transaction *oldtrans = trans->copy(); Recurrence *rec = NULL; if(trans->parentSplit()) { SplitTransaction *split = trans->parentSplit(); Security *security = NULL; if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL) { security = ((SecurityTransaction*) trans)->security(); } else if(trans->type() == TRANSACTION_TYPE_INCOME && ((Income*) trans)->security()) { security = ((Income*) trans)->security(); } TransactionEditDialog *dialog = new TransactionEditDialog(b_extra, trans->type(), true, trans->fromAccount() == split->account(), security, SECURITY_ALL_VALUES, security != NULL, budget, parent); dialog->editWidget->updateAccounts(split->account()); dialog->editWidget->setTransaction(trans); if(dialog->exec() == QDialog::Accepted) { if(dialog->editWidget->modifyTransaction(trans)) { transactionModified(trans, oldtrans); delete oldtrans; return true; } } dialog->deleteLater(); } else if(EditScheduledTransactionDialog::editTransaction(trans, rec, parent, true, b_extra)) { if(!rec && trans->date() <= QDate::currentDate()) { transactionModified(trans, oldtrans); } else { budget->removeTransaction(trans, true); transactionRemoved(trans); ScheduledTransaction *strans = new ScheduledTransaction(budget, trans, rec); budget->addScheduledTransaction(strans); scheduledTransactionAdded(strans); } delete oldtrans; return true; } delete oldtrans; return false; } void Eqonomize::newRefund() { if(tabs->activePageIndex() == 1) expensesWidget->newRefundRepayment(); } void Eqonomize::newRepayment() { if(tabs->activePageIndex() == 2) incomesWidget->newRefundRepayment(); } void Eqonomize::newRefundRepayment() { if(tabs->activePageIndex() == 1) expensesWidget->newRefundRepayment(); else if(tabs->activePageIndex() == 2) incomesWidget->newRefundRepayment(); } bool Eqonomize::newRefundRepayment(Transaction *trans) { if(trans->type() != TRANSACTION_TYPE_EXPENSE && trans->type() != TRANSACTION_TYPE_INCOME) return false; RefundDialog *dialog = new RefundDialog(trans, this); if(dialog->exec() == QDialog::Accepted) { Transaction *new_trans = dialog->createRefund(); if(new_trans) { budget->addTransaction(new_trans); transactionAdded(new_trans); dialog->deleteLater(); return true; } } dialog->deleteLater(); return false; } void Eqonomize::editSelectedTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {editOccurrence(); return;} } if(!w) return; w->editTransaction(); } void Eqonomize::deleteSelectedScheduledTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {removeScheduledTransaction(); return;} } if(!w) return; w->removeScheduledTransaction(); } void Eqonomize::deleteSelectedSplitTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {return;} } if(!w) return; w->removeSplitTransaction(); } void Eqonomize::deleteSelectedTransaction() { TransactionListWidget *w = NULL; switch(tabs->activePageIndex()) { case 0: {return;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {return;} case 5: {removeOccurrence(); return;} } if(!w) return; w->removeTransaction(); } void Eqonomize::onPageChange(QWidget *w) { if(w == expenses_page) { expensesWidget->onDisplay(); } else if(w == incomes_page) { incomesWidget->onDisplay(); } else if(w == transfers_page) { transfersWidget->onDisplay(); } if(w == accounts_page) { accountsSelectionChanged(); } else { ActionDeleteAccount->setEnabled(false); ActionEditAccount->setEnabled(false); ActionBalanceAccount->setEnabled(false); ActionShowAccountTransactions->setEnabled(false); } if(w == securities_page) { securitiesSelectionChanged(); } else { ActionEditSecurity->setEnabled(false); ActionDeleteSecurity->setEnabled(false); ActionSetQuotation->setEnabled(false); ActionEditQuotations->setEnabled(false); ActionEditSecurityTransactions->setEnabled(false); } updateTransactionActions(); } void Eqonomize::updateTransactionActions() { TransactionListWidget *w = NULL; bool b_transaction = false, b_scheduledtransaction = false; switch(tabs->activePageIndex()) { case 0: {b_transaction = false; b_scheduledtransaction = false; break;} case 1: {w = expensesWidget; break;} case 2: {w = incomesWidget; break;} case 3: {w = transfersWidget; break;} case 4: {b_transaction = false; b_scheduledtransaction = false; break;} case 5: { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->selectedItem(); b_transaction = i && !i->scheduledTransaction()->isOneTimeTransaction(); b_scheduledtransaction = (i != NULL); break; } } if(w) { w->updateTransactionActions(); } else { ActionJoinTransactions->setEnabled(false); ActionSplitUpTransaction->setEnabled(false); ActionEditSplitTransaction->setEnabled(false); ActionDeleteSplitTransaction->setEnabled(false); ActionEditTransaction->setEnabled(b_transaction); ActionDeleteTransaction->setEnabled(b_transaction); ActionEditScheduledTransaction->setEnabled(b_scheduledtransaction); ActionDeleteScheduledTransaction->setEnabled(b_scheduledtransaction); ActionNewRefund->setEnabled(false); ActionNewRepayment->setEnabled(false); ActionNewRefundRepayment->setEnabled(false); } } void Eqonomize::popupAccountsMenu(KListView*, QListViewItem *i, const QPoint &p) { if(i == NULL) return; if(i == assetsItem || (account_items.contains(i) && (account_items[i]->type() == ACCOUNT_TYPE_ASSETS))) { ActionAddAccount->setText("Add Account"); } else { ActionAddAccount->setText("Add Category"); } if(!accountPopupMenu) { accountPopupMenu = new QPopupMenu(this); ActionAddAccount->plug(accountPopupMenu); ActionEditAccount->plug(accountPopupMenu); ActionBalanceAccount->plug(accountPopupMenu); ActionDeleteAccount->plug(accountPopupMenu); accountPopupMenu->insertSeparator(); ActionShowAccountTransactions->plug(accountPopupMenu); } accountPopupMenu->popup(p); } void Eqonomize::showAccountTransactions(bool b) { QListViewItem *i = accountsView->selectedItem(); if(i == NULL || i == assetsItem) return; if(i == incomesItem) { if(b) incomesWidget->setFilter(QDate(), to_date, -1.0, -1.0, NULL, NULL); else incomesWidget->setFilter(accountsPeriodFromButton->isChecked() ? from_date : QDate(), to_date, -1.0, -1.0, NULL, NULL); incomesWidget->showFilter(); tabs->showPage(2); onPageChange(incomes_page); } else if(i == expensesItem) { if(b) expensesWidget->setFilter(QDate(), to_date, -1.0, -1.0, NULL, NULL); else expensesWidget->setFilter(accountsPeriodFromButton->isChecked() ? from_date : QDate(), to_date, -1.0, -1.0, NULL, NULL); expensesWidget->showFilter(); tabs->showPage(1); onPageChange(expenses_page); } else { Account *account = account_items[i]; AccountType type = account->type(); if(type == ACCOUNT_TYPE_INCOMES) { if(b) incomesWidget->setFilter(QDate(), to_date, -1.0, -1.0, account, NULL); else incomesWidget->setFilter(accountsPeriodFromButton->isChecked() ? from_date : QDate(), to_date, -1.0, -1.0, account, NULL); incomesWidget->showFilter(); tabs->showPage(2); onPageChange(incomes_page); } else if(type == ACCOUNT_TYPE_EXPENSES) { if(b) expensesWidget->setFilter(QDate(), to_date, -1.0, -1.0, NULL, account); else expensesWidget->setFilter(accountsPeriodFromButton->isChecked() ? from_date : QDate(), to_date, -1.0, -1.0, NULL, account); expensesWidget->showFilter(); tabs->showPage(1); onPageChange(expenses_page); } else if(((AssetsAccount*) account)->accountType() == ASSETS_TYPE_SECURITIES) { tabs->showPage(4); onPageChange(securities_page); } else { LedgerDialog *dialog = new LedgerDialog((AssetsAccount*) account, this, i18n("Ledger"), b_extra); dialog->show(); } } } void Eqonomize::accountsPeriodToChanged(const QDate &date) { bool error = false; if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); error = true; } if(!error && accountsPeriodFromEdit->date() > date) { if(accountsPeriodFromButton->isChecked()) { KMessageBox::error(this, i18n("To date is before from date.")); } from_date = date; accountsPeriodFromEdit->blockSignals(true); accountsPeriodFromEdit->setDate(from_date); accountsPeriodFromEdit->blockSignals(false); } if(error) { accountsPeriodToEdit->setFocus(); accountsPeriodToEdit->blockSignals(true); accountsPeriodToEdit->setDate(to_date); accountsPeriodToEdit->blockSignals(false); accountsPeriodToEdit->lineEdit()->selectAll(); return; } to_date = date; filterAccounts(); } void Eqonomize::accountsPeriodFromChanged(const QDate &date) { bool error = false; if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); error = true; } if(!error && date > accountsPeriodToEdit->date()) { KMessageBox::error(this, i18n("From date is after to date.")); to_date = date; accountsPeriodToEdit->blockSignals(true); accountsPeriodToEdit->setDate(to_date); accountsPeriodToEdit->blockSignals(false); } if(error) { accountsPeriodFromEdit->setFocus(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodFromEdit->setDate(from_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodFromEdit->lineEdit()->selectAll(); return; } from_date = date; if(accountsPeriodFromButton->isChecked()) filterAccounts(); } void Eqonomize::prevMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); from_date = addMonths(from_date, -1); accountsPeriodFromEdit->setDate(from_date); if((to_date == QDate::currentDate() && calSys->day(from_date) == 1) || calSys->day(to_date) == calSys->daysInMonth(to_date)) { to_date = addMonths(to_date, -1); calSys->setYMD(to_date, calSys->year(to_date), calSys->month(to_date), calSys->daysInMonth(to_date)); } else { to_date = addMonths(to_date, -1); } accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::nextMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); from_date = addMonths(from_date, 1); accountsPeriodFromEdit->setDate(from_date); to_date = accountsPeriodToEdit->date(); if((to_date == QDate::currentDate() && calSys->day(from_date) == 1) || calSys->day(to_date) == calSys->daysInMonth(to_date)) { to_date = addMonths(to_date, 1); calSys->setYMD(to_date, calSys->year(to_date), calSys->month(to_date), calSys->daysInMonth(to_date)); } else { to_date = addMonths(to_date, 1); } accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::currentMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); QDate curdate = QDate::currentDate(); calSys->setYMD(from_date, calSys->year(curdate), calSys->month(curdate), 1); accountsPeriodFromEdit->setDate(from_date); to_date = curdate; accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::prevYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); from_date = addYears(from_date, -1); accountsPeriodFromEdit->setDate(from_date); if((to_date == QDate::currentDate() && calSys->day(from_date) == 1) || calSys->day(to_date) == calSys->daysInMonth(to_date)) { to_date = addYears(to_date, -1); calSys->setYMD(to_date, calSys->year(to_date), calSys->month(to_date), calSys->daysInMonth(to_date)); } else { to_date = addYears(to_date, -1); } accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::nextYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); from_date = addYears(from_date, 1); accountsPeriodFromEdit->setDate(from_date); if((to_date == QDate::currentDate() && calSys->day(from_date) == 1) || calSys->day(to_date) == calSys->daysInMonth(to_date)) { to_date = addYears(to_date, 1); calSys->setYMD(to_date, calSys->year(to_date), calSys->month(to_date), calSys->daysInMonth(to_date)); } else { to_date = addYears(to_date, 1); } accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::currentYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); accountsPeriodFromEdit->blockSignals(true); accountsPeriodToEdit->blockSignals(true); QDate curdate = QDate::currentDate(); calSys->setYMD(from_date, calSys->year(curdate), 1, 1); accountsPeriodFromEdit->setDate(from_date); to_date = curdate; accountsPeriodToEdit->setDate(to_date); accountsPeriodFromEdit->blockSignals(false); accountsPeriodToEdit->blockSignals(false); filterAccounts(); } void Eqonomize::securitiesPeriodToChanged(const QDate &date) { bool error = false; if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); error = true; } if(!error && securitiesPeriodFromEdit->date() > date) { if(securitiesPeriodFromButton->isChecked()) { KMessageBox::error(this, i18n("To date is before from date.")); } securities_from_date = date; securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodFromEdit->setDate(securities_from_date); securitiesPeriodFromEdit->blockSignals(false); } if(error) { securitiesPeriodToEdit->setFocus(); securitiesPeriodToEdit->blockSignals(true); securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodToEdit->blockSignals(false); securitiesPeriodToEdit->lineEdit()->selectAll(); return; } securities_to_date = date; updateSecurities(); } void Eqonomize::securitiesPeriodFromChanged(const QDate &date) { bool error = false; if(!date.isValid()) { KMessageBox::error(this, i18n("Invalid date.")); error = true; } if(!error && date > securitiesPeriodToEdit->date()) { KMessageBox::error(this, i18n("From date is after to date.")); securities_to_date = date; securitiesPeriodToEdit->blockSignals(true); securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodToEdit->blockSignals(false); } if(error) { securitiesPeriodFromEdit->setFocus(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodFromEdit->setDate(securities_from_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodFromEdit->lineEdit()->selectAll(); return; } securities_from_date = date; if(securitiesPeriodFromButton->isChecked()) updateSecurities(); } void Eqonomize::securitiesPrevMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); securities_from_date = addMonths(securities_from_date, -1); securitiesPeriodFromEdit->setDate(securities_from_date); if((securities_to_date == QDate::currentDate() && calSys->day(securities_from_date) == 1) || calSys->day(securities_to_date) == calSys->daysInMonth(securities_to_date)) { securities_to_date = addMonths(securities_to_date, -1); calSys->setYMD(securities_to_date, calSys->year(securities_to_date), calSys->month(securities_to_date), calSys->daysInMonth(securities_to_date)); } else { securities_to_date = addMonths(securities_to_date, -1); } securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::securitiesNextMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); securities_from_date = addMonths(securities_from_date, 1); securitiesPeriodFromEdit->setDate(securities_from_date); securities_to_date = securitiesPeriodToEdit->date(); if((securities_to_date == QDate::currentDate() && calSys->day(securities_from_date) == 1) || calSys->day(securities_to_date) == calSys->daysInMonth(securities_to_date)) { securities_to_date = addMonths(securities_to_date, 1); calSys->setYMD(securities_to_date, calSys->year(securities_to_date), calSys->month(securities_to_date), calSys->daysInMonth(securities_to_date)); } else { securities_to_date = addMonths(securities_to_date, 1); } securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::securitiesCurrentMonth() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); QDate curdate = QDate::currentDate(); calSys->setYMD(securities_from_date, calSys->year(curdate), calSys->month(curdate), 1); securitiesPeriodFromEdit->setDate(securities_from_date); securities_to_date = curdate; securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::securitiesPrevYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); securities_from_date = addYears(securities_from_date, -1); securitiesPeriodFromEdit->setDate(securities_from_date); if((securities_to_date == QDate::currentDate() && calSys->day(securities_from_date) == 1) || calSys->day(securities_to_date) == calSys->daysInMonth(securities_to_date)) { securities_to_date = addYears(securities_to_date, -1); calSys->setYMD(securities_to_date, calSys->year(securities_to_date), calSys->month(securities_to_date), calSys->daysInMonth(securities_to_date)); } else { securities_to_date = addYears(securities_to_date, -1); } securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::securitiesNextYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); securities_from_date = addYears(securities_from_date, 1); securitiesPeriodFromEdit->setDate(securities_from_date); if((securities_to_date == QDate::currentDate() && calSys->day(securities_from_date) == 1) || calSys->day(securities_to_date) == calSys->daysInMonth(securities_to_date)) { securities_to_date = addYears(securities_to_date, 1); calSys->setYMD(securities_to_date, calSys->year(securities_to_date), calSys->month(securities_to_date), calSys->daysInMonth(securities_to_date)); } else { securities_to_date = addYears(securities_to_date, 1); } securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::securitiesCurrentYear() { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); securitiesPeriodFromEdit->blockSignals(true); securitiesPeriodToEdit->blockSignals(true); QDate curdate = QDate::currentDate(); calSys->setYMD(securities_from_date, calSys->year(curdate), 1, 1); securitiesPeriodFromEdit->setDate(securities_from_date); securities_to_date = curdate; securitiesPeriodToEdit->setDate(securities_to_date); securitiesPeriodFromEdit->blockSignals(false); securitiesPeriodToEdit->blockSignals(false); updateSecurities(); } void Eqonomize::setModified(bool has_been_modified) { modified_auto_save = has_been_modified; if(has_been_modified) autoSave(); if(modified == has_been_modified) return; modified = has_been_modified; ActionSave->setEnabled(modified); if(!current_url.isValid()) setCaption(i18n("Untitled"), has_been_modified); else setCaption(current_url.fileName(), has_been_modified); if(modified) emit budgetUpdated(); else auto_save_timeout = true; } void Eqonomize::createDefaultBudget() { if(!askSave()) return; budget->clear(); current_url = ""; ActionFileReload->setEnabled(false); config->setGroup("General Options"); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif config->sync(); budget->addAccount(new AssetsAccount(budget, ASSETS_TYPE_CASH, i18n("Cash"), 100.0)); budget->addAccount(new AssetsAccount(budget, ASSETS_TYPE_CURRENT, i18n("Check Account"), 1000.0)); budget->addAccount(new AssetsAccount(budget, ASSETS_TYPE_SAVINGS, i18n("Savings Account"), 10000.0)); budget->addAccount(new IncomesAccount(budget, i18n("Salary"))); budget->addAccount(new IncomesAccount(budget, i18n("Other"))); budget->addAccount(new ExpensesAccount(budget, i18n("Bills"))); budget->addAccount(new ExpensesAccount(budget, i18n("Clothing"))); budget->addAccount(new ExpensesAccount(budget, i18n("Groceries"))); budget->addAccount(new ExpensesAccount(budget, i18n("Leisure"))); budget->addAccount(new ExpensesAccount(budget, i18n("Other"))); reloadBudget(); setModified(false); emit accountsModified(); emit transactionsModified(); emit budgetUpdated(); } void Eqonomize::reloadBudget() { incomes_accounts_value = 0.0; incomes_accounts_change = 0.0; expenses_accounts_value = 0.0; expenses_accounts_change = 0.0; assets_accounts_value = 0.0; assets_accounts_change = 0.0; expenses_budget = 0.0; expenses_budget_diff = 0.0; incomes_budget = 0.0; incomes_budget_diff = 0.0; account_value.clear(); account_change.clear(); for(QMap::Iterator it = account_items.begin(); it != account_items.end(); ++it) { delete it.key(); } account_items.clear(); item_accounts.clear(); AssetsAccount *aaccount = budget->assetsAccounts.first(); while(aaccount) { if(aaccount != budget->balancingAccount) { appendAssetsAccount(aaccount); } aaccount = budget->assetsAccounts.next(); } IncomesAccount *iaccount = budget->incomesAccounts.first(); while(iaccount) { appendIncomesAccount(iaccount); iaccount = budget->incomesAccounts.next(); } ExpensesAccount *eaccount = budget->expensesAccounts.first(); while(eaccount) { appendExpensesAccount(eaccount); eaccount = budget->expensesAccounts.next(); } account_value[budget->balancingAccount] = 0.0; account_change[budget->balancingAccount] = 0.0; expensesWidget->updateAccounts(); incomesWidget->updateAccounts(); transfersWidget->updateAccounts(); assetsItem->setOpen(true); incomesItem->setOpen(true); expensesItem->setOpen(true); expensesWidget->transactionsReset(); incomesWidget->transactionsReset(); transfersWidget->transactionsReset(); filterAccounts(); updateScheduledTransactions(); updateSecurities(); } void Eqonomize::openURL(const KURL& url) { if(url != current_url && crashRecovery(KURL(url))) return; QString tmpfile; if(!url.isLocalFile()) { if(!KIO::NetAccess::download(url, tmpfile, this)) { KMessageBox::error(this, i18n("Couldn't fetch %1.").arg(url.prettyURL())); return; } } else { tmpfile = url.path(); } QString errors; QString error = budget->loadFile(tmpfile, errors); if(!url.isLocalFile()) { KIO::NetAccess::removeTempFile(tmpfile); } if(!error.isNull()) { KMessageBox::error(this, i18n("Error loading %1: %2.").arg(url.prettyURL()).arg(error), i18n("Couldn't open file")); return; } if(!errors.isEmpty()) { KMessageBox::error(this, errors); } setCaption(url.fileName(), false); current_url = url; ActionFileReload->setEnabled(true); config->setGroup("General Options"); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif if(!cr_tmp_file.isEmpty()) {QFile file(cr_tmp_file); file.remove(); cr_tmp_file = "";} if(current_url.isLocalFile()) cr_tmp_file = kapp->tempSaveName(current_url.path()); config->sync(); ActionOpenRecent->addURL(url); reloadBudget(); emit accountsModified(); emit transactionsModified(); emit budgetUpdated(); setModified(false); checkSchedule(true); } bool Eqonomize::saveURL(const KURL& url) { if(url.isLocalFile()) { bool exists = QFile::exists(url.path()); if(url != current_url && exists) { if(KMessageBox::warningYesNo(this, i18n("The selected file already exists. Would you like to overwrite the old copy?")) != KMessageBox::Yes) return false; } mode_t perms = 0600; if(exists) { KURL u(url); u.setFileName(url.fileName() + "~"); KIO::UDSEntry fentry; if(KIO::NetAccess::stat(url, fentry, this)) { KFileItem item(fentry, url); perms = item.permissions(); } if((!KIO::NetAccess::exists(u, false, this) || KIO::NetAccess::del(u, this))) { KIO::NetAccess::file_copy(url, u, perms, true, false, this); } } QString error = budget->saveFile(url.path(), perms); if(!error.isNull()) { KMessageBox::error(this, i18n("Error saving %1: %2.").arg(url.prettyURL()).arg(error), i18n("Couldn't save file")); return false; } else { setCaption(url.fileName(), false); current_url = url; ActionFileReload->setEnabled(true); config->setGroup("General Options"); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif if(!cr_tmp_file.isEmpty()) {QFile file(cr_tmp_file); file.remove();} cr_tmp_file = kapp->tempSaveName(current_url.path()); config->sync(); ActionOpenRecent->addURL(url); setModified(false); } return true; } KTempFile tf; tf.setAutoDelete(true); QString error = budget->saveFile(tf.name()); if(!error.isNull()) { KMessageBox::error(this, i18n("Error saving %1: %2.").arg(url.prettyURL()).arg(error), i18n("Couldn't save file")); return false; } if(KIO::NetAccess::upload(tf.name(), url, this)) { setCaption(url.fileName(), false); current_url = url; ActionFileReload->setEnabled(true); config->setGroup("General Options"); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif if(!cr_tmp_file.isEmpty()) {QFile file(cr_tmp_file); file.remove(); cr_tmp_file = "";} config->sync(); ActionOpenRecent->addURL(url); setModified(false); return true; } else { KMessageBox::error(this, i18n("Failed to upload file to %1.").arg(url.prettyURL()), i18n("Couldn't save file")); } return false; } void Eqonomize::importCSV() { ImportCSVDialog *dialog = new ImportCSVDialog(budget, this); if(dialog->exec() == QDialog::Accepted) { reloadBudget(); emit accountsModified(); emit transactionsModified(); setModified(true); } dialog->deleteLater(); } void Eqonomize::importQIF() { if(importQIFFile(budget, this, b_extra)) { reloadBudget(); emit accountsModified(); emit transactionsModified(); setModified(true); } } void Eqonomize::exportQIF() { exportQIFFile(budget, this, b_extra); } void Eqonomize::showOverTimeReport() { KDialogBase *dialog = new KDialogBase(0, 0, false, i18n("Report"), KDialogBase::Close, KDialogBase::Close, true); OverTimeReport *report = new OverTimeReport(budget, dialog); report->updateDisplay(); dialog->setMainWidget(report); QDesktopWidget desktop; QSize default_size = QSize(750, 650).boundedTo(desktop.availableGeometry(this).size()); dialog->setInitialSize(dialog->configDialogSize(*config, "Over Time Report").expandedTo(default_size)); dialog->show(); connect(this, SIGNAL(accountsModified()), report, SLOT(updateAccounts())); connect(this, SIGNAL(transactionsModified()), report, SLOT(updateTransactions())); connect(dialog, SIGNAL(finished()), this, SLOT(overTimeReportClosed())); connect(this, SIGNAL(timeToSaveConfig()), report, SLOT(saveConfig())); } void Eqonomize::overTimeReportClosed() { KDialogBase *dialog = (KDialogBase*) sender(); OverTimeReport *report = (OverTimeReport*) dialog->mainWidget(); report->saveConfig(); dialog->delayedDestruct(); } void Eqonomize::showCategoriesComparisonReport() { KDialogBase *dialog = new KDialogBase(0, 0, false, i18n("Report"), KDialogBase::Close, KDialogBase::Close, true); CategoriesComparisonReport *report = new CategoriesComparisonReport(budget, dialog, b_extra); report->updateDisplay(); dialog->setMainWidget(report); QDesktopWidget desktop; QSize default_size = QSize(750, 670).boundedTo(desktop.availableGeometry(this).size()); dialog->setInitialSize(dialog->configDialogSize(*config, "Categories Comparison Report").expandedTo(default_size)); dialog->show(); connect(this, SIGNAL(accountsModified()), report, SLOT(updateAccounts())); connect(this, SIGNAL(transactionsModified()), report, SLOT(updateTransactions())); connect(dialog, SIGNAL(finished()), this, SLOT(categoriesComparisonReportClosed())); connect(this, SIGNAL(timeToSaveConfig()), report, SLOT(saveConfig())); } void Eqonomize::categoriesComparisonReportClosed() { KDialogBase *dialog = (KDialogBase*) sender(); CategoriesComparisonReport *report = (CategoriesComparisonReport*) dialog->mainWidget(); report->saveConfig(); dialog->delayedDestruct(); } void Eqonomize::showOverTimeChart() { KDialogBase *dialog = new KDialogBase(0, 0, false, i18n("Chart"), KDialogBase::Close, KDialogBase::Close, true); OverTimeChart *chart = new OverTimeChart(budget, dialog, b_extra); dialog->setMainWidget(chart); QDesktopWidget desktop; QSize default_size = QSize(850, b_extra ? 750 : 730).boundedTo(desktop.availableGeometry(this).size()); dialog->setInitialSize(dialog->configDialogSize(*config, "Over Time Chart").expandedTo(default_size)); dialog->show(); chart->updateDisplay(); connect(this, SIGNAL(accountsModified()), chart, SLOT(updateAccounts())); connect(this, SIGNAL(transactionsModified()), chart, SLOT(updateTransactions())); connect(dialog, SIGNAL(finished()), this, SLOT(overTimeChartClosed())); connect(this, SIGNAL(timeToSaveConfig()), chart, SLOT(saveConfig())); } void Eqonomize::overTimeChartClosed() { KDialogBase *dialog = (KDialogBase*) sender(); OverTimeChart *chart = (OverTimeChart*) dialog->mainWidget(); chart->saveConfig(); dialog->delayedDestruct(); } void Eqonomize::showCategoriesComparisonChart() { KDialogBase *dialog = new KDialogBase(0, 0, false, i18n("Chart"), KDialogBase::Close, KDialogBase::Close, true); CategoriesComparisonChart *chart = new CategoriesComparisonChart(budget, dialog); dialog->setMainWidget(chart); QDesktopWidget desktop; QSize default_size = QSize(750, 700).boundedTo(desktop.availableGeometry(this).size()); dialog->setInitialSize(dialog->configDialogSize(*config, "Categories Comparison Chart").expandedTo(default_size)); dialog->show(); chart->updateDisplay(); connect(this, SIGNAL(accountsModified()), chart, SLOT(updateAccounts())); connect(this, SIGNAL(transactionsModified()), chart, SLOT(updateTransactions())); connect(dialog, SIGNAL(finished()), this, SLOT(categoriesComparisonChartClosed())); connect(this, SIGNAL(timeToSaveConfig()), chart, SLOT(saveConfig())); } void Eqonomize::categoriesComparisonChartClosed() { KDialogBase *dialog = (KDialogBase*) sender(); CategoriesComparisonChart *report = (CategoriesComparisonChart*) dialog->mainWidget(); report->saveConfig(); dialog->delayedDestruct(); } QString htmlize_string(QString str) { str.replace('<', "<"); str.replace('>', ">"); str.replace('&', "&"); str.replace('\"', """); return str; } bool Eqonomize::exportScheduleList(QTextStream &outf, int fileformat) { switch(fileformat) { case 'h': { outf.setEncoding(QTextStream::UnicodeUTF8); outf << "" << '\n'; outf << "" << '\n'; outf << "\t" << '\n'; outf << "\t\t"; outf << htmlize_string(i18n("Transaction Schedule")); outf << "" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t" << '\n'; outf << "\t" << '\n'; outf << "\t" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->firstChild(); while(i) { outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; i = (ScheduleListViewItem*) i->nextSibling(); } outf << "\t\t\t" << '\n'; outf << "\t\t
"; outf << htmlize_string(i18n("Transaction Schedule")); outf << "
" << htmlize_string(scheduleView->columnText(0)) << "" << htmlize_string(scheduleView->columnText(1)) << "" << htmlize_string(scheduleView->columnText(2)) << "" << htmlize_string(scheduleView->columnText(3)) << "" << htmlize_string(scheduleView->columnText(4)) << "" << htmlize_string(scheduleView->columnText(5)) << "" << htmlize_string(scheduleView->columnText(6)) << "
" << htmlize_string(KGlobal::locale()->formatDate(i->date(), true)) << "" << htmlize_string(i->text(1)) << "" << htmlize_string(i->text(2)) << "" << htmlize_string(i->text(3)) << "" << htmlize_string(i->text(4)) << "" << htmlize_string(i->text(5)) << "" << htmlize_string(i->text(6)) << "
" << '\n'; outf << "\t" << '\n'; outf << "" << '\n'; break; } case 'c': { outf.setEncoding(QTextStream::Locale); outf << "\"" << scheduleView->columnText(0) << "\",\"" << scheduleView->columnText(1) << "\",\"" << scheduleView->columnText(2) << "\",\"" << scheduleView->columnText(3) << "\",\"" << scheduleView->columnText(4) << "\",\""<< scheduleView->columnText(5) << "\",\"" << scheduleView->columnText(6) << "\"\n"; ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->firstChild(); while(i) { outf << "\"" << KGlobal::locale()->formatDate(i->date(), true) << "\",\"" << i->text(1) << "\",\"" << i->text(2) << "\",\"" << i->text(3) << "\",\"" << i->text(4) << "\",\"" << i->text(5) << "\",\"" << i->text(6) << "\"\n"; i = (ScheduleListViewItem*) i->nextSibling(); } break; } } return true; } bool Eqonomize::exportSecuritiesList(QTextStream &outf, int fileformat) { switch(fileformat) { case 'h': { outf.setEncoding(QTextStream::UnicodeUTF8); outf << "" << '\n'; outf << "" << '\n'; outf << "\t" << '\n'; outf << "\t\t"; outf << htmlize_string(i18n("Securities")); outf << "" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t" << '\n'; outf << "\t" << '\n'; outf << "\t" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->firstChild(); while(i) { outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; i = (SecurityListViewItem*) i->nextSibling(); } outf << "\t\t\t\t" << '\n'; if(securitiesView->childCount() > 1) { outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; } outf << "\t\t\t" << '\n'; outf << "\t\t
"; outf << htmlize_string(i18n("Securities")); outf << "
" << htmlize_string(securitiesView->columnText(0)) << "" << htmlize_string(securitiesView->columnText(1)) << "" << htmlize_string(securitiesView->columnText(2)) << "" << htmlize_string(securitiesView->columnText(3)) << "" << htmlize_string(securitiesView->columnText(4)) << "" << htmlize_string(securitiesView->columnText(5)) << "" << htmlize_string(securitiesView->columnText(6)) << "" << htmlize_string(securitiesView->columnText(7)) << "" << htmlize_string(securitiesView->columnText(8)) << "
" << htmlize_string(i->text(0)) << "" << htmlize_string(i->text(1)) << "" << htmlize_string(i->text(2)) << "" << htmlize_string(i->text(3)) << "" << htmlize_string(i->text(4)) << "" << htmlize_string(i->text(5)) << "" << htmlize_string(i->text(6)) << "" << htmlize_string(i->text(7)) << "" << htmlize_string(i->text(8)) << "
" << htmlize_string(i18n("Total")) << "" << htmlize_string(KGlobal::locale()->formatMoney(total_value)) << "--" << htmlize_string(KGlobal::locale()->formatMoney(total_cost)) << "" << htmlize_string(KGlobal::locale()->formatMoney(total_profit)) << "" << htmlize_string(KGlobal::locale()->formatNumber(total_rate * 100) + "%") << "--
" << '\n'; outf << "\t" << '\n'; outf << "" << '\n'; break; } case 'c': { outf.setEncoding(QTextStream::Locale); outf << "\"" << scheduleView->columnText(0) << "\",\"" << scheduleView->columnText(1) << "\",\"" << scheduleView->columnText(2) << "\",\"" << scheduleView->columnText(3) << "\",\"" << scheduleView->columnText(4) << "\",\"" << scheduleView->columnText(5) << "\",\"" << scheduleView->columnText(6) << "\",\"" << scheduleView->columnText(7) << "\",\"" << scheduleView->columnText(8) << "\"\n"; SecurityListViewItem *i = (SecurityListViewItem*) securitiesView->firstChild(); while(i) { outf << "\"" << i->text(0) << "\",\"" << i->text(1) << "\",\"" << i->text(2) << "\",\"" << i->text(3) << "\",\"" << i->text(4) << "\",\"" << i->text(5) << "\",\"" << i->text(6) << "\",\"" << i->text(7) << "\",\"" << i->text(8) << '\n'; i = (SecurityListViewItem*) i->nextSibling(); } break; } } return true; } bool Eqonomize::exportAccountsList(QTextStream &outf, int fileformat) { switch(fileformat) { case 'h': { outf.setEncoding(QTextStream::UnicodeUTF8); outf << "" << '\n'; outf << "" << '\n'; outf << "\t" << '\n'; outf << "\t\t"; outf << i18n("html format", "Accounts & Categories"); outf << "" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t" << '\n'; outf << "\t" << '\n'; outf << "\t" << '\n'; if(accountsPeriodFromButton->isChecked()) outf << "\t\t

" << i18n("html format", "Accounts & Categories (%1–%2)").arg(htmlize_string(KGlobal::locale()->formatDate(from_date, true))).arg(htmlize_string(KGlobal::locale()->formatDate(to_date, true))) << "

" << '\n'; else outf << "\t\t

" << i18n("html format", "Accounts & Categories (to %1)").arg(htmlize_string(KGlobal::locale()->formatDate(to_date, true))) << "

" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << "" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; if(includes_budget) { outf << "\t\t\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; } outf << "\t\t\t" << '\n'; Account *account = budget->assetsAccounts.first(); while(account) { outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; account = budget->assetsAccounts.next(); } outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t
"; outf << htmlize_string(i18n("Accounts")); outf << "
" << htmlize_string(i18n("Name")) << "" << htmlize_string(i18n("Type")) << "" << htmlize_string(i18n("Change")); bool includes_budget = (to_date > QDate::currentDate() && (expenses_budget >= 0.0 || incomes_budget >= 0.0)); if(includes_budget) outf << "*"; outf << "" << htmlize_string(i18n("Balance")); if(includes_budget) outf << "*"; outf << "
" << ""; outf << "*" << htmlize_string(i18n("Includes budgeted transactions")); outf << "" << "
" << htmlize_string(account->name()); if(includes_budget && ((AssetsAccount*) account)->isBudgetAccount()) outf << "*"; outf << ""; switch(((AssetsAccount*) account)->accountType()) { case ASSETS_TYPE_CURRENT: {outf << htmlize_string(i18n("Current Account")); break;} case ASSETS_TYPE_SAVINGS: {outf << htmlize_string(i18n("Savings Account")); break;} case ASSETS_TYPE_CREDIT_CARD: {outf << htmlize_string(i18n("Credit Card")); break;} case ASSETS_TYPE_LIABILITIES: {outf << htmlize_string(i18n("Liabilities")); break;} case ASSETS_TYPE_SECURITIES: {outf << htmlize_string(i18n("Securities")); break;} default: {outf << htmlize_string(i18n("Cash")); break;} } outf << "" << htmlize_string(KGlobal::locale()->formatMoney(account_change[account])) << "" << htmlize_string(KGlobal::locale()->formatMoney(account_value[account])) << "
" << htmlize_string(i18n("Total")); if(includes_budget) outf << "*"; outf << ""; outf << "" << htmlize_string(KGlobal::locale()->formatMoney(assets_accounts_change)) << "" << htmlize_string(KGlobal::locale()->formatMoney(assets_accounts_value)) << "
" << '\n'; outf << "\t\t
" << '\n'; outf << "\t\t
" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << "" << '\n'; outf << "" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; account = budget->incomesAccounts.first(); while(account) { outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; if(account_budget[account] < 0.0) { outf << ""; outf << ""; } else { outf << ""; outf << ""; } outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; account = budget->incomesAccounts.next(); } outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; if(incomes_budget >= 0.0) { outf << ""; outf << ""; } else { outf << ""; outf << ""; } outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t
"; outf << htmlize_string(i18n("Incomes")); outf << "
" << htmlize_string(i18n("Category")) << "" << htmlize_string(i18n("Budget")) << "" << htmlize_string(i18n("Remaining Budget")) << "" << htmlize_string(i18n("Change")) << "" << htmlize_string(i18n("Total Incomes")) << "
" << htmlize_string(account->name()) << "--"; outf << htmlize_string(KGlobal::locale()->formatMoney(account_budget[account])); outf << ""; outf << htmlize_string(KGlobal::locale()->formatMoney(account_budget_diff[account])); outf << "" << htmlize_string(KGlobal::locale()->formatMoney(account_change[account])) << "" << htmlize_string(KGlobal::locale()->formatMoney(account_value[account])) << "
" << htmlize_string(i18n("Total")) << "" << htmlize_string(KGlobal::locale()->formatMoney(incomes_budget)) << "" << htmlize_string(KGlobal::locale()->formatMoney(incomes_budget_diff)) << "" << "-" << "" << "-" << "" << htmlize_string(KGlobal::locale()->formatMoney(incomes_accounts_change)) << "" << htmlize_string(KGlobal::locale()->formatMoney(incomes_accounts_value)) << "
" << '\n'; outf << "\t\t
" << '\n'; outf << "\t\t
" << '\n'; outf << "\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; outf << ""; outf << ""; outf << "" << '\n'; outf << "" << '\n'; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; account = budget->expensesAccounts.first(); while(account) { outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; if(account_budget[account] < 0.0) { outf << ""; outf << ""; } else { outf << ""; outf << ""; } outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; account = budget->expensesAccounts.next(); } outf << "\t\t\t\t" << '\n'; outf << "\t\t\t\t\t"; if(expenses_budget >= 0.0) { outf << ""; outf << ""; } else { outf << ""; outf << ""; } outf << ""; outf << "" << "\n"; outf << "\t\t\t\t" << '\n'; outf << "\t\t\t" << '\n'; outf << "\t\t
"; outf << htmlize_string(i18n("Costs")); outf << "
" << htmlize_string(i18n("Category")) << "" << htmlize_string(i18n("Budget")) << "" << htmlize_string(i18n("Remaining Budget")) << "" << htmlize_string(i18n("Change")) << "" << htmlize_string(i18n("Total Expenses")) << "
" << htmlize_string(account->name()) << "--"; outf << htmlize_string(KGlobal::locale()->formatMoney(account_budget[account])); outf << ""; outf << htmlize_string(KGlobal::locale()->formatMoney(account_budget_diff[account])); outf << "" << htmlize_string(KGlobal::locale()->formatMoney(account_change[account])) << "" << htmlize_string(KGlobal::locale()->formatMoney(account_value[account])) << "
" << htmlize_string(i18n("Total")) << "" << htmlize_string(KGlobal::locale()->formatMoney(expenses_budget)) << "" << htmlize_string(KGlobal::locale()->formatMoney(expenses_budget_diff)) << "" << "-" << "" << "-" << "" << htmlize_string(KGlobal::locale()->formatMoney(expenses_accounts_change)) << "" << htmlize_string(KGlobal::locale()->formatMoney(expenses_accounts_value)) << "
" << '\n'; outf << "\t" << '\n'; outf << "" << '\n'; break; } case 'c': { outf.setEncoding(QTextStream::Locale); outf << "\"" << i18n("Account/Category") << "\",\"" << i18n("Change") << "\",\"" << i18n("Value") << "\"\n"; Account *account = budget->assetsAccounts.first(); while(account) { outf << "\"" << account->name() << "\",\"" << KGlobal::locale()->formatMoney(account_change[account]) << "\",\"" << KGlobal::locale()->formatMoney(account_value[account]) << "\"\n"; account = budget->assetsAccounts.next(); } account = budget->incomesAccounts.first(); while(account) { outf << "\"" << account->name() << "\",\"" << KGlobal::locale()->formatMoney(account_change[account]) << "\",\"" << KGlobal::locale()->formatMoney(account_value[account]) << "\"\n"; account = budget->incomesAccounts.next(); } account = budget->expensesAccounts.first(); while(account) { outf << "\"" << account->name() << "\",\"" << KGlobal::locale()->formatMoney(account_change[account]) << "\",\"" << KGlobal::locale()->formatMoney(account_value[account]) << "\"\n"; account = budget->expensesAccounts.next(); } break; } } return true; } void Eqonomize::printView() { switch(tabs->activePageIndex()) { case 0: {break;} case 1: { if(expensesWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty expenses list.")); return; } break; } case 2: { if(incomesWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty incomes list.")); return; } break; } case 3: { if(transfersWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty transfers list.")); return; } break; } case 4: { if(securitiesView->childCount() == 0) { KMessageBox::error(this, i18n("Empty securities list.")); return; } break; } case 5: { if(scheduleView->childCount() == 0) { KMessageBox::error(this, i18n("Empty schedule list.")); return; } break; } } QString str; QTextOStream stream(&str); saveView(stream, 'h'); KHTMLPart *htmlpart = new KHTMLPart(this); htmlpart->begin(); htmlpart->write(str); htmlpart->end(); htmlpart->view()->print(); delete htmlpart; } bool Eqonomize::saveView(QTextStream &file, int fileformat) { switch(tabs->activePageIndex()) { case 0: {return exportAccountsList(file, fileformat);} case 1: {return expensesWidget->exportList(file, fileformat);} case 2: {return incomesWidget->exportList(file, fileformat);} case 3: {return transfersWidget->exportList(file, fileformat);} case 4: {return exportSecuritiesList(file, fileformat);} case 5: {return exportScheduleList(file, fileformat);} } return false; } void Eqonomize::saveView() { switch(tabs->activePageIndex()) { case 0: {break;} case 1: { if(expensesWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty expenses list.")); return; } break; } case 2: { if(incomesWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty incomes list.")); return; } break; } case 3: { if(transfersWidget->isEmpty()) { KMessageBox::error(this, i18n("Empty transfers list.")); return; } break; } case 4: { if(securitiesView->childCount() == 0) { KMessageBox::error(this, i18n("Empty securities list.")); return; } break; } case 5: { if(scheduleView->childCount() == 0) { KMessageBox::error(this, i18n("Empty schedule list.")); return; } break; } } KFileDialog *dialog = new KFileDialog(QString::null, QString::null, this, NULL, true); QStringList filter; filter << "text/html" << "text/x-csv"; dialog->setMimeFilter(filter, "text/html"); dialog->setOperationMode(KFileDialog::Saving); dialog->setMode(KFile::File); if(dialog->exec() != QDialog::Accepted) {dialog->deleteLater(); return;} KURL url = dialog->selectedURL(); char filetype = 'h'; if(dialog->currentMimeFilter() == "text/x-csv") filetype = 'c'; dialog->deleteLater(); if(url.isEmpty() && url.isValid()) return; if(url.isLocalFile()) { if(QFile::exists(url.path())) { if(KMessageBox::warningYesNo(this, i18n("The selected file already exists. Would you like to overwrite the old copy?")) != KMessageBox::Yes) return; } QFileInfo info(url.path()); if(info.isDir()) { KMessageBox::error(this, i18n("You selected a directory!")); return; } KSaveFile ofile(url.path()); if(ofile.status()) { ofile.abort(); KMessageBox::error(this, i18n("Couldn't open file for writing.")); return; } saveView(*ofile.textStream(), filetype); if(ofile.status()) { ofile.abort(); KMessageBox::error(this, i18n("Error while writing file; file was not saved.")); return; } ofile.close(); if(ofile.status()) { KMessageBox::error(this, i18n("Error after saving file; data may not have been saved.")); return; } return; } KTempFile tf; tf.setAutoDelete(true); if(saveView(*tf.textStream(), filetype)) { if(!KIO::NetAccess::upload(tf.name(), url, this)) { KMessageBox::error(this, i18n("Failed to upload file to %1.").arg(url.prettyURL())); } } } void Eqonomize::setupActions() { KStdAction::openNew(this, SLOT(fileNew()), actionCollection()); KStdAction::open(this, SLOT(fileOpen()), actionCollection()); ActionSave = KStdAction::save(this, SLOT(fileSave()), actionCollection()); ActionOpenRecent = KStdAction::openRecent(this, SLOT(fileOpenRecent(const KURL&)), actionCollection()); KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection()); KStdAction::quit(this, SLOT(close()), actionCollection()); ActionFileReload = KStdAction::revert(this, SLOT(fileReload()), actionCollection()); ActionSaveView = new KAction(i18n("Export View..."), "filesave", 0, this, SLOT(saveView()), actionCollection(), "save_view"); ActionPrintView = KStdAction::print(this, SLOT(printView()), actionCollection()); ActionPrintView->setText(i18n("Print View...")); ActionSelectInitialPeriod = new KSelectAction(i18n("Initial Period"), 0, actionCollection(), "select_initial_period"); QStringList period_list; period_list << i18n("Current Month"); period_list << i18n("Current Year"); period_list << i18n("Current Whole Month"); period_list << i18n("Current Whole Year"); period_list << i18n("Remember Last Dates"); ActionSelectInitialPeriod->setItems(period_list); ActionImportCSV = new KAction(i18n("Import CSV File..."), "fileimport", 0, this, SLOT(importCSV()), actionCollection(), "import_csv"); ActionImportQIF = new KAction(i18n("Import QIF File..."), "fileimport", 0, this, SLOT(importQIF()), actionCollection(), "import_qif"); ActionExportQIF = new KAction(i18n("Export As QIF File..."), "filesave", 0, this, SLOT(exportQIF()), actionCollection(), "export_qif"); ActionAddAccount = new KAction(i18n("Add Account..."), "filenew", 0, this, SLOT(addAccount()), actionCollection(), "add_account"); ActionNewAssetsAccount = new KAction(i18n("New Account..."), "filenew", 0, this, SLOT(newAssetsAccount()), actionCollection(), "new_assets_account"); ActionNewIncomesAccount = new KAction(i18n("New Income Category..."), "filenew", 0, this, SLOT(newIncomesAccount()), actionCollection(), "new_incomes_account"); ActionNewExpensesAccount = new KAction(i18n("New Expense Category..."), "filenew", 0, this, SLOT(newExpensesAccount()), actionCollection(), "new_expenses_account"); ActionBalanceAccount = new KAction(i18n("Balance..."), "edit", 0, this, SLOT(balanceAccount()), actionCollection(), "balance_account"); ActionEditAccount = new KAction(i18n("Edit..."), "edit", 0, this, SLOT(editAccount()), actionCollection(), "edit_account"); ActionDeleteAccount = new KAction(i18n("Remove"), "editdelete", 0, this, SLOT(deleteAccount()), actionCollection(), "delete_account"); ActionShowAccountTransactions = new KAction(i18n("Show Transactions"), 0, this, SLOT(showAccountTransactions()), actionCollection(), "show_account_transactions"); ActionNewExpense = new KAction(i18n("New Expense..."), "filenew", CTRL+Key_E, this, SLOT(newScheduledExpense()), actionCollection(), "new_expense"); ActionNewIncome = new KAction(i18n("New Income..."), "filenew", CTRL+Key_I, this, SLOT(newScheduledIncome()), actionCollection(), "new_income"); ActionNewTransfer = new KAction(i18n("New Transfer..."), "filenew", CTRL+Key_T, this, SLOT(newScheduledTransfer()), actionCollection(), "new_transfer"); ActionNewSplitTransaction = new KAction(i18n("New Split Transaction..."), "filenew", 0, this, SLOT(newSplitTransaction()), actionCollection(), "new_split_transaction"); ActionEditTransaction = new KAction(i18n("Edit Transaction(s) (Occurrence)..."), "edit", 0, this, SLOT(editSelectedTransaction()), actionCollection(), "edit_transaction"); ActionEditScheduledTransaction = new KAction(i18n("Edit Schedule (Recurrence)..."), "edit", 0, this, SLOT(editSelectedScheduledTransaction()), actionCollection(), "edit_scheduled_transaction"); ActionDeleteTransaction = new KAction(i18n("Remove Transaction(s) (Occurrence)"), "editdelete", 0, this, SLOT(deleteSelectedTransaction()), actionCollection(), "delete_transaction"); ActionDeleteScheduledTransaction = new KAction(i18n("Delete Schedule (Recurrence)"), "editdelete", 0, this, SLOT(deleteSelectedScheduledTransaction()), actionCollection(), "delete_scheduled_transaction"); ActionEditSplitTransaction = new KAction(i18n("Edit Split Transaction..."), "edit", 0, this, SLOT(editSelectedSplitTransaction()), actionCollection(), "edit_split_transaction"); ActionDeleteSplitTransaction = new KAction(i18n("Remove Split Transaction"), "editdelete", 0, this, SLOT(deleteSelectedSplitTransaction()), actionCollection(), "delete_split_transaction"); ActionJoinTransactions = new KAction(i18n("Join Transactions..."), 0, this, SLOT(joinSelectedTransactions()), actionCollection(), "joins_transactions"); ActionSplitUpTransaction = new KAction(i18n("Split Up Transaction"), 0, this, SLOT(splitUpSelectedTransaction()), actionCollection(), "split_up_transaction"); ActionNewRefund = new KAction(i18n("Refund..."), "forward", 0, this, SLOT(newRefund()), actionCollection(), "new_refund"); ActionNewRepayment = new KAction(i18n("Repayment..."), "back", 0, this, SLOT(newRepayment()), actionCollection(), "new_repayment"); ActionNewRefundRepayment = new KAction(i18n("New Refund/Repayment..."), "filenew", 0, this, SLOT(newRefundRepayment()), actionCollection(), "new_refund_repayment"); ActionNewSecurity = new KAction(i18n("New Security..."), "filenew", 0, this, SLOT(newSecurity()), actionCollection(), "new_security"); ActionEditSecurity = new KAction(i18n("Edit Security..."), "edit", 0, this, SLOT(editSecurity()), actionCollection(), "edit_security"); ActionDeleteSecurity = new KAction(i18n("Remove Security"), "editdelete", 0, this, SLOT(deleteSecurity()), actionCollection(), "delete_security"); ActionSellShares = new KAction(i18n("Shares Sold..."), "forward", 0, this, SLOT(sellSecurities()), actionCollection(), "sell_shares"); ActionBuyShares = new KAction(i18n("Shares Bought..."), "back", 0, this, SLOT(buySecurities()), actionCollection(), "buy_shares"); ActionNewDividend = new KAction(i18n("Dividend..."), "forward", 0, this, SLOT(newDividend()), actionCollection(), "new_dividend"); ActionNewReinvestedDividend = new KAction(i18n("Reinvested Dividend..."), "forward", 0, this, SLOT(newReinvestedDividend()), actionCollection(), "new_reinvested_dividend"); ActionNewSecurityTrade = new KAction(i18n("Shares Moved..."), 0, this, SLOT(newSecurityTrade()), actionCollection(), "new_security_trade"); ActionSetQuotation = new KAction(i18n("Set Quotation..."), "edit", 0, this, SLOT(setQuotation()), actionCollection(), "set_quotation"); ActionEditQuotations = new KAction(i18n("Edit Quotations..."), "edit", 0, this, SLOT(editQuotations()), actionCollection(), "edit_quotations"); ActionEditSecurityTransactions = new KAction(i18n("Transactions..."), "edit", 0, this, SLOT(editSecurityTransactions()), actionCollection(), "edit_security_transactions"); ActionOverTimeReport = new KAction(i18n("Development Over Time Report..."), 0, this, SLOT(showOverTimeReport()), actionCollection(), "over_time_report"); ActionCategoriesComparisonReport = new KAction(i18n("Categories Comparison Report..."), 0, this, SLOT(showCategoriesComparisonReport()), actionCollection(), "categories_comparison_report"); ActionCategoriesComparisonChart = new KAction(i18n("Categories Comparison Chart..."), 0, this, SLOT(showCategoriesComparisonChart()), actionCollection(), "categories_comparison_chart"); ActionOverTimeChart = new KAction(i18n("Development Over Time Chart..."), 0, this, SLOT(showOverTimeChart()), actionCollection(), "over_time_chart"); ActionExtraProperties = new KToggleAction(i18n("Use Additional Transaction Properties"), 0, actionCollection(), "extra_properties"); ActionExtraProperties->setChecked(b_extra); QObject::connect(ActionExtraProperties, SIGNAL(toggled(bool)), this, SLOT(useExtraProperties(bool))); ActionSave->setEnabled(false); ActionFileReload->setEnabled(false); ActionBalanceAccount->setEnabled(false); ActionEditAccount->setEnabled(false); ActionDeleteAccount->setEnabled(false); ActionShowAccountTransactions->setEnabled(false); ActionEditTransaction->setEnabled(false); ActionDeleteTransaction->setEnabled(false); ActionEditSplitTransaction->setEnabled(false); ActionDeleteSplitTransaction->setEnabled(false); ActionJoinTransactions->setEnabled(false); ActionSplitUpTransaction->setEnabled(false); ActionEditScheduledTransaction->setEnabled(false); ActionDeleteScheduledTransaction->setEnabled(false); ActionNewRefund->setEnabled(false); ActionNewRepayment->setEnabled(false); ActionNewRefundRepayment->setEnabled(false); ActionEditSecurity->setEnabled(false); ActionDeleteSecurity->setEnabled(false); ActionSellShares->setEnabled(true); ActionBuyShares->setEnabled(true); ActionNewDividend->setEnabled(true); ActionNewReinvestedDividend->setEnabled(true); ActionNewSecurityTrade->setEnabled(true); ActionSetQuotation->setEnabled(false); ActionEditQuotations->setEnabled(false); ActionEditSecurityTransactions->setEnabled(false); } bool Eqonomize::crashRecovery(KURL url) { config->setGroup("General Options"); bool b = false; if(url.isLocalFile()) { cr_tmp_file = kapp->checkRecoverFile(url.path(), b); } else if(url.isEmpty()) { cr_tmp_file = kapp->checkRecoverFile("/UNSAVED EQZ", b); } if(b) { if(KMessageBox::questionYesNo(this, i18n("Eqonomize! exited unexpectedly before the file was saved and data was lost.\nDo you want to load the last auto-saved version of the file?"), i18n("Crash Recovery")) == KMessageBox::Yes) { QString errors; QString error = budget->loadFile(cr_tmp_file, errors); if(!error.isNull()) { KMessageBox::error(this, i18n("Error loading %1: %2.").arg(cr_tmp_file).arg(error), i18n("Couldn't open file")); config->sync(); return false; } if(!errors.isEmpty()) { KMessageBox::error(this, errors); } current_url = url; ActionFileReload->setEnabled(true); setCaption(current_url.fileName(), false); QFile file(cr_tmp_file); file.remove(); reloadBudget(); emit accountsModified(); emit transactionsModified(); emit budgetUpdated(); setModified(true); checkSchedule(true); return true; } QFile file(cr_tmp_file); file.remove(); } else { cr_tmp_file = ""; } return false; } void Eqonomize::onAutoSaveTimeout() { auto_save_timeout = true; if(modified_auto_save) { autoSave(); } } void Eqonomize::autoSave() { if(auto_save_timeout) { saveCrashRecovery(); modified_auto_save = false; auto_save_timeout = false; } } void Eqonomize::saveCrashRecovery() { if(cr_tmp_file.isEmpty() && current_url.isEmpty()) { cr_tmp_file = kapp->tempSaveName("/UNSAVED EQZ"); } if(budget->saveFile(cr_tmp_file).isNull()) { config->setGroup("General Options"); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif config->sync(); } } void Eqonomize::saveOptions() { config->setGroup("General Options"); ActionOpenRecent->saveEntries(config); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif config->writeEntry("currentEditExpenseFromItem", expensesWidget->currentEditFromItem()); config->writeEntry("currentEditExpenseToItem", expensesWidget->currentEditToItem()); config->writeEntry("currentEditIncomeFromItem", incomesWidget->currentEditFromItem()); config->writeEntry("currentEditIncomeToItem", incomesWidget->currentEditToItem()); config->writeEntry("currentEditTransferFromItem", transfersWidget->currentEditFromItem()); config->writeEntry("currentEditTransferToItem", transfersWidget->currentEditToItem()); config->writeEntry("useExtraProperties", b_extra); InitialPeriod initial_period = (InitialPeriod) ActionSelectInitialPeriod->currentItem(); config->writeEntry("initialPeriod", initial_period); if(initial_period == INITIAL_PERIOD_LAST) { config->writeEntry("initialFromDate", from_date.toString(Qt::ISODate)); config->writeEntry("initialFromDateEnabled", accountsPeriodFromButton->isChecked()); config->writeEntry("initialToDate", to_date.toString(Qt::ISODate)); } emit timeToSaveConfig(); } void Eqonomize::readFileDependentOptions() { config->setGroup("General Options"); expensesWidget->setCurrentEditFromItem(config->readNumEntry("currentEditExpenseFromItem", 0)); expensesWidget->setCurrentEditToItem(config->readNumEntry("currentEditExpenseToItem", 0)); incomesWidget->setCurrentEditFromItem(config->readNumEntry("currentEditIncomeFromItem", 0)); incomesWidget->setCurrentEditToItem(config->readNumEntry("currentEditIncomeToItem", 0)); transfersWidget->setCurrentEditFromItem(config->readNumEntry("currentEditTransferFromItem", 0)); transfersWidget->setCurrentEditToItem(config->readNumEntry("currentEditTransferToItem", 0)); } void Eqonomize::readOptions() { config->setGroup("General Options"); ActionOpenRecent->loadEntries(config); first_run = config->readBoolEntry("firstRun", true); config->writeEntry("firstRun", false); } void Eqonomize::saveProperties(KConfig*) { } void Eqonomize::readProperties(KConfig*) { } bool Eqonomize::queryClose() { return askSave(true); } bool Eqonomize::queryExit() { saveOptions(); return true; } void Eqonomize::dragEnterEvent(QDragEnterEvent *event) { event->accept(KURLDrag::canDecode(event)); } void Eqonomize::dropEvent(QDropEvent *event) { KURL::List urls; if(KURLDrag::decode(event, urls) && !urls.isEmpty()) { const KURL &url = urls.first(); if(!askSave()) return; openURL(url); } } void Eqonomize::fileNew() { if(!askSave()) return; budget->clear(); reloadBudget(); setCaption(QString::null, false); current_url = ""; ActionFileReload->setEnabled(false); #if KDE_IS_VERSION(3,1,3) config->writePathEntry("lastURL", current_url.url()); #else config->writeEntry("lastURL", current_url.url()); #endif if(!cr_tmp_file.isEmpty()) {QFile file(cr_tmp_file); file.remove(); cr_tmp_file = "";} cr_tmp_file = kapp->tempSaveName("/UNSAVED EQZ"); config->sync(); setModified(false); emit accountsModified(); emit transactionsModified(); emit budgetUpdated(); } void Eqonomize::fileOpen() { if(!askSave()) return; KURL url = KFileDialog::getOpenURL(QString::null, "application/x-eqonomize", this); if(!url.isEmpty()) openURL(url); } void Eqonomize::fileOpenRecent(const KURL &url) { if(!askSave()) return; openURL(url); } void Eqonomize::fileReload() { openURL(current_url); } void Eqonomize::fileSave() { if(!current_url.isValid()) { KURL file_url = KFileDialog::getSaveURL("budget", "application/x-eqonomize", this); if (!file_url.isEmpty() && file_url.isValid()) { saveURL(file_url); } } else { saveURL(current_url); } } void Eqonomize::fileSaveAs() { KURL file_url = KFileDialog::getSaveURL(current_url.directory(), "application/x-eqonomize", this); if (!file_url.isEmpty() && file_url.isValid()) { saveURL(file_url); } } bool Eqonomize::askSave(bool before_exit) { if(!modified) return true; int b_save = 0; if(before_exit && current_url.isValid()) b_save = KMessageBox::warningYesNoCancel(this, i18n("The current file has been modified. Do you want to save it?"), i18n("Warning"), KStdGuiItem::yes(), KStdGuiItem::no(), "saveOnExit"); else b_save = KMessageBox::warningYesNoCancel(this, i18n("The current file has been modified. Do you want to save it?")); if(b_save == KMessageBox::Yes) { if(!current_url.isValid()) { KURL file_url = KFileDialog::getSaveURL("budget", "application/x-eqonomize", this); if (!file_url.isEmpty() && file_url.isValid()) { return saveURL(file_url); } else { return false; } } else { return saveURL(current_url); } } if(b_save == KMessageBox::No) { if(!cr_tmp_file.isEmpty()) {QFile file(cr_tmp_file); file.remove(); cr_tmp_file = "";} return true; } return false; } void Eqonomize::optionsPreferences() { } void Eqonomize::checkSchedule() { checkSchedule(true); } bool Eqonomize::checkSchedule(bool update_display) { bool b = false; ScheduledTransaction *strans = budget->scheduledTransactions.first(); while(strans) { if(strans->firstOccurrence() < QDate::currentDate() || (QTime::currentTime().hour() >= 18 && strans->firstOccurrence() == QDate::currentDate())) { b = true; ConfirmScheduleDialog *dialog = new ConfirmScheduleDialog(b_extra, budget, this, i18n("Confirm Schedule")); dialog->exec(); Transaction *trans = dialog->firstTransaction(); while(trans) { budget->addTransaction(trans); trans = dialog->nextTransaction(); } dialog->deleteLater(); break; } strans = budget->scheduledTransactions.next(); } if(b && update_display) { expensesWidget->transactionsReset(); incomesWidget->transactionsReset(); transfersWidget->transactionsReset(); filterAccounts(); updateScheduledTransactions(); updateSecurities(); emit transactionsModified(); setModified(true); } return b; } void Eqonomize::updateScheduledTransactions() { scheduleView->clear(); ScheduledTransaction *strans = budget->scheduledTransactions.first(); while(strans) { appendScheduledTransaction(strans); strans = budget->scheduledTransactions.next(); } } void Eqonomize::appendScheduledTransaction(ScheduledTransaction *strans) { Transaction *trans = strans->transaction(); QListViewItem *i = new ScheduleListViewItem(strans, strans->firstOccurrence(), scheduleView, KGlobal::locale()->formatDate(strans->firstOccurrence(), true), QString::null, trans->description(), KGlobal::locale()->formatMoney(trans->value()), trans->fromAccount()->name(), trans->toAccount()->name(), trans->comment()); switch(trans->type()) { case TRANSACTION_TYPE_TRANSFER: {i->setText(1, i18n("Transfer")); break;} case TRANSACTION_TYPE_INCOME: { if(((Income*) trans)->security()) i->setText(1, i18n("Dividend")); else i->setText(1, i18n("Income")); break; } case TRANSACTION_TYPE_EXPENSE: {i->setText(1, i18n("Expense")); break;} case TRANSACTION_TYPE_SECURITY_BUY: {i->setText(1, i18n("Security Buy")); break;} case TRANSACTION_TYPE_SECURITY_SELL: {i->setText(1, i18n("Security Sell")); break;} } } void Eqonomize::addAccount() { QListViewItem *i = accountsView->selectedItem(); if(i == NULL) return; if(i == assetsItem || (account_items.contains(i) && (account_items[i]->type() == ACCOUNT_TYPE_ASSETS))) { newAssetsAccount(); } else if(i == incomesItem || (account_items.contains(i) && (account_items[i]->type() == ACCOUNT_TYPE_INCOMES))) { newIncomesAccount(); } else { newExpensesAccount(); } } void Eqonomize::newAssetsAccount() { EditAssetsAccountDialog *dialog = new EditAssetsAccountDialog(budget, this, i18n("New Account")); if(dialog->exec() == QDialog::Accepted) { AssetsAccount *account = dialog->newAccount(); budget->addAccount(account); appendAssetsAccount(account); filterAccounts(); expensesWidget->updateFromAccounts(); incomesWidget->updateToAccounts(); transfersWidget->updateAccounts(); emit accountsModified(); setModified(true); } dialog->deleteLater(); } void Eqonomize::newIncomesAccount() { EditIncomesAccountDialog *dialog = new EditIncomesAccountDialog(budget, this, i18n("New Income Category")); if(dialog->exec() == QDialog::Accepted) { IncomesAccount *account = dialog->newAccount(); budget->addAccount(account); appendIncomesAccount(account); filterAccounts(); incomesWidget->updateFromAccounts(); emit accountsModified(); setModified(true); } dialog->deleteLater(); } void Eqonomize::newExpensesAccount() { EditExpensesAccountDialog *dialog = new EditExpensesAccountDialog(budget, this, i18n("New Expense Category")); if(dialog->exec() == QDialog::Accepted) { ExpensesAccount *account = dialog->newAccount(); budget->addAccount(account); appendExpensesAccount(account); filterAccounts(); expensesWidget->updateToAccounts(); emit accountsModified(); setModified(true); } dialog->deleteLater(); } void Eqonomize::accountExecuted(QListViewItem*) { showAccountTransactions(); } void Eqonomize::accountExecuted(QListViewItem *i, const QPoint&, int c) { if(i == NULL) return; switch(c) { case 0: { if(account_items.contains(i)) { editAccount(account_items[i]); } break; } case 1: { if(account_items.contains(i)) { if(account_items[i]->type() == ACCOUNT_TYPE_ASSETS) { showAccountTransactions(); } else { accountsTabs->setCurrentPage(1); if(budgetEdit->isEnabled()) { budgetEdit->setFocus(); budgetEdit->lineEdit()->selectAll(); } else { budgetButton->setFocus(); } } } break; } case 2: { showAccountTransactions(); break; } case 3: { showAccountTransactions(true); break; } } } void Eqonomize::balanceAccount() { QListViewItem *i = accountsView->selectedItem(); if(!account_items.contains(i)) return; Account *i_account = account_items[i]; balanceAccount(i_account); } void Eqonomize::balanceAccount(Account *i_account) { if(!i_account) return; if(i_account->type() != ACCOUNT_TYPE_ASSETS || ((AssetsAccount*) i_account)->accountType() == ASSETS_TYPE_SECURITIES) return; AssetsAccount *account = (AssetsAccount*) i_account; double book_value = account->initialBalance(); double current_balancing = 0.0; Transaction *trans = budget->transactions.first(); while(trans) { if(trans->fromAccount() == account) { book_value -= trans->value(); if(trans->toAccount() == budget->balancingAccount) current_balancing -= trans->value(); } if(trans->toAccount() == account) { book_value += trans->value(); if(trans->fromAccount() == budget->balancingAccount) current_balancing += trans->value(); } trans = budget->transactions.next(); } KDialogBase *dialog = new KDialogBase(this, 0, true, i18n("Balance Account"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true); dialog->setMainWidget(new QWidget(dialog)); QGridLayout *grid = new QGridLayout(dialog->mainWidget(), 3, 2, 0, dialog->spacingHint()); grid->addWidget(new QLabel(i18n("Book value:"), dialog->mainWidget()), 0, 0); QLabel *label = new QLabel(KGlobal::locale()->formatMoney(book_value), dialog->mainWidget()); label->setAlignment(Qt::AlignRight); grid->addWidget(label, 0, 1); label = new QLabel(QString("of which %1 is balanced").arg(KGlobal::locale()->formatMoney(current_balancing)), dialog->mainWidget()); label->setAlignment(Qt::AlignRight); grid->addWidget(label, 1, 1); grid->addWidget(new QLabel(i18n("Real value:"), dialog->mainWidget()), 2, 0); EqonomizeValueEdit *realEdit = new EqonomizeValueEdit(book_value, true, true, dialog->mainWidget()); grid->addWidget(realEdit, 2, 1); if(dialog->exec() == QDialog::Accepted && realEdit->value() != book_value) { trans = new Balancing(budget, realEdit->value() - book_value, QDate::currentDate(), account); budget->addTransaction(trans); transactionAdded(trans); } dialog->deleteLater(); } void Eqonomize::editAccount() { QListViewItem *i = accountsView->selectedItem(); if(!account_items.contains(i)) return; Account *i_account = account_items[i]; editAccount(i_account); } bool Eqonomize::editAccount(Account *i_account) { return editAccount(i_account, this); } bool Eqonomize::editAccount(Account *i_account, QWidget *parent) { QListViewItem *i = item_accounts[i_account]; switch(i_account->type()) { case ACCOUNT_TYPE_ASSETS: { EditAssetsAccountDialog *dialog = new EditAssetsAccountDialog(budget, parent, i18n("Edit Account")); AssetsAccount *account = (AssetsAccount*) i_account; dialog->setAccount(account); double prev_ib = account->initialBalance(); bool was_budget_account = account->isBudgetAccount(); if(dialog->exec() == QDialog::Accepted) { dialog->modifyAccount(account); if(was_budget_account != account->isBudgetAccount()) { filterAccounts(); } else { account_value[account] += (account->initialBalance() - prev_ib); assets_accounts_value += (account->initialBalance() - prev_ib); if(to_date > QDate::currentDate()) i->setText(0, account->name() + "*"); else i->setText(0, account->name()); i->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(account_value[account], KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); } emit accountsModified(); setModified(true); expensesWidget->updateFromAccounts(); incomesWidget->updateToAccounts(); transfersWidget->updateAccounts(); assetsItem->sortChildItems(0, true); expensesWidget->filterTransactions(); incomesWidget->filterTransactions(); transfersWidget->filterTransactions(); dialog->deleteLater(); return true; } dialog->deleteLater(); break; } case ACCOUNT_TYPE_INCOMES: { EditIncomesAccountDialog *dialog = new EditIncomesAccountDialog(budget, parent, i18n("Edit Income Category")); IncomesAccount *account = (IncomesAccount*) i_account; dialog->setAccount(account); if(dialog->exec() == QDialog::Accepted) { dialog->modifyAccount(account); i->setText(0, account->name()); emit accountsModified(); setModified(true); incomesWidget->updateFromAccounts(); incomesItem->sortChildItems(0, true); incomesWidget->filterTransactions(); dialog->deleteLater(); return true; } dialog->deleteLater(); break; } case ACCOUNT_TYPE_EXPENSES: { EditExpensesAccountDialog *dialog = new EditExpensesAccountDialog(budget, parent, i18n("Edit Expense Category")); ExpensesAccount *account = (ExpensesAccount*) i_account; dialog->setAccount(account); if(dialog->exec() == QDialog::Accepted) { dialog->modifyAccount(account); i->setText(0, account->name()); emit accountsModified(); setModified(true); expensesWidget->updateToAccounts(); expensesItem->sortChildItems(0, true); expensesWidget->filterTransactions(); dialog->deleteLater(); return true; } dialog->deleteLater(); break; } } return false; } void Eqonomize::deleteAccount() { QListViewItem *i = accountsView->selectedItem(); if(!account_items.contains(i)) return; Account *account = account_items[i]; if(!budget->accountHasTransactions(account)) { item_accounts.remove(account); account_items.remove(i); delete i; account_change.remove(account); account_value.remove(account); budget->removeAccount(account); expensesWidget->updateAccounts(); transfersWidget->updateAccounts(); incomesWidget->updateAccounts(); filterAccounts(); emit accountsModified(); setModified(true); } else { QRadioButton *deleteButton = NULL, *moveToButton = NULL; QComboBox *moveToCombo = NULL; QButtonGroup *group = NULL; KDialogBase *dialog = NULL; bool accounts_left = false; QValueVector moveto_accounts; switch(account->type()) { case ACCOUNT_TYPE_EXPENSES: {accounts_left = budget->expensesAccounts.count() > 1; break;} case ACCOUNT_TYPE_INCOMES: {accounts_left = budget->incomesAccounts.count() > 1; break;} case ACCOUNT_TYPE_ASSETS: { AssetsAccount *aaccount = budget->assetsAccounts.first(); while(aaccount) { if(aaccount != budget->balancingAccount && aaccount != account && ((((AssetsAccount*) account)->accountType() == ASSETS_TYPE_SECURITIES) == (aaccount->accountType() == ASSETS_TYPE_SECURITIES))) { accounts_left = true; break; } aaccount = budget->assetsAccounts.next(); } break; } } if(accounts_left) { dialog = new KDialogBase(this, 0, true, i18n("Move transactions?"), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true); dialog->setMainWidget(new QWidget(dialog)); QGridLayout *grid = new QGridLayout(dialog->mainWidget(), 3, 2, 0, dialog->spacingHint()); group = new QButtonGroup(); QLabel *label = NULL; deleteButton = new QRadioButton(i18n("Remove"), dialog->mainWidget()); group->insert(deleteButton); moveToButton = new QRadioButton(i18n("Move to:"), dialog->mainWidget()); group->insert(moveToButton); moveToButton->setChecked(true); moveToCombo = new KComboBox(dialog->mainWidget()); moveToCombo->setEditable(false); switch(account->type()) { case ACCOUNT_TYPE_EXPENSES: { label = new QLabel(i18n("The category contains some expenses.\nWhat do you want to do with them?"), dialog->mainWidget()); ExpensesAccount *eaccount = budget->expensesAccounts.first(); while(eaccount) { if(eaccount != account) { moveToCombo->insertItem(eaccount->name()); moveto_accounts.push_back(eaccount); } eaccount = budget->expensesAccounts.next(); } break; } case ACCOUNT_TYPE_INCOMES: { label = new QLabel(i18n("The category contains some incomes.\nWhat do you want to do with them?"), dialog->mainWidget()); IncomesAccount *iaccount = budget->incomesAccounts.first(); while(iaccount) { if(iaccount != account) { moveToCombo->insertItem(iaccount->name()); moveto_accounts.push_back(iaccount); } iaccount = budget->incomesAccounts.next(); } break; } case ACCOUNT_TYPE_ASSETS: { label = new QLabel(i18n("The account contains some transactions.\nWhat do you want to do with them?"), dialog->mainWidget()); AssetsAccount *aaccount = budget->assetsAccounts.first(); while(aaccount) { if(aaccount != budget->balancingAccount && aaccount != account && ((((AssetsAccount*) account)->accountType() == ASSETS_TYPE_SECURITIES) == (aaccount->accountType() == ASSETS_TYPE_SECURITIES))) { moveToCombo->insertItem(aaccount->name()); moveto_accounts.push_back(aaccount); } aaccount = budget->assetsAccounts.next(); } break; } } grid->addMultiCellWidget(label, 0, 0, 0, 1); grid->addWidget(deleteButton, 1, 0); grid->addWidget(moveToButton, 2, 0); grid->addWidget(moveToCombo, 2, 1); } bool do_delete = false; if(accounts_left) { do_delete = (dialog->exec() == QDialog::Accepted); } else { switch(account->type()) { case ACCOUNT_TYPE_EXPENSES: {do_delete = (KMessageBox::warningYesNo(this, i18n("The category contains some expenses that will be removed. Do you still want to remove the category?"), i18n("Remove Category?")) == KMessageBox::Yes); break;} case ACCOUNT_TYPE_INCOMES: {do_delete = (KMessageBox::warningYesNo(this, i18n("The category contains some incomes that will be removed. Do you still want to remove the category?"), i18n("Remove Category?")) == KMessageBox::Yes); break;} case ACCOUNT_TYPE_ASSETS: {do_delete = (KMessageBox::warningYesNo(this, i18n("The account contains some transactions that will be removed. Do you still want to remove the account?"), i18n("Remove Account?")) == KMessageBox::Yes); break;} } } if(do_delete) { if(accounts_left && moveToButton->isChecked()) { budget->moveTransactions(account, moveto_accounts[moveToCombo->currentItem()]); } item_accounts.remove(account); account_items.remove(i); delete i; account_change.remove(account); account_value.remove(account); AccountType type = account->type(); budget->removeAccount(account); filterAccounts(); updateSecurities(); updateScheduledTransactions(); switch(type) { case ACCOUNT_TYPE_EXPENSES: {expensesWidget->filterTransactions(); break;} case ACCOUNT_TYPE_INCOMES: {incomesWidget->filterTransactions(); break;} case ACCOUNT_TYPE_ASSETS: {incomesWidget->filterTransactions(); expensesWidget->filterTransactions(); transfersWidget->filterTransactions(); break;} } expensesWidget->updateAccounts(); transfersWidget->updateAccounts(); incomesWidget->updateAccounts(); emit accountsModified(); emit transactionsModified(); setModified(true); } if(dialog) dialog->deleteLater(); if(group) delete group; } } void Eqonomize::transactionAdded(Transaction *trans) { addTransactionValue(trans, trans->date(), true); emit transactionsModified(); setModified(true); expensesWidget->onTransactionAdded(trans); incomesWidget->onTransactionAdded(trans); transfersWidget->onTransactionAdded(trans); if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) trans)->security()); } else if(trans->type() == TRANSACTION_TYPE_INCOME && ((Income*) trans)->security()) { updateSecurity(((Income*) trans)->security()); } } void Eqonomize::transactionModified(Transaction *trans, Transaction *oldtrans) { subtractTransactionValue(oldtrans, true); addTransactionValue(trans, trans->date(), true); emit transactionsModified(); setModified(true); expensesWidget->onTransactionModified(trans, oldtrans); incomesWidget->onTransactionModified(trans, oldtrans); transfersWidget->onTransactionModified(trans, oldtrans); if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) trans)->security()); if(((SecurityTransaction*) trans)->security() != ((SecurityTransaction*) oldtrans)->security()) { updateSecurity(((SecurityTransaction*) oldtrans)->security()); } } else if(trans->type() == TRANSACTION_TYPE_INCOME && ((Income*) trans)->security()) { updateSecurity(((Income*) trans)->security()); if(((Income*) trans)->security() != ((Income*) oldtrans)->security()) { updateSecurity(((Income*) oldtrans)->security()); } } } void Eqonomize::transactionRemoved(Transaction *trans) { subtractTransactionValue(trans, true); emit transactionsModified(); setModified(true); expensesWidget->onTransactionRemoved(trans); incomesWidget->onTransactionRemoved(trans); transfersWidget->onTransactionRemoved(trans); if(trans->type() == TRANSACTION_TYPE_SECURITY_BUY || trans->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) trans)->security()); } else if(trans->type() == TRANSACTION_TYPE_INCOME && ((Income*) trans)->security()) { updateSecurity(((Income*) trans)->security()); } } void Eqonomize::scheduledTransactionAdded(ScheduledTransaction *strans) { appendScheduledTransaction(strans); addScheduledTransactionValue(strans, true); emit transactionsModified(); setModified(true); expensesWidget->onScheduledTransactionAdded(strans); incomesWidget->onScheduledTransactionAdded(strans); transfersWidget->onScheduledTransactionAdded(strans); if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY || strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) strans->transaction())->security()); } else if(strans->transaction()->type() == TRANSACTION_TYPE_INCOME && ((Income*) strans->transaction())->security()) { updateSecurity(((Income*) strans->transaction())->security()); } } void Eqonomize::scheduledTransactionModified(ScheduledTransaction *strans, ScheduledTransaction *oldstrans) { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->firstChild(); while(i) { if(i->scheduledTransaction() == strans) { Transaction *trans = strans->transaction(); i->setDate(strans->firstOccurrence()); i->setText(0, KGlobal::locale()->formatDate(i->date(), true)); switch(trans->type()) { case TRANSACTION_TYPE_TRANSFER: {i->setText(1, i18n("Transfer")); break;} case TRANSACTION_TYPE_INCOME: { if(((Income*) trans)->security()) i->setText(1, i18n("Dividend")); else i->setText(1, i18n("Income")); break; } case TRANSACTION_TYPE_EXPENSE: {i->setText(1, i18n("Expense")); break;} case TRANSACTION_TYPE_SECURITY_BUY: {i->setText(1, i18n("Security Buy")); break;} case TRANSACTION_TYPE_SECURITY_SELL: {i->setText(1, i18n("Security Sell")); break;} } i->setText(2, trans->description()); i->setText(3, KGlobal::locale()->formatMoney(trans->value())); i->setText(4, trans->fromAccount()->name()); i->setText(5, trans->toAccount()->name()); i->setText(6, trans->comment()); scheduleView->sort(); break; } i = (ScheduleListViewItem*) i->nextSibling(); } subtractScheduledTransactionValue(oldstrans, true); addScheduledTransactionValue(strans, true); emit transactionsModified(); setModified(true); expensesWidget->onScheduledTransactionModified(strans, oldstrans); incomesWidget->onScheduledTransactionModified(strans, oldstrans); transfersWidget->onScheduledTransactionModified(strans, oldstrans); if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY || strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) strans->transaction())->security()); if(((SecurityTransaction*) strans->transaction())->security() != ((SecurityTransaction*) oldstrans->transaction())->security()) { updateSecurity(((SecurityTransaction*) oldstrans->transaction())->security()); } } else if(strans->transaction()->type() == TRANSACTION_TYPE_INCOME && ((Income*) strans->transaction())->security()) { updateSecurity(((Income*) strans->transaction())->security()); if(((Income*) strans->transaction())->security() != ((Income*) oldstrans->transaction())->security()) { updateSecurity(((Income*) oldstrans->transaction())->security()); } } } void Eqonomize::scheduledTransactionRemoved(ScheduledTransaction *strans) { scheduledTransactionRemoved(strans, strans); } void Eqonomize::scheduledTransactionRemoved(ScheduledTransaction *strans, ScheduledTransaction *old_strans) { ScheduleListViewItem *i = (ScheduleListViewItem*) scheduleView->firstChild(); while(i) { if(i->scheduledTransaction() == strans) { delete i; break; } i = (ScheduleListViewItem*) i->nextSibling(); } subtractScheduledTransactionValue(old_strans, true); emit transactionsModified(); setModified(true); expensesWidget->onScheduledTransactionRemoved(strans); incomesWidget->onScheduledTransactionRemoved(strans); transfersWidget->onScheduledTransactionRemoved(strans); if(strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_BUY || strans->transaction()->type() == TRANSACTION_TYPE_SECURITY_SELL) { updateSecurity(((SecurityTransaction*) strans->transaction())->security()); } else if(strans->transaction()->type() == TRANSACTION_TYPE_INCOME && ((Income*) strans->transaction())->security()) { updateSecurity(((Income*) strans->transaction())->security()); } } void Eqonomize::splitTransactionAdded(SplitTransaction *split) { blockSignals(true); QValueVector::size_type c = split->splits.count(); for(QValueVector::size_type i = 0; i < c; i++) { transactionAdded(split->splits[i]); } blockSignals(false); emit transactionsModified(); } void Eqonomize::splitTransactionRemoved(SplitTransaction *split) { blockSignals(true); QValueVector::size_type c = split->splits.count(); for(QValueVector::size_type i = 0; i < c; i++) { transactionRemoved(split->splits[i]); } blockSignals(false); emit transactionsModified(); } void Eqonomize::appendExpensesAccount(ExpensesAccount *account) { QListViewItem *i = new QListViewItem(expensesItem, account->name(), "-", KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()) + " "); account_items[i] = account; item_accounts[account] = i; account_value[account] = 0.0; account_change[account] = 0.0; expensesItem->sortChildItems(0, true); } void Eqonomize::appendIncomesAccount(IncomesAccount *account) { QListViewItem *i = new QListViewItem(incomesItem, account->name(), "-", KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()) + " "); account_items[i] = account; item_accounts[account] = i; account_value[account] = 0.0; account_change[account] = 0.0; incomesItem->sortChildItems(0, true); } void Eqonomize::appendAssetsAccount(AssetsAccount *account) { QListViewItem *i = new QListViewItem(assetsItem, account->name(), QString::null, KGlobal::locale()->formatNumber(0.0, KGlobal::locale()->fracDigits()), KGlobal::locale()->formatNumber(account->initialBalance(), KGlobal::locale()->fracDigits()) + " "); if(account->isBudgetAccount() && to_date > QDate::currentDate()) i->setText(0, account->name() + "*"); account_items[i] = account; item_accounts[account] = i; account_value[account] = account->initialBalance(); assets_accounts_value += account->initialBalance(); account_change[account] = 0.0; assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->sortChildItems(0, true); } bool Eqonomize::filterTransaction(Transaction *trans) { if(accountsPeriodFromButton->isChecked() && trans->date() < from_date) return true; if(trans->date() > to_date) return true; return false; } void Eqonomize::subtractScheduledTransactionValue(ScheduledTransaction *strans, bool update_value_display) { addScheduledTransactionValue(strans, update_value_display, true); } void Eqonomize::addScheduledTransactionValue(ScheduledTransaction *strans, bool update_value_display, bool subtract) { if(!strans->recurrence()) return addTransactionValue(strans->transaction(), strans->transaction()->date(), update_value_display, subtract, -1, -1, NULL); Recurrence *rec = strans->recurrence(); QDate curdate = rec->firstOccurrence(); int b_future = 1; if(to_date <= QDate::currentDate()) b_future = 0; else if(strans->transaction()->date() <= QDate::currentDate()) b_future = -1; while(!curdate.isNull() && curdate <= to_date) { addTransactionValue(strans->transaction(), curdate, update_value_display, subtract, 1, b_future, NULL); curdate = rec->nextOccurrence(curdate); } } void Eqonomize::subtractTransactionValue(Transaction *trans, bool update_value_display) { addTransactionValue(trans, trans->date(), update_value_display, true); } void Eqonomize::addTransactionValue(Transaction *trans, const QDate &transdate, bool update_value_display, bool subtract, int n, int b_future, const QDate *monthdate) { if(n == 0) return; bool b_filter_to = n < 0 && transdate > to_date; bool b_from = accountsPeriodFromButton->isChecked(); bool b_lastmonth = false; QDate date; if(b_filter_to) { if(!monthdate) { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); if(calSys->year(transdate) != calSys->year(to_date) || calSys->month(transdate) != calSys->month(to_date)) return; } else { if(transdate > *monthdate) return; } b_lastmonth = true; } bool b_filter = !b_lastmonth && b_from && transdate < from_date; bool b_curmonth = false; bool b_firstmonth = false; const KCalendarSystem *calSys = KGlobal::locale()->calendar(); if(!b_lastmonth && b_future < 0) { if(to_date <= QDate::currentDate()) { b_future = 0; } else { b_future = (transdate > QDate::currentDate()); if(!b_future) { QDate curdate = QDate::currentDate(); if(calSys->year(curdate) == calSys->year(transdate) && calSys->month(curdate) == calSys->month(transdate)) { b_curmonth = true; b_future = true; } } } } else if(!b_lastmonth && b_future) { b_curmonth = (transdate <= QDate::currentDate()); } if(b_from && !b_lastmonth && b_filter && !frommonth_begin.isNull()) { if(transdate >= frommonth_begin) b_firstmonth = true; } bool balfrom = false; bool balto = false; double value = subtract ? -trans->value() : trans->value(); if(!monthdate) { calSys->setYMD(date, calSys->year(transdate), calSys->month(transdate), calSys->daysInMonth(transdate)); monthdate = &date; } if(n > 1) value *= n; switch(trans->fromAccount()->type()) { case ACCOUNT_TYPE_EXPENSES: { if(b_lastmonth) { account_month_endlast[trans->fromAccount()] -= value; account_month[trans->fromAccount()][*monthdate] -= value; if(update_value_display) { updateMonthlyBudget(trans->fromAccount()); updateTotalMonthlyExpensesBudget(); } break; } bool update_month_display = false; if(b_firstmonth) { account_month_beginfirst[trans->fromAccount()] -= value; update_month_display = true; } if(b_curmonth) { account_month_begincur[trans->fromAccount()] -= value; update_month_display = true; } if(b_future || (!frommonth_begin.isNull() && transdate >= frommonth_begin) || (!prevmonth_begin.isNull() && transdate >= prevmonth_begin)) { account_month[trans->fromAccount()][*monthdate] -= value; update_month_display = true; } if(update_value_display && update_month_display) { updateMonthlyBudget(trans->fromAccount()); updateTotalMonthlyExpensesBudget(); } account_value[trans->fromAccount()] -= value; expenses_accounts_value -= value; if(!b_filter) { account_change[trans->fromAccount()] -= value; expenses_accounts_change -= value; if(update_value_display) { expensesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_change, KGlobal::locale()->fracDigits())); } } if(update_value_display) { expensesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } case ACCOUNT_TYPE_INCOMES: { if(b_lastmonth) { account_month_endlast[trans->fromAccount()] += value; account_month[trans->fromAccount()][*monthdate] += value; if(update_value_display) { updateMonthlyBudget(trans->fromAccount()); updateTotalMonthlyIncomesBudget(); } break; } bool update_month_display = false; if(b_firstmonth) { account_month_beginfirst[trans->fromAccount()] += value; update_month_display = true; } if(b_curmonth) { account_month_begincur[trans->fromAccount()] += value; update_month_display = true; } if(b_future || (!frommonth_begin.isNull() && transdate >= frommonth_begin) || (!prevmonth_begin.isNull() && transdate >= prevmonth_begin)) { account_month[trans->fromAccount()][*monthdate] += value; update_month_display = true; } if(update_value_display && update_month_display) { updateMonthlyBudget(trans->fromAccount()); updateTotalMonthlyIncomesBudget(); } account_value[trans->fromAccount()] += value; incomes_accounts_value += value; if(!b_filter) { account_change[trans->fromAccount()] += value; incomes_accounts_change += value; if(update_value_display) { incomesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_change, KGlobal::locale()->fracDigits())); } } if(update_value_display) { incomesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } case ACCOUNT_TYPE_ASSETS: { if(b_lastmonth) break; if(((AssetsAccount*) trans->fromAccount())->accountType() == ASSETS_TYPE_SECURITIES) { if(update_value_display) { updateSecurityAccount((AssetsAccount*) trans->fromAccount(), false); assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); item_accounts[trans->fromAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->fromAccount()], KGlobal::locale()->fracDigits())); } break; } balfrom = (trans->fromAccount() == budget->balancingAccount); if(!balfrom) { account_value[trans->fromAccount()] -= value; assets_accounts_value -= value; if(!b_filter) { account_change[trans->fromAccount()] -= value; assets_accounts_change -= value; if(update_value_display) { assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); item_accounts[trans->fromAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->fromAccount()], KGlobal::locale()->fracDigits())); } } if(update_value_display) assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } } switch(trans->toAccount()->type()) { case ACCOUNT_TYPE_EXPENSES: { if(b_lastmonth) { account_month_endlast[trans->toAccount()] += value; account_month[trans->toAccount()][*monthdate] += value; if(update_value_display) { updateMonthlyBudget(trans->toAccount()); updateTotalMonthlyExpensesBudget(); } break; } bool update_month_display = false; if(b_firstmonth) { account_month_beginfirst[trans->toAccount()] += value; update_month_display = true; } if(b_curmonth) { account_month_begincur[trans->toAccount()] += value; update_month_display = true; } if(b_future || (!frommonth_begin.isNull() && transdate >= frommonth_begin) || (!prevmonth_begin.isNull() && transdate >= prevmonth_begin)) { account_month[trans->toAccount()][*monthdate] += value; update_month_display = true; } if(update_value_display && update_month_display) { updateMonthlyBudget(trans->toAccount()); updateTotalMonthlyExpensesBudget(); } account_value[trans->toAccount()] += value; expenses_accounts_value += value; if(!b_filter) { account_change[trans->toAccount()] += value; expenses_accounts_change += value; if(update_value_display) { expensesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_change, KGlobal::locale()->fracDigits())); } } if(update_value_display) { expensesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } case ACCOUNT_TYPE_INCOMES: { if(b_lastmonth) { account_month_endlast[trans->toAccount()] -= value; account_month[trans->toAccount()][*monthdate] -= value; if(update_value_display) { updateMonthlyBudget(trans->toAccount()); updateTotalMonthlyIncomesBudget(); } break; } bool update_month_display = false; if(b_firstmonth) { account_month_beginfirst[trans->toAccount()] -= value; update_month_display = true; } if(b_curmonth) { account_month_begincur[trans->toAccount()] -= value; update_month_display = true; } if(b_future || (!frommonth_begin.isNull() && transdate >= frommonth_begin) || (!prevmonth_begin.isNull() && transdate >= prevmonth_begin)) { account_month[trans->toAccount()][*monthdate] -= value; update_month_display = true; } if(update_value_display && update_month_display) { updateMonthlyBudget(trans->toAccount()); updateTotalMonthlyIncomesBudget(); } account_value[trans->toAccount()] -= value; incomes_accounts_value -= value; if(!b_filter) { account_change[trans->toAccount()] -= value; incomes_accounts_change -= value; if(update_value_display) { incomesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_change, KGlobal::locale()->fracDigits())); } } if(update_value_display) { incomesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } case ACCOUNT_TYPE_ASSETS: { if(b_lastmonth) break; if(((AssetsAccount*) trans->toAccount())->accountType() == ASSETS_TYPE_SECURITIES) { if(update_value_display) { updateSecurityAccount((AssetsAccount*) trans->toAccount(), false); assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); item_accounts[trans->toAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->toAccount()], KGlobal::locale()->fracDigits())); } break; } balto = (trans->toAccount() == budget->balancingAccount); if(!balto) { account_value[trans->toAccount()] += value; assets_accounts_value += value; if(!b_filter) { account_change[trans->toAccount()] += value; assets_accounts_change += value; if(update_value_display) { assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); item_accounts[trans->toAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->toAccount()], KGlobal::locale()->fracDigits())); } } if(update_value_display) assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); } break; } } if(update_value_display && !b_lastmonth) { if(!balfrom) { item_accounts[trans->fromAccount()]->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(account_value[trans->fromAccount()], KGlobal::locale()->fracDigits()) + " "); item_accounts[trans->fromAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->fromAccount()], KGlobal::locale()->fracDigits())); } if(!balto) { item_accounts[trans->toAccount()]->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(account_value[trans->toAccount()], KGlobal::locale()->fracDigits()) + " "); item_accounts[trans->toAccount()]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[trans->toAccount()], KGlobal::locale()->fracDigits())); } } } void Eqonomize::updateTotalMonthlyExpensesBudget() { if(budget->expensesAccounts.count() > 0) { expenses_budget = 0.0; expenses_budget_diff = 0.0; ExpensesAccount *eaccount = budget->expensesAccounts.first(); bool b_budget = false; while(eaccount) { double d = account_budget[eaccount]; if(d >= 0.0) { expenses_budget += d; expenses_budget_diff += account_budget_diff[eaccount]; b_budget = true; } eaccount = budget->expensesAccounts.next(); } if(b_budget) { expensesItem->setText(BUDGET_COLUMN, i18n("%1: budget; %2: remaining budget", "%2 of %1").arg(KGlobal::locale()->formatNumber(expenses_budget, KGlobal::locale()->fracDigits())).arg(KGlobal::locale()->formatNumber(expenses_budget_diff, KGlobal::locale()->fracDigits()))); return; } else { expenses_budget = -1.0; } } expensesItem->setText(BUDGET_COLUMN, "-"); } void Eqonomize::updateTotalMonthlyIncomesBudget() { if(budget->incomesAccounts.count() > 0) { incomes_budget = 0.0; incomes_budget_diff = 0.0; IncomesAccount *iaccount = budget->incomesAccounts.first(); bool b_budget = false; while(iaccount) { double d = account_budget[iaccount]; if(d >= 0.0) { incomes_budget += d; incomes_budget_diff += account_budget_diff[iaccount]; b_budget = true; } iaccount = budget->incomesAccounts.next(); } if(b_budget) { incomesItem->setText(BUDGET_COLUMN, i18n("%1: budget; %2: remaining budget", "%2 of %1").arg(KGlobal::locale()->formatNumber(incomes_budget, KGlobal::locale()->fracDigits())).arg(KGlobal::locale()->formatNumber(incomes_budget_diff, KGlobal::locale()->fracDigits()))); return; } else { incomes_budget = -1.0; } } incomesItem->setText(BUDGET_COLUMN, "-"); } void Eqonomize::updateMonthlyBudget(Account *account) { if(account->type() == ACCOUNT_TYPE_ASSETS) return; CategoryAccount *ca = (CategoryAccount*) account; double mbudget = 0.0; QListViewItem *i = item_accounts[account]; QMap::const_iterator it = ca->mbudgets.begin(); QMap::const_iterator it_e = ca->mbudgets.end(); while(it != it_e && it.data() < 0.0) ++it; if(it == it_e || it.key() > to_date) { i->setText(BUDGET_COLUMN, "-"); account_budget[account] = -1.0; } else { const KCalendarSystem *calSys = KGlobal::locale()->calendar(); bool after_from = false; QDate monthdate, monthend, curdate = QDate::currentDate(), curmonth, frommonth; frommonth = frommonth_begin; if(!accountsPeriodFromButton->isChecked() || frommonth <= it.key()) { after_from = true; } else { it = ca->mbudgets.find(frommonth); if(it == it_e) { QMap::const_iterator it_b = ca->mbudgets.begin(); --it; while(it != it_b) { if(frommonth > it.key()) break; --it; } } } double diff = 0.0, future_diff = 0.0, future_change_diff = 0.0, m = 0.0, v = 0.0; QDate monthlast; calSys->setYMD(monthlast, calSys->year(to_date), calSys->month(to_date), 1); QMap::const_iterator it_n = it; ++it_n; bool has_budget = false; bool b_firstmonth = !after_from && (monthdate != frommonth); monthdate = frommonth; do { m = it.data(); if(m >= 0.0) { monthend = calSys->addDays(monthdate, calSys->daysInMonth(monthdate) - 1); has_budget = true; bool b_lastmonth = (monthlast == monthdate && to_date != monthend); v = account_month[account][monthend]; if(partial_budget && (b_firstmonth || b_lastmonth)) { int day = 1; if(b_firstmonth) day = calSys->day(from_date); int dim = calSys->day(monthend); int day2 = dim; if(b_lastmonth) day2 = calSys->day(to_date); m = (m * (day2 - day + 1)) / dim; if(b_firstmonth) v -= account_month_beginfirst[account]; if(b_lastmonth) v -= account_month_endlast[account]; } mbudget += m; diff += m - v; b_firstmonth = false; } monthdate = addMonths(monthdate, 1); if(it_n != it_e && monthdate == it_n.key()) { it = it_n; ++it_n; } } while(monthdate <= monthlast); bool b_future = (curdate < to_date); curdate = calSys->addDays(curdate, 1); if(b_future) { bool after_cur = false; it = ca->mbudgets.begin(); while(it != it_e && it.data() < 0.0) ++it; if(curdate < it.key()) { curmonth = it.key(); after_cur = true; } else { calSys->setYMD(curmonth, calSys->year(curdate), calSys->month(curdate), 1); it = ca->mbudgets.find(curmonth); if(it == it_e) { QMap::const_iterator it_b = ca->mbudgets.begin(); --it; while(it != it_b) { if(curmonth > it.key()) break; --it; } } } it_n = it; ++it_n; bool had_from = after_from || from_date <= curdate; bool b_curmonth = !after_cur && (curmonth != curdate); do { m = it.data(); if(m >= 0.0) { monthend = calSys->addDays(curmonth, calSys->daysInMonth(curmonth) - 1); v = account_month[account][monthend]; bool b_lastmonth = (monthlast == curmonth && to_date != monthend); bool b_frommonth = !had_from && frommonth == curmonth; if(partial_budget && (b_curmonth || b_lastmonth || b_frommonth)) { int day = 1; if(b_curmonth) { v -= account_month_begincur[account]; day = calSys->day(curdate); } int dim = calSys->day(monthend); int day2; if(b_lastmonth) { v -= account_month_endlast[account]; day2 = calSys->day(to_date); } else { day2 = dim; } m = (m * (day2 - day + 1)) / dim; if(b_frommonth) { int day3 = calSys->day(from_date); double v3 = b_curmonth ? (account_month_beginfirst[account] - account_month_begincur[account]) : account_month_beginfirst[account]; double m3 = ((m - v) * (day3 - day + 1)) / (day2 - day + 1); if(v3 > m3) m3 = v3; double m2 = m - m3; double v2 = v - v3; if(m2 > v2) future_change_diff += m2 - v2; } } else if(b_frommonth) { int dim = calSys->day(monthend); int day = dim; if(b_lastmonth) { v -= account_month_endlast[account]; int day = calSys->day(to_date); m = (m * day) / dim; } int day2 = 1; if(b_curmonth) day2 = calSys->day(curdate); int day3 = calSys->day(from_date); double v3 = b_curmonth ? (account_month_beginfirst[account] - account_month_begincur[account]) : account_month_beginfirst[account]; double m3 = ((m - v) * (day3 - day2 + 1)) / (day - day2 + 1); if(v3 > m3) m3 = v3; double m2 = m - v - m3; double v2 = v - account_month_beginfirst[account]; if(m2 > v2) future_change_diff += m2 - v2; } else if(b_lastmonth) { v -= account_month_endlast[account]; int dim = calSys->day(monthend); int day = calSys->day(to_date); m = (m * day) / dim; } if(m > v) { future_diff += m - v; if(had_from) future_change_diff += m - v; } if(b_frommonth) had_from = true; b_curmonth = false; } curmonth = addMonths(curmonth, 1); if(it_n != it_e && curmonth == it_n.key()) { it = it_n; ++it_n; } } while(curmonth <= monthlast); } if(has_budget) { i->setText(BUDGET_COLUMN, i18n("%1: budget; %2: remaining budget", "%2 of %1").arg(KGlobal::locale()->formatNumber(mbudget, KGlobal::locale()->fracDigits())).arg(KGlobal::locale()->formatNumber(diff, KGlobal::locale()->fracDigits()))); account_budget[account] = mbudget; account_budget_diff[account] = diff; } else { i->setText(BUDGET_COLUMN, "-"); account_budget[account] = -1.0; } double future_diff_bak = future_diff, future_diff_change_bak = future_change_diff; future_diff -= account_future_diff[account]; future_change_diff -= account_future_diff_change[account]; account_future_diff[account] = future_diff_bak; account_future_diff_change[account] = future_diff_change_bak; if(future_diff == 0.0 & future_change_diff == 0.0) return; if(budget->budgetAccount) { if(account->type() == ACCOUNT_TYPE_EXPENSES) { account_value[budget->budgetAccount] -= future_diff; account_change[budget->budgetAccount] -= future_change_diff; } else { account_value[budget->budgetAccount] += future_diff; account_change[budget->budgetAccount] += future_change_diff; } item_accounts[budget->budgetAccount]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[budget->budgetAccount], KGlobal::locale()->fracDigits())); item_accounts[budget->budgetAccount]->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(account_value[budget->budgetAccount], KGlobal::locale()->fracDigits()) + " "); } if(account->type() == ACCOUNT_TYPE_EXPENSES) { assets_accounts_value -= future_diff; assets_accounts_change -= future_change_diff; } else { assets_accounts_value += future_diff; assets_accounts_change += future_change_diff; } assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); } if(item_accounts[account] == accountsView->selectedItem()) updateBudgetEdit(); } void Eqonomize::updateBudgetEdit() { QListViewItem *i = accountsView->selectedItem(); budgetEdit->blockSignals(true); budgetButton->blockSignals(true); if(i == NULL || i == assetsItem || i == incomesItem || i == expensesItem || account_items[i]->type() == ACCOUNT_TYPE_ASSETS) { budgetEdit->setValue(0.0); budgetEdit->setEnabled(false); budgetButton->setEnabled(false); if(i == incomesItem || i == expensesItem) { QDate tomonth, prevmonth_end; const KCalendarSystem *calSys = KGlobal::locale()->calendar(); calSys->setYMD(tomonth, calSys->year(to_date), calSys->month(to_date), 1); prevmonth_end = calSys->addDays(prevmonth_begin, calSys->daysInMonth(prevmonth_begin) - 1); double d_to = 0.0, d_prev = 0.0, v_prev = 0.0; CategoryAccount *ca; bool b_budget = false, b_budget_prev = false; if(i == incomesItem) ca = budget->incomesAccounts.first(); else ca = budget->expensesAccounts.first(); while(ca) { double d = ca->monthlyBudget(tomonth); if(d >= 0.0) { d_to += d; b_budget = true; } d = ca->monthlyBudget(prevmonth_begin); if(d >= 0.0) { d_prev += d; b_budget_prev = true; v_prev += account_month[ca][prevmonth_end]; } if(i == incomesItem) ca = budget->incomesAccounts.next(); else ca = budget->expensesAccounts.next(); } if(!b_budget_prev) { if(i == incomesItem) ca = budget->incomesAccounts.first(); else ca = budget->expensesAccounts.first(); while(ca) { v_prev += account_month[ca][prevmonth_end]; if(i == incomesItem) ca = budget->incomesAccounts.next(); else ca = budget->expensesAccounts.next(); } } if(!b_budget_prev) prevMonthBudgetLabel->setText(i18n("%1 (with no budget)").arg(KGlobal::locale()->formatMoney(v_prev))); else prevMonthBudgetLabel->setText(i18n("%1 (with budget %2)").arg(KGlobal::locale()->formatMoney(v_prev)).arg(KGlobal::locale()->formatMoney(d_prev))); budgetButton->setChecked(b_budget); budgetEdit->setValue(d_to); } else { budgetButton->setChecked(false); prevMonthBudgetLabel->setText("-"); } } else { CategoryAccount *ca = (CategoryAccount*) account_items[i]; QDate tomonth; const KCalendarSystem *calSys = KGlobal::locale()->calendar(); calSys->setYMD(tomonth, calSys->year(to_date), calSys->month(to_date), 1); double d = ca->monthlyBudget(tomonth); if(d < 0.0) { budgetEdit->setValue(0.0); budgetButton->setChecked(false); budgetEdit->setEnabled(false); } else { budgetEdit->setValue(d); budgetButton->setChecked(true); budgetEdit->setEnabled(true); } budgetButton->setEnabled(true); d = ca->monthlyBudget(prevmonth_begin); if(d < 0.0) prevMonthBudgetLabel->setText(i18n("%1 (with no budget)").arg(KGlobal::locale()->formatMoney(account_month[ca][calSys->addDays(prevmonth_begin, calSys->daysInMonth(prevmonth_begin) - 1)]))); else prevMonthBudgetLabel->setText(i18n("%1 (with budget %2)").arg(KGlobal::locale()->formatMoney(account_month[ca][calSys->addDays(prevmonth_begin, calSys->daysInMonth(prevmonth_begin) - 1)])).arg(KGlobal::locale()->formatMoney(d))); } budgetEdit->blockSignals(false); budgetButton->blockSignals(false); } void Eqonomize::accountsSelectionChanged() { QListViewItem *i = accountsView->selectedItem(); if(i == NULL || i == assetsItem || i == incomesItem || i == expensesItem) { ActionDeleteAccount->setEnabled(false); ActionEditAccount->setEnabled(false); ActionBalanceAccount->setEnabled(false); budgetEdit->setEnabled(false); } else { ActionDeleteAccount->setEnabled(true); ActionEditAccount->setEnabled(true); ActionBalanceAccount->setEnabled(account_items[i]->type() == ACCOUNT_TYPE_ASSETS && ((AssetsAccount*) account_items[i])->accountType() != ASSETS_TYPE_SECURITIES); } ActionShowAccountTransactions->setEnabled(i != NULL && i != assetsItem); updateBudgetEdit(); } void Eqonomize::updateSecurityAccount(AssetsAccount *account, bool update_display) { double value = 0.0, value_from = 0.0; bool b_from = accountsPeriodFromButton->isChecked(); Security *security = budget->securities.first(); while(security) { if(security->account() == account) { value += security->value(to_date, true); if(b_from) value_from += security->value(from_date, true); } security = budget->securities.next(); } if(!b_from) { value_from = account->initialBalance(); } assets_accounts_value -= account_value[account]; assets_accounts_value += value; assets_accounts_change -= account_change[account]; assets_accounts_change += (value - value_from); account_value[account] = value; account_change[account] = value - value_from; if(update_display) { assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); item_accounts[account]->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(value - value_from, KGlobal::locale()->fracDigits())); item_accounts[account]->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(value, KGlobal::locale()->fracDigits()) + " "); } } void Eqonomize::filterAccounts() { expenses_accounts_value = 0.0; expenses_accounts_change = 0.0; incomes_accounts_value = 0.0; incomes_accounts_change = 0.0; assets_accounts_value = 0.0; assets_accounts_change = 0.0; incomes_budget = 0.0; incomes_budget_diff = 0.0; expenses_budget = 0.0; expenses_budget_diff = 0.0; AssetsAccount *aaccount = budget->assetsAccounts.first(); while(aaccount) { if(aaccount->accountType() == ASSETS_TYPE_SECURITIES) { account_value[aaccount] = 0.0; account_change[aaccount] = 0.0; updateSecurityAccount(aaccount, false); } else { account_value[aaccount] = aaccount->initialBalance(); account_change[aaccount] = 0.0; assets_accounts_value += aaccount->initialBalance(); } aaccount = budget->assetsAccounts.next(); } const KCalendarSystem *calSys = KGlobal::locale()->calendar(); Transaction *trans = budget->transactions.first(); QDate monthdate, monthdate_begin; bool b_from = accountsPeriodFromButton->isChecked(); QDate lastmonth; calSys->setYMD(lastmonth, calSys->year(to_date), calSys->month(to_date), calSys->daysInMonth(to_date)); QDate curdate = QDate::currentDate(), curmonth, curmonth_begin; calSys->setYMD(curmonth_begin, calSys->year(curdate), calSys->month(curdate), 1); prevmonth_begin = addMonths(to_date, -1); prevmonth_begin = calSys->addDays(prevmonth_begin, -(calSys->day(prevmonth_begin) - 1)); calSys->setYMD(curmonth, calSys->year(curdate), calSys->month(curdate), calSys->daysInMonth(curdate)); frommonth_begin = QDate(); IncomesAccount *iaccount = budget->incomesAccounts.first(); while(iaccount) { account_value[iaccount] = 0.0; account_change[iaccount] = 0.0; account_month[iaccount] = QMap(); account_month[iaccount][monthdate] = 0.0; account_budget[iaccount] = -1.0; account_budget_diff[iaccount] = 0.0; account_month_beginfirst[iaccount] = 0.0; account_month_begincur[iaccount] = 0.0; account_month_endlast[iaccount] = 0.0; account_future_diff[iaccount] = 0.0; account_future_diff_change[iaccount] = 0.0; if(!iaccount->mbudgets.isEmpty() && iaccount->mbudgets.begin().data() >= 0.0 && (frommonth_begin.isNull() || iaccount->mbudgets.begin().key() < frommonth_begin)) { frommonth_begin = iaccount->mbudgets.begin().key(); } iaccount = budget->incomesAccounts.next(); } ExpensesAccount *eaccount = budget->expensesAccounts.first(); while(eaccount) { account_value[eaccount] = 0.0; account_change[eaccount] = 0.0; account_month[eaccount] = QMap(); account_month[eaccount][monthdate] = 0.0; account_budget[eaccount] = -1.0; account_budget_diff[eaccount] = 0.0; account_month_beginfirst[eaccount] = 0.0; account_month_begincur[eaccount] = 0.0; account_month_endlast[eaccount] = 0.0; account_future_diff[eaccount] = 0.0; account_future_diff_change[eaccount] = 0.0; if(!eaccount->mbudgets.isEmpty() && eaccount->mbudgets.begin().data() >= 0.0 && (frommonth_begin.isNull() || eaccount->mbudgets.begin().key() < frommonth_begin)) { frommonth_begin = eaccount->mbudgets.begin().key(); } eaccount = budget->expensesAccounts.next(); } if(frommonth_begin.isNull() || (b_from && frommonth_begin < from_date)) { if(b_from) calSys->setYMD(frommonth_begin, calSys->year(from_date), calSys->month(from_date), 1); else frommonth_begin = curmonth_begin; } if(frommonth_begin.isNull() || frommonth_begin > prevmonth_begin) { monthdate_begin = prevmonth_begin; } else { monthdate_begin = frommonth_begin; } if(monthdate_begin > curmonth_begin) monthdate_begin = curmonth_begin; monthdate = calSys->addDays(monthdate_begin, calSys->daysInMonth(monthdate_begin) - 1); bool b_future = false; bool b_past = (curdate >= to_date); if(b_past) { footer1->hide(); assetsItem->setText(0, i18n("Accounts")); if(budget->budgetAccount) { item_accounts[budget->budgetAccount]->setText(0, budget->budgetAccount->name()); } } else { footer1->show(); assetsItem->setText(0, i18n("Accounts") + "*"); if(budget->budgetAccount) { item_accounts[budget->budgetAccount]->setText(0, budget->budgetAccount->name() + "*"); } } while(trans && trans->date() <= lastmonth) { if(!b_past && !b_future && trans->date() >= curmonth_begin) b_future = true; if(!b_from || b_future || trans->date() >= frommonth_begin || trans->date() >= prevmonth_begin) { while(trans->date() > monthdate) { monthdate_begin = addMonths(monthdate_begin, 1); monthdate = calSys->addDays(monthdate_begin, calSys->daysInMonth(monthdate_begin) - 1); iaccount = budget->incomesAccounts.first(); while(iaccount) { account_month[iaccount][monthdate] = 0.0; iaccount = budget->incomesAccounts.next(); } eaccount = budget->expensesAccounts.first(); while(eaccount) { account_month[eaccount][monthdate] = 0.0; eaccount = budget->expensesAccounts.next(); } } addTransactionValue(trans, trans->date(), false, false, -1, b_future, &monthdate); } else { addTransactionValue(trans, trans->date(), false, false, -1, b_future, NULL); } trans = budget->transactions.next(); } while(lastmonth >= monthdate) { monthdate_begin = addMonths(monthdate_begin, 1); monthdate = calSys->addDays(monthdate_begin, calSys->daysInMonth(monthdate_begin) - 1); iaccount = budget->incomesAccounts.first(); while(iaccount) { account_month[iaccount][monthdate] = 0.0; iaccount = budget->incomesAccounts.next(); } eaccount = budget->expensesAccounts.first(); while(eaccount) { account_month[eaccount][monthdate] = 0.0; eaccount = budget->expensesAccounts.next(); } } ScheduledTransaction *strans = budget->scheduledTransactions.first(); while(strans && strans->transaction()->date() <= lastmonth) { addScheduledTransactionValue(strans, false, false); strans = budget->scheduledTransactions.next(); } for(QMap::Iterator it = account_items.begin(); it != account_items.end(); ++it) { switch(it.data()->type()) { case ACCOUNT_TYPE_INCOMES: {} case ACCOUNT_TYPE_EXPENSES: { updateMonthlyBudget(it.data()); break; } default: {} } } updateTotalMonthlyIncomesBudget(); updateTotalMonthlyExpensesBudget(); for(QMap::Iterator it = account_items.begin(); it != account_items.end(); ++it) { it.key()->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(account_change[it.data()], KGlobal::locale()->fracDigits())); it.key()->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(account_value[it.data()], KGlobal::locale()->fracDigits()) + " "); } incomesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_value, KGlobal::locale()->fracDigits()) + " "); incomesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(incomes_accounts_change, KGlobal::locale()->fracDigits())); expensesItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_value, KGlobal::locale()->fracDigits()) + " "); expensesItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(expenses_accounts_change, KGlobal::locale()->fracDigits())); assetsItem->setText(VALUE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_value, KGlobal::locale()->fracDigits()) + " "); assetsItem->setText(CHANGE_COLUMN, KGlobal::locale()->formatNumber(assets_accounts_change, KGlobal::locale()->fracDigits())); budgetMonthEdit->blockSignals(true); budgetMonthEdit->setDate(to_date); budgetMonthEdit->blockSignals(false); updateBudgetEdit(); } #include "eqonomize.moc"