File indexing completed on 2024-05-19 16:16:48

0001 /*
0002     SPDX-FileCopyrightText: 2006-2018 Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "investtransaction.h"
0008 #include "investtransaction_p.h"
0009 
0010 // ----------------------------------------------------------------------------
0011 // QT Includes
0012 
0013 #include <QString>
0014 #include <QWidget>
0015 #include <QList>
0016 #include <QPushButton>
0017 
0018 // ----------------------------------------------------------------------------
0019 // KDE Includes
0020 
0021 #include <KLocalizedString>
0022 
0023 // ----------------------------------------------------------------------------
0024 // Project Includes
0025 
0026 #include "kmymoneypayeecombo.h"
0027 #include "transaction.h"
0028 
0029 #include "mymoneyutils.h"
0030 #include "mymoneytransaction.h"
0031 #include "mymoneysplit.h"
0032 #include "mymoneyfile.h"
0033 #include "register.h"
0034 #include "transactionform.h"
0035 #include "kmymoneylineedit.h"
0036 #include "kmymoneycombo.h"
0037 #include "investtransactioneditor.h"
0038 #include "kmymoneyutils.h"
0039 #include "amountedit.h"
0040 
0041 #include "kmymoneysettings.h"
0042 #include "widgetenums.h"
0043 
0044 using namespace eWidgets;
0045 using namespace KMyMoneyRegister;
0046 using namespace KMyMoneyTransactionForm;
0047 
0048 InvestTransaction::InvestTransaction(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId) :
0049     Transaction(*new InvestTransactionPrivate, parent, transaction, split, uniqueId)
0050 {
0051     Q_D(InvestTransaction);
0052 #ifndef KMM_DESIGNER
0053     // dissect the transaction into its type, splits, currency, security etc.
0054     KMyMoneyUtils::dissectTransaction(d->m_transaction, d->m_split,
0055                                       d->m_assetAccountSplit,
0056                                       d->m_feeSplits,
0057                                       d->m_interestSplits,
0058                                       d->m_security,
0059                                       d->m_currency,
0060                                       d->m_transactionType);
0061 #endif
0062 
0063     QList<MyMoneySplit>::ConstIterator it_s;
0064     for (it_s = d->m_feeSplits.constBegin(); it_s != d->m_feeSplits.constEnd(); ++it_s) {
0065         d->m_feeAmount += (*it_s).value();
0066     }
0067     for (it_s = d->m_interestSplits.constBegin(); it_s != d->m_interestSplits.constEnd(); ++it_s) {
0068         d->m_interestAmount += (*it_s).value();
0069     }
0070 
0071     // check the count of the fee splits and setup the text
0072     switch (d->m_feeSplits.count()) {
0073     case 0:
0074         break;
0075 
0076     case 1:
0077         d->m_feeCategory = MyMoneyFile::instance()->accountToCategory(d->m_feeSplits[0].accountId());
0078         break;
0079 
0080     default:
0081         d->m_feeCategory = i18nc("Split transaction (category replacement)", "Split transaction");
0082         break;
0083     }
0084 
0085     // check the count of the interest splits and setup the text
0086     switch (d->m_interestSplits.count()) {
0087     case 0:
0088         break;
0089 
0090     case 1:
0091         d->m_interestCategory = MyMoneyFile::instance()->accountToCategory(d->m_interestSplits[0].accountId());
0092         break;
0093 
0094     default:
0095         d->m_interestCategory = i18nc("Split transaction (category replacement)", "Split transaction");
0096         break;
0097     }
0098 
0099     d->m_rowsForm = 7;
0100 
0101     // setup initial size
0102     setNumRowsRegister(numRowsRegister(KMyMoneySettings::showRegisterDetailed()));
0103 
0104     emit parent->itemAdded(this);
0105 }
0106 
0107 InvestTransaction::~InvestTransaction()
0108 {
0109 }
0110 
0111 const QString InvestTransaction::sortSecurity() const
0112 {
0113     Q_D(const InvestTransaction);
0114     return d->m_security.name();
0115 }
0116 
0117 const char* InvestTransaction::className()
0118 {
0119     return "InvestTransaction";
0120 }
0121 
0122 void InvestTransaction::setupForm(TransactionForm* form)
0123 {
0124     Transaction::setupForm(form);
0125     form->setSpan(5, 1, 2, 1);
0126 }
0127 
0128 void InvestTransaction::activity(QString& txt, eMyMoney::Split::InvestmentTransactionType type) const
0129 {
0130     switch (type) {
0131     case eMyMoney::Split::InvestmentTransactionType::AddShares:
0132         txt = i18nc("Add securities/shares/bonds", "Add shares");
0133         break;
0134     case eMyMoney::Split::InvestmentTransactionType::RemoveShares:
0135         txt = i18nc("Remove securities/shares/bonds", "Remove shares");
0136         break;
0137     case eMyMoney::Split::InvestmentTransactionType::BuyShares:
0138         txt = i18nc("Buy securities/shares/bonds", "Buy shares");
0139         break;
0140     case eMyMoney::Split::InvestmentTransactionType::SellShares:
0141         txt = i18nc("Sell securities/shares/bonds", "Sell shares");
0142         break;
0143     case eMyMoney::Split::InvestmentTransactionType::Dividend:
0144         txt = i18n("Dividend");
0145         break;
0146     case eMyMoney::Split::InvestmentTransactionType::ReinvestDividend:
0147         txt = i18n("Reinvest Dividend");
0148         break;
0149     case eMyMoney::Split::InvestmentTransactionType::Yield:
0150         txt = i18n("Yield");
0151         break;
0152     case eMyMoney::Split::InvestmentTransactionType::SplitShares:
0153         txt = i18nc("Split securities/shares/bonds", "Split shares");
0154         break;
0155     case eMyMoney::Split::InvestmentTransactionType::InterestIncome:
0156         txt = i18n("Interest Income");
0157         break;
0158     default:
0159         txt = i18nc("Unknown investment activity", "Unknown");
0160         break;
0161     }
0162 }
0163 
0164 bool InvestTransaction::formCellText(QString& txt, Qt::Alignment& align, int row, int col, QPainter* /* painter */)
0165 {
0166     Q_D(InvestTransaction);
0167     bool fieldEditable = false;
0168 
0169     switch (row) {
0170     case 0:
0171         switch (col) {
0172         case (int)eTransactionForm::Column::Label1:
0173             align |= Qt::AlignLeft;
0174             txt = i18n("Activity");
0175             break;
0176 
0177         case (int)eTransactionForm::Column::Value1:
0178             align |= Qt::AlignLeft;
0179             fieldEditable = true;
0180             activity(txt, d->m_transactionType);
0181             break;
0182 
0183         case (int)eTransactionForm::Column::Label2:
0184             align |= Qt::AlignLeft;
0185             txt = i18n("Date");
0186             break;
0187 
0188         case (int)eTransactionForm::Column::Value2:
0189             align |= Qt::AlignRight;
0190             fieldEditable = true;
0191             if (!d->m_transaction.id().isEmpty())
0192                 txt = QLocale().toString(d->m_transaction.postDate(), QLocale::ShortFormat);
0193             break;
0194         }
0195         break;
0196 
0197     case 1:
0198         switch (col) {
0199         case (int)eTransactionForm::Column::Label1:
0200             align |= Qt::AlignLeft;
0201             txt = i18n("Security");
0202             break;
0203 
0204         case (int)eTransactionForm::Column::Value1:
0205             align |= Qt::AlignLeft;
0206             fieldEditable = true;
0207             if (d->m_account.isInvest())
0208                 txt = d->m_security.name();
0209             break;
0210 
0211         case (int)eTransactionForm::Column::Label2:
0212             align |= Qt::AlignLeft;
0213             if (haveShares()) {
0214                 txt = i18n("Shares");
0215             } else if (haveSplitRatio()) {
0216                 txt = i18n("Ratio");
0217             }
0218             break;
0219 
0220         case (int)eTransactionForm::Column::Value2:
0221             align |= Qt::AlignRight;
0222             if ((fieldEditable = haveShares()) == true) {
0223                 txt = d->m_split.shares().abs().formatMoney(QString(), MyMoneyMoney::denomToPrec(d->m_security.smallestAccountFraction()));
0224             } else if (haveSplitRatio()) {
0225                 txt = QString("1 / %1").arg(d->m_split.shares().abs().formatMoney(QString(), -1));
0226             }
0227             break;
0228         }
0229         break;
0230 
0231     case 2:
0232         switch (col) {
0233         case (int)eTransactionForm::Column::Label1:
0234             align |= Qt::AlignLeft;
0235             if (haveAssetAccount())
0236                 txt = i18n("Account");
0237             break;
0238 
0239         case (int)eTransactionForm::Column::Value1:
0240             align |= Qt::AlignLeft;
0241             if ((fieldEditable = haveAssetAccount()) == true) {
0242                 txt = MyMoneyFile::instance()->accountToCategory(d->m_assetAccountSplit.accountId());
0243             }
0244             break;
0245 
0246         case (int)eTransactionForm::Column::Label2:
0247             align |= Qt::AlignLeft;
0248             if (havePrice())
0249                 txt = i18n("Price/share");
0250             break;
0251 
0252         case (int)eTransactionForm::Column::Value2:
0253             align |= Qt::AlignRight;
0254             if ((fieldEditable = havePrice()) == true && !d->m_split.shares().isZero()) {
0255                 txt = d->m_split.price().formatMoney(QString(), d->m_security.pricePrecision());
0256             }
0257             break;
0258         }
0259         break;
0260 
0261     case 3:
0262         switch (col) {
0263         case (int)eTransactionForm::Column::Label1:
0264             align |= Qt::AlignLeft;
0265             if (haveFees())
0266                 txt = i18n("Fees");
0267             break;
0268 
0269         case (int)eTransactionForm::Column::Value1:
0270             align |= Qt::AlignLeft;
0271             if ((fieldEditable = haveFees()) == true) {
0272                 txt = d->m_feeCategory;
0273             }
0274             break;
0275 
0276         case (int)eTransactionForm::Column::Label2:
0277             align |= Qt::AlignLeft;
0278             if (haveFees() && !d->m_feeCategory.isEmpty())
0279                 txt = i18n("Fee Amount");
0280             break;
0281 
0282         case (int)eTransactionForm::Column::Value2:
0283             align |= Qt::AlignRight;
0284             if (haveFees()) {
0285                 if ((fieldEditable = !d->m_feeCategory.isEmpty()) == true) {
0286                     txt = MyMoneyUtils::formatMoney(d->m_feeAmount, d->m_currency);
0287                 }
0288             }
0289             break;
0290         }
0291         break;
0292 
0293     case 4:
0294         switch (col) {
0295         case (int)eTransactionForm::Column::Label1:
0296             align |= Qt::AlignLeft;
0297             if (haveInterest())
0298                 txt = i18n("Interest");
0299             break;
0300 
0301         case (int)eTransactionForm::Column::Value1:
0302             align |= Qt::AlignLeft;
0303             if ((fieldEditable = haveInterest()) == true) {
0304                 txt = d->m_interestCategory;
0305             }
0306             break;
0307 
0308         case (int)eTransactionForm::Column::Label2:
0309             align |= Qt::AlignLeft;
0310             if (haveInterest() && !d->m_interestCategory.isEmpty())
0311                 txt = i18n("Interest");
0312             break;
0313 
0314         case (int)eTransactionForm::Column::Value2:
0315             align |= Qt::AlignRight;
0316             if (haveInterest()) {
0317                 if ((fieldEditable = !d->m_interestCategory.isEmpty()) == true) {
0318                     txt = MyMoneyUtils::formatMoney(-d->m_interestAmount, d->m_currency);
0319                 }
0320             }
0321             break;
0322         }
0323         break;
0324 
0325     case 5:
0326         switch (col) {
0327         case (int)eTransactionForm::Column::Label1:
0328             align |= Qt::AlignLeft;
0329             txt = i18n("Memo");
0330             break;
0331 
0332         case (int)eTransactionForm::Column::Value1:
0333             align &= ~Qt::AlignVCenter;
0334             align |= Qt::AlignTop;
0335             align |= Qt::AlignLeft;
0336             fieldEditable = true;
0337             if (!d->m_transaction.id().isEmpty())
0338                 txt = d->m_split.memo().section('\n', 0, 2);
0339             break;
0340 
0341         case (int)eTransactionForm::Column::Label2:
0342             align |= Qt::AlignLeft;
0343             if (haveAmount())
0344                 txt = i18nc("Total balance", "Total");
0345             break;
0346 
0347         case (int)eTransactionForm::Column::Value2:
0348             align |= Qt::AlignRight;
0349             if ((fieldEditable = haveAmount()) == true) {
0350                 txt = d->m_assetAccountSplit.value().abs()
0351                       .formatMoney(d->m_currency.tradingSymbol(), MyMoneyMoney::denomToPrec(d->m_currency.smallestAccountFraction()));
0352             }
0353         }
0354         break;
0355 
0356     case 6:
0357         switch (col) {
0358         case (int)eTransactionForm::Column::Label2:
0359             align |= Qt::AlignLeft;
0360             txt = i18n("Status");
0361             break;
0362 
0363         case (int)eTransactionForm::Column::Value2:
0364             align |= Qt::AlignRight;
0365             fieldEditable = true;
0366             txt = reconcileState();
0367             break;
0368         }
0369     }
0370 
0371     return fieldEditable;
0372 }
0373 
0374 void InvestTransaction::registerCellText(QString& txt, Qt::Alignment& align, int row, int col, QPainter* /* painter */)
0375 {
0376     Q_D(InvestTransaction);
0377     switch (row) {
0378     case 0:
0379         switch (col) {
0380         case (int)eTransaction::Column::Date:
0381             align |= Qt::AlignLeft;
0382             txt = QLocale().toString(d->m_transaction.postDate(), QLocale::ShortFormat);
0383             break;
0384 
0385         case (int)eTransaction::Column::Detail:
0386             align |= Qt::AlignLeft;
0387             activity(txt, d->m_transactionType);
0388             break;
0389 
0390         case (int)eTransaction::Column::Security:
0391             align |= Qt::AlignLeft;
0392             if (d->m_account.isInvest())
0393                 txt = d->m_security.name();
0394             break;
0395 
0396         case (int)eTransaction::Column::ReconcileFlag:
0397             align |= Qt::AlignHCenter;
0398             txt = reconcileState(false);
0399             break;
0400 
0401         case (int)eTransaction::Column::Quantity:
0402             align |= Qt::AlignRight;
0403             if (haveShares())
0404                 txt = d->m_split.shares().abs().formatMoney(QString(), MyMoneyMoney::denomToPrec(d->m_security.smallestAccountFraction()));
0405             else if (haveSplitRatio()) {
0406                 txt = QString("1 / %1").arg(d->m_split.shares().abs().formatMoney(QString(), -1));
0407             }
0408             break;
0409 
0410         case (int)eTransaction::Column::Price:
0411             align |= Qt::AlignRight;
0412             if (havePrice() && !d->m_split.shares().isZero()) {
0413                 txt = d->m_split.price().formatMoney(d->m_currency.tradingSymbol(), d->m_security.pricePrecision());
0414             }
0415             break;
0416 
0417         case (int)eTransaction::Column::Value:
0418             align |= Qt::AlignRight;
0419             if (haveAmount()) {
0420                 txt = MyMoneyUtils::formatMoney(d->m_assetAccountSplit.value().abs(), d->m_currency);
0421 
0422             } else if (haveInterest()) {
0423                 txt = MyMoneyUtils::formatMoney(-d->m_interestAmount, d->m_currency);
0424             }
0425             break;
0426 
0427         case (int)eTransaction::Column::Balance:
0428             align |= Qt::AlignRight;
0429             if (d->m_showBalance)
0430                 txt = d->m_balance.formatMoney(QString(), MyMoneyMoney::denomToPrec(d->m_security.smallestAccountFraction()));
0431             else
0432                 txt = "----";
0433             break;
0434 
0435         default:
0436             break;
0437         }
0438         break;
0439 
0440     case 1:
0441         switch (col) {
0442         case (int)eTransaction::Column::Detail:
0443             align |= Qt::AlignLeft;
0444             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty()) {
0445                 txt = MyMoneyFile::instance()->accountToCategory(d->m_assetAccountSplit.accountId());
0446             } else if (haveInterest() && d->m_interestSplits.count()) {
0447                 txt = d->m_interestCategory;
0448             } else if (haveFees() && d->m_feeSplits.count()) {
0449                 txt = d->m_feeCategory;
0450             } else
0451                 singleLineMemo(txt, d->m_split);
0452             break;
0453 
0454         case (int)eTransaction::Column::Quantity:
0455             align |= Qt::AlignRight;
0456             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty()) {
0457                 // txt = m_interestAmount.abs().formatMoney(m_currency);
0458             } else if (haveInterest() && d->m_interestSplits.count()) {
0459                 txt = MyMoneyUtils::formatMoney(-d->m_interestAmount, d->m_currency);
0460             } else if (haveFees() && d->m_feeSplits.count()) {
0461                 txt = MyMoneyUtils::formatMoney(d->m_feeAmount, d->m_currency);
0462             }
0463             break;
0464 
0465         default:
0466             break;
0467         }
0468         break;
0469 
0470     case 2:
0471         switch (col) {
0472         case (int)eTransaction::Column::Detail:
0473             align |= Qt::AlignLeft;
0474             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty() //
0475                     && haveInterest() && d->m_interestSplits.count()) {
0476                 txt = d->m_interestCategory;
0477             } else if (haveFees() && d->m_feeSplits.count()) {
0478                 txt = d->m_feeCategory;
0479             } else
0480                 singleLineMemo(txt, d->m_split);
0481             break;
0482 
0483         case (int)eTransaction::Column::Quantity:
0484             align |= Qt::AlignRight;
0485             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty() //
0486                     && haveInterest() && d->m_interestSplits.count()) {
0487                 txt = MyMoneyUtils::formatMoney(-d->m_interestAmount, d->m_currency);
0488             } else if (haveFees() && d->m_feeSplits.count()) {
0489                 txt = MyMoneyUtils::formatMoney(d->m_feeAmount, d->m_currency);
0490             }
0491             break;
0492 
0493         default:
0494             break;
0495         }
0496         break;
0497 
0498     case 3:
0499         switch (col) {
0500         case (int)eTransaction::Column::Detail:
0501             align |= Qt::AlignLeft;
0502             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty() //
0503                     && haveInterest() && d->m_interestSplits.count() //
0504                     && haveFees() && d->m_feeSplits.count()) {
0505                 txt = d->m_feeCategory;
0506             } else
0507                 singleLineMemo(txt, d->m_split);
0508             break;
0509 
0510         case (int)eTransaction::Column::Quantity:
0511             align |= Qt::AlignRight;
0512             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty() //
0513                     && haveInterest() && d->m_interestSplits.count() //
0514                     && haveFees() && d->m_feeSplits.count()) {
0515                 txt = MyMoneyUtils::formatMoney(d->m_feeAmount, d->m_currency);
0516             }
0517             break;
0518 
0519         default:
0520             break;
0521         }
0522         break;
0523 
0524     case 4:
0525         switch (col) {
0526         case (int)eTransaction::Column::Detail:
0527             align |= Qt::AlignLeft;
0528             singleLineMemo(txt, d->m_split);
0529             break;
0530 
0531         default:
0532             break;
0533         }
0534         break;
0535     }
0536 }
0537 
0538 int InvestTransaction::registerColWidth(int col, const QFontMetrics& cellFontMetrics)
0539 {
0540     Q_D(InvestTransaction);
0541     QString txt;
0542     MyMoneyMoney amount;
0543     int nw = 0;
0544 
0545     // for now just check all rows in that column
0546     for (int row = 0; row < d->m_rowsRegister; ++row) {
0547         int w;
0548         Transaction::registerCellText(txt, row, col);
0549         w = cellFontMetrics.width(txt + "  ");
0550         nw = qMax(nw, w);
0551     }
0552 
0553     // TODO the optimized way would be to base the size on the contents of a single row
0554     //      as we do it in StdTransaction::registerColWidth()
0555 #if 0
0556     switch (col) {
0557     default:
0558         break;
0559 
0560     case PriceColumn:
0561         if (havePrice()) {
0562             txt = (m_split.value() / m_split.shares()).formatMoney(QString(), KMyMoneySettings::pricePrecision());
0563             nw = cellFontMetrics.width(txt + "  ");
0564         }
0565         break;
0566     }
0567 #endif
0568     return nw;
0569 }
0570 
0571 void InvestTransaction::loadTab(KMyMoneyTransactionForm::TransactionForm* /* form */)
0572 {
0573 }
0574 
0575 int InvestTransaction::numColsForm() const
0576 {
0577     return 4;
0578 }
0579 
0580 void InvestTransaction::arrangeWidgetsInForm(QMap<QString, QWidget*>& editWidgets)
0581 {
0582     Q_D(InvestTransaction);
0583     if (!d->m_form || !d->m_parent)
0584         return;
0585 
0586     setupFormPalette(editWidgets);
0587 
0588     // arrange the edit widgets
0589     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Value1, editWidgets["activity"]);
0590     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Value2, editWidgets["postdate"]);
0591     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Value1, editWidgets["security"]);
0592     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Value2, editWidgets["shares"]);
0593     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Value1, editWidgets["asset-account"]);
0594     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Value2, editWidgets["price"]);
0595     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Value1, editWidgets["fee-account"]->parentWidget());
0596     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Value2, editWidgets["fee-amount"]);
0597     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Value1, editWidgets["interest-account"]->parentWidget());
0598     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Value2, editWidgets["interest-amount"]);
0599     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Value1, editWidgets["memo"]);
0600     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Value2, editWidgets["total"]);
0601     arrangeWidget(d->m_form, 6, (int)eTransactionForm::Column::Value2, editWidgets["status"]);
0602 
0603     // arrange dynamic labels
0604     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Label1, editWidgets["activity-label"]);
0605     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Label2, editWidgets["postdate-label"]);
0606     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Label1, editWidgets["security-label"]);
0607     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Label2, editWidgets["shares-label"]);
0608     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Label1, editWidgets["asset-label"]);
0609     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Label2, editWidgets["price-label"]);
0610     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Label1, editWidgets["fee-label"]);
0611     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Label2, editWidgets["fee-amount-label"]);
0612     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Label1, editWidgets["interest-label"]);
0613     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Label2, editWidgets["interest-amount-label"]);
0614     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Label1, editWidgets["memo-label"]);
0615     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Label2, editWidgets["total-label"]);
0616     arrangeWidget(d->m_form, 6, (int)eTransactionForm::Column::Label2, editWidgets["status-label"]);
0617 
0618     // get rid of the hints. we don't need them for the form
0619     QMap<QString, QWidget*>::iterator it;
0620     for (it = editWidgets.begin(); it != editWidgets.end(); ++it) {
0621         KMyMoneyCombo* combo = dynamic_cast<KMyMoneyCombo*>(*it);
0622         KMyMoneyLineEdit* lineedit = dynamic_cast<KMyMoneyLineEdit*>(*it);
0623         AmountEdit* edit = dynamic_cast<AmountEdit*>(*it);
0624         KMyMoneyPayeeCombo* payee = dynamic_cast<KMyMoneyPayeeCombo*>(*it);
0625         if (combo)
0626             combo->setPlaceholderText(QString());
0627         if (edit)
0628             edit->setPlaceholderText(QString());
0629         if (lineedit)
0630             lineedit->setPlaceholderText(QString());
0631         if (payee)
0632             payee->setPlaceholderText(QString());
0633     }
0634 }
0635 
0636 void InvestTransaction::tabOrderInForm(QWidgetList& tabOrderWidgets) const
0637 {
0638     Q_D(const InvestTransaction);
0639     // activity
0640     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(0, (int)eTransactionForm::Column::Value1)));
0641 
0642     // date
0643     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(0, (int)eTransactionForm::Column::Value2)));
0644 
0645     // security
0646     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(1, (int)eTransactionForm::Column::Value1)));
0647 
0648     // shares
0649     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(1, (int)eTransactionForm::Column::Value2)));
0650 
0651     // account
0652     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(2, (int)eTransactionForm::Column::Value1)));
0653 
0654     // price
0655     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(2, (int)eTransactionForm::Column::Value2)));
0656 
0657     // make sure to have the fee category field and the split button as separate tab order widgets
0658     // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
0659     // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
0660     // go haywire when someone changes the KMyMoneyCategory object ...
0661     QWidget* w = d->m_form->cellWidget(3, (int)eTransactionForm::Column::Value1);
0662     tabOrderWidgets.append(focusWidget(w));
0663     w = w->findChild<QPushButton*>("splitButton");
0664     if (w)
0665         tabOrderWidgets.append(w);
0666 
0667     // fee amount
0668     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(3, (int)eTransactionForm::Column::Value2)));
0669 
0670     // the same applies for the interest categories
0671     w = d->m_form->cellWidget(4, (int)eTransactionForm::Column::Value1);
0672     tabOrderWidgets.append(focusWidget(w));
0673     w = w->findChild<QPushButton*>("splitButton");
0674     if (w)
0675         tabOrderWidgets.append(w);
0676 
0677     // interest amount
0678     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(4, (int)eTransactionForm::Column::Value2)));
0679 
0680     // memo
0681     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(5, (int)eTransactionForm::Column::Value1)));
0682 
0683     // state
0684     tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(6, (int)eTransactionForm::Column::Value2)));
0685 }
0686 
0687 void InvestTransaction::arrangeWidgetsInRegister(QMap<QString, QWidget*>& editWidgets)
0688 {
0689     Q_D(InvestTransaction);
0690     if (!d->m_parent)
0691         return;
0692 
0693     setupRegisterPalette(editWidgets);
0694 
0695     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Date, editWidgets["postdate"]);
0696     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Security, editWidgets["security"]);
0697     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Detail, editWidgets["activity"]);
0698     arrangeWidget(d->m_parent, d->m_startRow + 1, (int)eTransaction::Column::Detail, editWidgets["asset-account"]);
0699     arrangeWidget(d->m_parent, d->m_startRow + 2, (int)eTransaction::Column::Detail, editWidgets["interest-account"]->parentWidget());
0700     arrangeWidget(d->m_parent, d->m_startRow + 3, (int)eTransaction::Column::Detail, editWidgets["fee-account"]->parentWidget());
0701     arrangeWidget(d->m_parent, d->m_startRow + 4, (int)eTransaction::Column::Detail, editWidgets["memo"]);
0702     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Quantity, editWidgets["shares"]);
0703     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Price, editWidgets["price"]);
0704     arrangeWidget(d->m_parent, d->m_startRow + 2, (int)eTransaction::Column::Quantity, editWidgets["interest-amount"]);
0705     arrangeWidget(d->m_parent, d->m_startRow + 3, (int)eTransaction::Column::Quantity, editWidgets["fee-amount"]);
0706     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Value, editWidgets["total"]);
0707     arrangeWidget(d->m_parent, d->m_startRow + 1, (int)eTransaction::Column::Date, editWidgets["status"]);
0708 
0709     // increase the height of the row containing the memo widget
0710     d->m_parent->setRowHeight(d->m_startRow + 4, d->m_parent->rowHeightHint() * 3);
0711 }
0712 
0713 void InvestTransaction::tabOrderInRegister(QWidgetList& tabOrderWidgets) const
0714 {
0715     Q_D(const InvestTransaction);
0716     QWidget* w;
0717 
0718     // date
0719     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Date)));
0720     // security
0721     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Security)));
0722     // activity
0723     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Detail)));
0724     // shares
0725     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Quantity)));
0726     // price
0727     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Price)));
0728     // asset account
0729     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 1, (int)eTransaction::Column::Detail)));
0730 
0731     // make sure to have the category fields and the split button as separate tab order widgets
0732     // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
0733     // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
0734     // go haywire when someone changes the KMyMoneyCategory object ...
0735     w = d->m_parent->cellWidget(d->m_startRow + 2, (int)eTransaction::Column::Detail);    // interest account
0736     tabOrderWidgets.append(focusWidget(w));
0737     w = w->findChild<QPushButton*>("splitButton");
0738     if (w)
0739         tabOrderWidgets.append(w);
0740 
0741     // interest amount
0742     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 2, (int)eTransaction::Column::Quantity)));
0743 
0744     w = d->m_parent->cellWidget(d->m_startRow + 3, (int)eTransaction::Column::Detail);    // fee account
0745     tabOrderWidgets.append(focusWidget(w));
0746     w = w->findChild<QPushButton*>("splitButton");
0747     if (w)
0748         tabOrderWidgets.append(w);
0749 
0750     // fee amount
0751     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 3, (int)eTransaction::Column::Quantity)));
0752 
0753     // memo
0754     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 4, (int)eTransaction::Column::Detail)));
0755 
0756     // status
0757     tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 1, (int)eTransaction::Column::Date)));
0758 }
0759 
0760 eRegister::Action InvestTransaction::actionType() const
0761 {
0762     return eRegister::Action::None;
0763 }
0764 
0765 int InvestTransaction::numRowsRegister(bool expanded) const
0766 {
0767     Q_D(const InvestTransaction);
0768     int numRows = 1;
0769     if (expanded) {
0770         if (!d->m_inEdit) {
0771             if (haveAssetAccount() && !d->m_assetAccountSplit.accountId().isEmpty())
0772                 ++numRows;
0773             if (haveInterest() && d->m_interestSplits.count())
0774                 ++numRows;
0775             if (haveFees() && d->m_feeSplits.count())
0776                 ++numRows;
0777             if (!d->m_split.memo().isEmpty())
0778                 ++numRows;
0779         } else
0780             numRows = 5;
0781     }
0782     return numRows;
0783 }
0784 
0785 bool InvestTransaction::haveShares() const
0786 {
0787     Q_D(const InvestTransaction);
0788     auto rc = true;
0789     switch (d->m_transactionType) {
0790     case eMyMoney::Split::InvestmentTransactionType::Dividend:
0791     case eMyMoney::Split::InvestmentTransactionType::Yield:
0792     case eMyMoney::Split::InvestmentTransactionType::SplitShares:
0793     case eMyMoney::Split::InvestmentTransactionType::InterestIncome:
0794         rc = false;
0795         break;
0796 
0797     default:
0798         break;
0799     }
0800     return rc;
0801 }
0802 
0803 bool InvestTransaction::haveFees() const
0804 {
0805     Q_D(const InvestTransaction);
0806     auto rc = true;
0807     switch (d->m_transactionType) {
0808     case eMyMoney::Split::InvestmentTransactionType::AddShares:
0809     case eMyMoney::Split::InvestmentTransactionType::RemoveShares:
0810     case eMyMoney::Split::InvestmentTransactionType::SplitShares:
0811         rc = false;
0812         break;
0813 
0814     default:
0815         break;
0816     }
0817     return rc;
0818 }
0819 
0820 bool InvestTransaction::haveInterest() const
0821 {
0822     Q_D(const InvestTransaction);
0823     auto rc = false;
0824     switch (d->m_transactionType) {
0825     case eMyMoney::Split::InvestmentTransactionType::BuyShares:
0826     case eMyMoney::Split::InvestmentTransactionType::SellShares:
0827     case eMyMoney::Split::InvestmentTransactionType::Dividend:
0828     case eMyMoney::Split::InvestmentTransactionType::ReinvestDividend:
0829     case eMyMoney::Split::InvestmentTransactionType::Yield:
0830     case eMyMoney::Split::InvestmentTransactionType::InterestIncome:
0831         rc = true;
0832         break;
0833 
0834     default:
0835         break;
0836     }
0837     return rc;
0838 }
0839 
0840 bool InvestTransaction::havePrice() const
0841 {
0842     Q_D(const InvestTransaction);
0843     auto rc = false;
0844     switch (d->m_transactionType) {
0845     case eMyMoney::Split::InvestmentTransactionType::BuyShares:
0846     case eMyMoney::Split::InvestmentTransactionType::SellShares:
0847     case eMyMoney::Split::InvestmentTransactionType::ReinvestDividend:
0848         rc = true;
0849         break;
0850 
0851     default:
0852         break;
0853     }
0854     return rc;
0855 }
0856 
0857 bool InvestTransaction::haveAmount() const
0858 {
0859     Q_D(const InvestTransaction);
0860     auto rc = false;
0861     switch (d->m_transactionType) {
0862     case eMyMoney::Split::InvestmentTransactionType::BuyShares:
0863     case eMyMoney::Split::InvestmentTransactionType::SellShares:
0864     case eMyMoney::Split::InvestmentTransactionType::Dividend:
0865     case eMyMoney::Split::InvestmentTransactionType::Yield:
0866     case eMyMoney::Split::InvestmentTransactionType::InterestIncome:
0867         rc = true;
0868         break;
0869 
0870     default:
0871         break;
0872     }
0873     return rc;
0874 }
0875 
0876 bool InvestTransaction::haveAssetAccount() const
0877 {
0878     Q_D(const InvestTransaction);
0879     auto rc = true;
0880     switch (d->m_transactionType) {
0881     case eMyMoney::Split::InvestmentTransactionType::AddShares:
0882     case eMyMoney::Split::InvestmentTransactionType::RemoveShares:
0883     case eMyMoney::Split::InvestmentTransactionType::SplitShares:
0884     case eMyMoney::Split::InvestmentTransactionType::ReinvestDividend:
0885         rc = false;
0886         break;
0887 
0888     default:
0889         break;
0890     }
0891     return rc;
0892 }
0893 
0894 bool InvestTransaction::haveSplitRatio() const
0895 {
0896     Q_D(const InvestTransaction);
0897     return d->m_transactionType == eMyMoney::Split::InvestmentTransactionType::SplitShares;
0898 }
0899 
0900 void InvestTransaction::splits(MyMoneySplit& assetAccountSplit, QList<MyMoneySplit>& interestSplits, QList<MyMoneySplit>& feeSplits) const
0901 {
0902     Q_D(const InvestTransaction);
0903     assetAccountSplit = d->m_assetAccountSplit;
0904     interestSplits = d->m_interestSplits;
0905     feeSplits = d->m_feeSplits;
0906 }
0907 
0908 int InvestTransaction::numRowsRegister() const
0909 {
0910     return RegisterItem::numRowsRegister();
0911 }
0912 
0913 TransactionEditor* InvestTransaction::createEditor(TransactionEditorContainer* regForm, const KMyMoneyRegister::SelectedTransactions& list, const QDate& lastPostDate)
0914 {
0915 #ifndef KMM_DESIGNER
0916     Q_D(InvestTransaction);
0917     d->m_inRegisterEdit = regForm == d->m_parent;
0918     return new InvestTransactionEditor(regForm, this, list, lastPostDate);
0919 #else
0920     return NULL;
0921 #endif
0922 }
0923