/*************************************************************************** kcurrencycalculator.cpp - description ------------------- begin : Thu Apr 8 2004 copyright : (C) 2000-2004 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif // ---------------------------------------------------------------------------- // TQt Includes #include #include #include #include #include // ---------------------------------------------------------------------------- // TDE Includes #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "kcurrencycalculator.h" #include #include #include #include #include #include #include "../kmymoneyutils.h" bool KCurrencyCalculator::setupSplitPrice(MyMoneyMoney& shares, const MyMoneyTransaction& t, const MyMoneySplit& s, const TQMap& priceInfo, TQWidget* parentWidget) { bool rc = true; MyMoneyFile* file = MyMoneyFile::instance(); if(!s.value().isZero()) { MyMoneyAccount cat = file->account(s.accountId()); MyMoneySecurity toCurrency; toCurrency = file->security(cat.currencyId()); // determine the fraction required for this category/account int fract = cat.fraction(toCurrency); if(cat.currencyId() != t.commodity()) { MyMoneySecurity fromCurrency; MyMoneyMoney fromValue, toValue; fromCurrency = file->security(t.commodity()); // display only positive values to the user fromValue = s.value().abs(); // if we had a price info in the beginning, we use it here if(priceInfo.find(cat.currencyId()) != priceInfo.end()) { toValue = (fromValue * priceInfo[cat.currencyId()]).convert(fract); } // if the shares are still 0, we need to change that if(toValue.isZero()) { MyMoneyPrice price = file->price(fromCurrency.id(), toCurrency.id()); // if the price is valid calculate the shares. If it is invalid // assume a conversion rate of 1.0 if(price.isValid()) { toValue = (price.rate(toCurrency.id()) * fromValue).convert(fract); } else { toValue = fromValue; } } // now present all that to the user KCurrencyCalculator calc(fromCurrency, toCurrency, fromValue, toValue, t.postDate(), fract, parentWidget, "currencyCalculator"); if(calc.exec() == TQDialog::Rejected) { rc = false; } else shares = (s.value() * calc.price()).convert(fract); } else { shares = s.value().convert(fract); } } else shares = s.value(); return rc; } KCurrencyCalculator::KCurrencyCalculator(const MyMoneySecurity& from, const MyMoneySecurity& to, const MyMoneyMoney& value, const MyMoneyMoney& shares, const TQDate& date, const signed64 resultFraction, TQWidget *parent, const char *name ) : KCurrencyCalculatorDecl(parent, name), m_fromCurrency(from), m_toCurrency(to), m_result(shares.abs()), m_value(value.abs()), m_resultFraction(resultFraction) { MyMoneyFile* file = MyMoneyFile::instance(); m_dateFrame->hide(); if(date.isValid()) m_dateEdit->setDate(date); else m_dateEdit->setDate(TQDate::currentDate()); m_fromCurrencyText->setText(m_fromCurrency.isCurrency() ? m_fromCurrency.id() : m_fromCurrency.tradingSymbol()); m_toCurrencyText->setText(m_toCurrency.isCurrency() ? m_toCurrency.id() : m_toCurrency.tradingSymbol()); m_fromAmount->setText(m_value.formatMoney("", MyMoneyMoney::denomToPrec(m_fromCurrency.smallestAccountFraction()))); m_dateText->setText(TDEGlobal::locale()->formatDate(date, true)); m_fromType->setText(KMyMoneyUtils::securityTypeToString(m_fromCurrency.securityType())); m_toType->setText(KMyMoneyUtils::securityTypeToString(m_toCurrency.securityType())); // load button icons m_cancelButton->setGuiItem(KStdGuiItem::cancel()); m_okButton->setGuiItem(KStdGuiItem::ok()); m_updateButton->setChecked(KMyMoneyGlobalSettings::priceHistoryUpdate()); // setup initial result if(m_result == MyMoneyMoney() && !m_value.isZero()) { MyMoneyPrice pr = file->price(m_fromCurrency.id(), m_toCurrency.id(), date); if(pr.isValid()) { m_result = m_value * pr.rate(m_fromCurrency.id()); } } // fill in initial values m_toAmount->loadText(m_result.formatMoney("", MyMoneyMoney::denomToPrec(m_resultFraction))); m_toAmount->setPrecision(MyMoneyMoney::denomToPrec(m_resultFraction)); m_conversionRate->setPrecision(KMyMoneyGlobalSettings::pricePrecision()); connect(m_amountButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSetToAmount())); connect(m_rateButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSetExchangeRate())); connect(m_toAmount, TQ_SIGNAL(valueChanged(const TQString&)), this, TQ_SLOT(slotUpdateResult(const TQString&))); connect(m_conversionRate, TQ_SIGNAL(valueChanged(const TQString&)), this, TQ_SLOT(slotUpdateRate(const TQString&))); connect(m_cancelButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(reject())); connect(m_okButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(accept())); // use this as the default m_amountButton->animateClick(); slotUpdateResult(m_toAmount->text()); // If the from security is not a currency, we only allow entering a price if(!m_fromCurrency.isCurrency()) { m_rateButton->animateClick(); m_amountButton->hide(); m_toAmount->hide(); } m_okButton->setFocus(); } KCurrencyCalculator::~KCurrencyCalculator() { } void KCurrencyCalculator::setupPriceEditor(void) { m_dateFrame->show(); m_amountDateFrame->hide(); m_updateButton->setChecked(true); m_updateButton->hide(); } void KCurrencyCalculator::slotSetToAmount(void) { m_rateButton->setChecked(false); m_toAmount->setEnabled(true); m_conversionRate->setEnabled(false); } void KCurrencyCalculator::slotSetExchangeRate(void) { m_amountButton->setChecked(false); m_toAmount->setEnabled(false); m_conversionRate->setEnabled(true); } void KCurrencyCalculator::slotUpdateResult(const TQString& /*txt*/) { MyMoneyMoney result = m_toAmount->value(); MyMoneyMoney price(0, 1); if(result.isNegative()) { m_toAmount->setValue(-result); slotUpdateResult(TQString()); return; } if(!result.isZero()) { price = result / m_value; m_conversionRate->loadText(price.formatMoney("", KMyMoneyGlobalSettings::pricePrecision())); m_result = (m_value * price).convert(m_resultFraction); m_toAmount->loadText(m_result.formatMoney("", MyMoneyMoney::denomToPrec(m_resultFraction))); } updateExample(price); } void KCurrencyCalculator::slotUpdateRate(const TQString& /*txt*/) { MyMoneyMoney price = m_conversionRate->value(); if(price.isNegative()) { m_conversionRate->setValue(-price); slotUpdateRate(TQString()); return; } if(!price.isZero()) { m_conversionRate->loadText(price.formatMoney("", KMyMoneyGlobalSettings::pricePrecision())); m_result = (m_value * price).convert(m_resultFraction); m_toAmount->loadText(m_result.formatMoney("", MyMoneyMoney::denomToPrec(m_resultFraction))); } updateExample(price); } void KCurrencyCalculator::updateExample(const MyMoneyMoney& price) { TQString msg; if(price.isZero()) { msg = TQString("1 %1 = ? %2").arg(m_fromCurrency.tradingSymbol()) .arg(m_toCurrency.tradingSymbol()); if(m_fromCurrency.isCurrency()) { msg += TQString("\n"); msg += TQString("1 %1 = ? %2").arg(m_toCurrency.tradingSymbol()) .arg(m_fromCurrency.tradingSymbol()); } } else { msg = TQString("1 %1 = %2 %3").arg(m_fromCurrency.tradingSymbol()) .arg(price.formatMoney("", KMyMoneyGlobalSettings::pricePrecision())) .arg(m_toCurrency.tradingSymbol()); if(m_fromCurrency.isCurrency()) { msg += TQString("\n"); msg += TQString("1 %1 = %2 %3").arg(m_toCurrency.tradingSymbol()) .arg((MyMoneyMoney(1,1)/price).formatMoney("", KMyMoneyGlobalSettings::pricePrecision())) .arg(m_fromCurrency.tradingSymbol()); } } m_conversionExample->setText(msg); m_okButton->setEnabled(!price.isZero()); } void KCurrencyCalculator::accept(void) { if(m_conversionRate->isEnabled()) slotUpdateRate(TQString()); else slotUpdateResult(TQString()); if(m_updateButton->isChecked()) { MyMoneyPrice pr = MyMoneyFile::instance()->price(m_fromCurrency.id(), m_toCurrency.id(), m_dateEdit->date()); if(!pr.isValid() || pr.date() != m_dateEdit->date() || (pr.date() == m_dateEdit->date() && pr.rate(m_fromCurrency.id()) != price())) { pr = MyMoneyPrice(m_fromCurrency.id(), m_toCurrency.id(), m_dateEdit->date(), price(), i18n("User")); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->addPrice(pr); ft.commit(); } catch(MyMoneyException *e) { tqDebug("Cannot add price"); delete e; } } } // remember setting for next round KMyMoneyGlobalSettings::setPriceHistoryUpdate(m_updateButton->isChecked()); KCurrencyCalculatorDecl::accept(); } const MyMoneyMoney KCurrencyCalculator::price(void) const { // This should fix https://bugs.kde.org/show_bug.cgi?id=205254 but // I am not sure about any side effects when dealing with multi- // currency transactions. // // The following line is the original version of this code // which causes some rounding issues (see the above bug entry) // return m_result / m_value; return m_conversionRate->value(); } #include "kcurrencycalculator.moc"