File indexing completed on 2024-05-12 16:44:08

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 "stdtransaction.h"
0008 #include "stdtransaction_p.h"
0009 
0010 // ----------------------------------------------------------------------------
0011 // QT Includes
0012 
0013 #include <QString>
0014 #include <QPainter>
0015 #include <QWidget>
0016 #include <QList>
0017 #include <QBoxLayout>
0018 #include <QPushButton>
0019 
0020 // ----------------------------------------------------------------------------
0021 // KDE Includes
0022 
0023 #include <KLocalizedString>
0024 
0025 // ----------------------------------------------------------------------------
0026 // Project Includes
0027 
0028 #include "kmymoneypayeecombo.h"
0029 #include "kmymoneycombo.h"
0030 #include "kmymoneytagcombo.h"
0031 #include "tabbar.h"
0032 #include "ktagcontainer.h"
0033 #include "mymoneytransaction.h"
0034 #include "mymoneysplit.h"
0035 #include "mymoneyexception.h"
0036 #include "mymoneyfile.h"
0037 #include "register.h"
0038 #include "transactionform.h"
0039 #include "kmymoneylineedit.h"
0040 #include "kmymoneyutils.h"
0041 #ifndef KMM_DESIGNER
0042 #include "stdtransactioneditor.h"
0043 #endif
0044 
0045 #include "kmymoneysettings.h"
0046 #include "widgetenums.h"
0047 #include "mymoneyenums.h"
0048 
0049 using namespace eWidgets;
0050 using namespace KMyMoneyRegister;
0051 using namespace KMyMoneyTransactionForm;
0052 
0053 StdTransaction::StdTransaction(Register *parent, const MyMoneyTransaction& transaction, const MyMoneySplit& split, int uniqueId) :
0054     Transaction(*new StdTransactionPrivate, parent, transaction, split, uniqueId)
0055 {
0056     Q_D(StdTransaction);
0057     d->m_showAccountRow = false;
0058     try {
0059         d->m_categoryHeader = i18n("Category");
0060         switch (transaction.splitCount()) {
0061         default:
0062             d->m_category = i18nc("Split transaction (category replacement)", "Split transaction");
0063             break;
0064 
0065         case 0: // the empty transaction
0066         case 1:
0067             break;
0068 
0069         case 2:
0070             setupFormHeader(d->m_transaction.splitByAccount(d->m_split.accountId(), false).accountId());
0071             break;
0072         }
0073     } catch (const MyMoneyException &e) {
0074         qDebug() << "Problem determining the category for transaction '" << d->m_transaction.id() << "'. Reason: " << e.what()  << "\n";
0075     }
0076     d->m_rowsForm = 6;
0077 
0078     if (KMyMoneyUtils::transactionType(d->m_transaction) == KMyMoneyUtils::InvestmentTransaction) {
0079         MyMoneySplit stockSplit = KMyMoneyUtils::stockSplit(d->m_transaction);
0080         d->m_payee = MyMoneyFile::instance()->account(stockSplit.accountId()).name();
0081         QString addon;
0082         if (stockSplit.action() == MyMoneySplit::actionName(eMyMoney::Split::Action::BuyShares)) {
0083             if (stockSplit.value().isNegative()) {
0084                 addon = i18n("Sell");
0085             } else {
0086                 addon = i18n("Buy");
0087             }
0088         } else if (stockSplit.action() == MyMoneySplit::actionName(eMyMoney::Split::Action::Dividend)) {
0089             addon = i18n("Dividend");
0090         } else if (stockSplit.action() == MyMoneySplit::actionName(eMyMoney::Split::Action::Yield)) {
0091             addon = i18n("Yield");
0092         } else if (stockSplit.action() == MyMoneySplit::actionName(eMyMoney::Split::Action::InterestIncome)) {
0093             addon = i18n("Interest Income");
0094         }
0095         if (!addon.isEmpty()) {
0096             d->m_payee += QString(" (%1)").arg(addon);
0097         }
0098         d->m_payeeHeader = i18n("Activity");
0099         d->m_category = i18n("Investment transaction");
0100     }
0101 
0102     // setup initial size
0103     setNumRowsRegister(numRowsRegister(KMyMoneySettings::showRegisterDetailed()));
0104 
0105     emit parent->itemAdded(this);
0106 }
0107 
0108 StdTransaction::~StdTransaction()
0109 {
0110 }
0111 
0112 const char* StdTransaction::className()
0113 {
0114     return "StdTransaction";
0115 }
0116 
0117 void StdTransaction::setupFormHeader(const QString& id)
0118 {
0119     Q_D(StdTransaction);
0120     d->m_category = MyMoneyFile::instance()->accountToCategory(id);
0121     switch (MyMoneyFile::instance()->account(id).accountGroup()) {
0122     case eMyMoney::Account::Type::Asset:
0123     case eMyMoney::Account::Type::Liability:
0124         d->m_categoryHeader = d->m_split.shares().isNegative() ? i18n("Transfer to") : i18n("Transfer from");
0125         break;
0126 
0127     default:
0128         d->m_categoryHeader = i18n("Category");
0129         break;
0130     }
0131 }
0132 
0133 eRegister::Action StdTransaction::actionType() const
0134 {
0135     Q_D(const StdTransaction);
0136     eRegister::Action action = eRegister::Action::None;
0137 
0138     // if at least one split is referencing an income or
0139     // expense account, we will not call it a transfer
0140 
0141     auto found = false;
0142     foreach (const auto split, d->m_transaction.splits()) {
0143         if (split.accountId() == d->m_split.accountId())
0144             continue;
0145         auto acc = MyMoneyFile::instance()->account(split.accountId());
0146         if (acc.accountGroup() == eMyMoney::Account::Type::Income //
0147                 || acc.accountGroup() == eMyMoney::Account::Type::Expense) {
0148             // otherwise, we have to determine between deposit and withdrawal
0149             action = d->m_split.shares().isNegative() ? eRegister::Action::Withdrawal : eRegister::Action::Deposit;
0150             found = true;
0151             break;
0152         }
0153     }
0154     // otherwise, it's a transfer
0155     if (!found)
0156         action = eRegister::Action::Transfer;
0157 
0158     return action;
0159 }
0160 
0161 void StdTransaction::loadTab(TransactionForm* form)
0162 {
0163     Q_D(StdTransaction);
0164     KMyMoneyTransactionForm::TabBar* bar = form->getTabBar();
0165     bar->setSignalEmission(eTabBar::SignalEmission::Never);
0166     for (auto i = 0; i < bar->count(); ++i) {
0167         bar->setTabEnabled(i, true);
0168     }
0169 
0170     if (d->m_transaction.splitCount() > 0) {
0171         bar->setCurrentIndex((int)actionType());
0172     }
0173     bar->setSignalEmission(eTabBar::SignalEmission::Always);
0174 }
0175 
0176 int StdTransaction::numColsForm() const
0177 {
0178     return 4;
0179 }
0180 
0181 void StdTransaction::setupForm(TransactionForm* form)
0182 {
0183     Transaction::setupForm(form);
0184     form->setSpan(4, (int)eTransactionForm::Column::Value1, 3, 1);
0185 }
0186 
0187 bool StdTransaction::showRowInForm(int row) const
0188 {
0189     Q_D(const StdTransaction);
0190     return row == 0 ? d->m_showAccountRow : true;
0191 }
0192 
0193 void StdTransaction::setShowRowInForm(int row, bool show)
0194 {
0195     Q_D(StdTransaction);
0196     if (row == 0)
0197         d->m_showAccountRow = show;
0198 }
0199 
0200 bool StdTransaction::formCellText(QString& txt, Qt::Alignment& align, int row, int col, QPainter* /* painter */)
0201 {
0202     Q_D(const StdTransaction);
0203     // if(m_transaction != MyMoneyTransaction()) {
0204     switch (row) {
0205     case 0:
0206         switch (col) {
0207         case (int)eTransactionForm::Column::Label1:
0208             align |= Qt::AlignLeft;
0209             txt = i18n("Account");
0210             break;
0211         }
0212         break;
0213 
0214     case 1:
0215         switch (col) {
0216         case (int)eTransactionForm::Column::Label1:
0217             align |= Qt::AlignLeft;
0218             txt = d->m_payeeHeader;
0219             break;
0220 
0221         case (int)eTransactionForm::Column::Value1:
0222             align |= Qt::AlignLeft;
0223             txt = d->m_payee;
0224             break;
0225 
0226         case (int)eTransactionForm::Column::Label2:
0227             align |= Qt::AlignLeft;
0228             if (haveNumberField())
0229                 txt = i18n("Number");
0230             break;
0231 
0232         case (int)eTransactionForm::Column::Value2:
0233             align |= Qt::AlignRight;
0234             if (haveNumberField())
0235                 txt = d->m_split.number();
0236             break;
0237         }
0238         break;
0239 
0240     case 2:
0241         switch (col) {
0242         case (int)eTransactionForm::Column::Label1:
0243             align |= Qt::AlignLeft;
0244             txt = d->m_categoryHeader;
0245             break;
0246 
0247         case (int)eTransactionForm::Column::Value1:
0248             align |= Qt::AlignLeft;
0249             txt = d->m_category;
0250             if (!d->m_transaction.id().isEmpty()) {
0251                 if (txt.isEmpty() && !d->m_split.value().isZero())
0252                     txt = i18n("*** UNASSIGNED ***");
0253             }
0254             break;
0255 
0256         case (int)eTransactionForm::Column::Label2:
0257             align |= Qt::AlignLeft;
0258             txt = i18n("Date");
0259             break;
0260 
0261         case (int)eTransactionForm::Column::Value2:
0262             align |= Qt::AlignRight;
0263             if (!d->m_transaction.id().isEmpty())
0264                 txt = QLocale().toString(d->m_transaction.postDate(), QLocale::ShortFormat);
0265             break;
0266         }
0267         break;
0268 
0269     case 3:
0270         switch (col) {
0271         case (int)eTransactionForm::Column::Label1:
0272             align |= Qt::AlignLeft;
0273             txt = i18n("Tags");
0274             break;
0275 
0276         case (int)eTransactionForm::Column::Value1:
0277             align |= Qt::AlignLeft;
0278             if (!d->m_tagList.isEmpty()) {
0279                 for (auto i = 0; i < d->m_tagList.size() - 1; ++i)
0280                     txt += d->m_tagList[i] + ", ";
0281                 txt += d->m_tagList.last();
0282             }
0283             //if (m_transaction != MyMoneyTransaction())
0284             //  txt = m_split.tagId();
0285             break;
0286 
0287         case (int)eTransactionForm::Column::Label2:
0288             align |= Qt::AlignLeft;
0289             txt = i18n("Amount");
0290             break;
0291 
0292         case (int)eTransactionForm::Column::Value2:
0293             align |= Qt::AlignRight;
0294             if (!d->m_transaction.id().isEmpty()) {
0295                 txt = (d->m_split.value(d->m_transaction.commodity(), d->m_splitCurrencyId).abs()).formatMoney(d->m_account.fraction());
0296             }
0297             break;
0298         }
0299         break;
0300 
0301     case 4:
0302         switch (col) {
0303         case (int)eTransactionForm::Column::Label1:
0304             align |= Qt::AlignLeft;
0305             txt = i18n("Memo");
0306             break;
0307 
0308         case (int)eTransactionForm::Column::Value1:
0309             align &= ~Qt::AlignVCenter;
0310             align |= Qt::AlignTop;
0311             align |= Qt::AlignLeft;
0312             if (!d->m_transaction.id().isEmpty())
0313                 txt = d->m_split.memo().section('\n', 0, 2);
0314             break;
0315         }
0316         break;
0317 
0318     case 5:
0319         switch (col) {
0320         case (int)eTransactionForm::Column::Label2:
0321             align |= Qt::AlignLeft;
0322             txt = i18n("Status");
0323             break;
0324 
0325         case (int)eTransactionForm::Column::Value2:
0326             align |= Qt::AlignRight;
0327             txt = reconcileState();
0328             break;
0329         }
0330     }
0331 
0332     // }
0333     if (col == (int)eTransactionForm::Column::Value2 && row == 1) {
0334         return haveNumberField();
0335     }
0336     return (col == (int)eTransactionForm::Column::Value1 && row < 5) || (col == (int)eTransactionForm::Column::Value2 && row > 0 && row != 4);
0337 }
0338 
0339 void StdTransaction::registerCellText(QString& txt, Qt::Alignment& align, int row, int col, QPainter* painter)
0340 {
0341     Q_D(const StdTransaction);
0342     switch (row) {
0343     case 0:
0344         switch (col) {
0345         case (int)eTransaction::Column::Number:
0346             align |= Qt::AlignLeft;
0347             if (haveNumberField())
0348                 txt = d->m_split.number();
0349             break;
0350 
0351         case (int)eTransaction::Column::Date:
0352             align |= Qt::AlignLeft;
0353             txt = QLocale().toString(d->m_transaction.postDate(), QLocale::ShortFormat);
0354             break;
0355 
0356         case (int)eTransaction::Column::Detail:
0357             switch (d->m_parent->getDetailsColumnType()) {
0358             case eRegister::DetailColumn::PayeeFirst:
0359                 txt = d->m_payee;
0360                 break;
0361             case eRegister::DetailColumn::AccountFirst:
0362                 txt = d->m_category;
0363                 if (!d->m_tagList.isEmpty()) {
0364                     txt += " ( ";
0365                     for (auto i = 0; i < d->m_tagList.size() - 1; ++i) {
0366                         txt += "<span style='color: " + d->m_tagColorList[i].name() + "'>&#x25CF;</span> " + d->m_tagList[i] + ", ";
0367                     }
0368                     txt += "<span style='color: " + d->m_tagColorList.last().name() + "'>&#x25CF;</span> " + d->m_tagList.last() + " )";
0369                 }
0370                 break;
0371             }
0372             align |= Qt::AlignLeft;
0373             if (txt.isEmpty() && d->m_rowsRegister < 3) {
0374                 singleLineMemo(txt, d->m_split);
0375             }
0376             if (txt.isEmpty() && d->m_rowsRegister < 2) {
0377                 if (d->m_account.accountType() != eMyMoney::Account::Type::Income
0378                         && d->m_account.accountType() != eMyMoney::Account::Type::Expense) {
0379                     txt = d->m_category;
0380                     if (txt.isEmpty() && !d->m_split.value().isZero()) {
0381                         txt = i18n("*** UNASSIGNED ***");
0382                         if (painter)
0383                             painter->setPen(KMyMoneySettings::schemeColor(SchemeColor::TransactionErroneous));
0384                     }
0385 
0386                     if (!d->m_tagList.isEmpty()) {
0387                         txt += " ( ";
0388                         for (auto i = 0; i < d->m_tagList.size() - 1; ++i) {
0389                             txt += "<span style='color: " + d->m_tagColorList[i].name() + "'>&#x25CF;</span> " + d->m_tagList[i] + ", ";
0390                         }
0391                         txt += "<span style='color: " + d->m_tagColorList.last().name() + "'>&#x25CF;</span> " + d->m_tagList.last() + " )";
0392                     }
0393                 }
0394             }
0395             break;
0396 
0397         case (int)eTransaction::Column::ReconcileFlag:
0398             align |= Qt::AlignHCenter;
0399             txt = reconcileState(false);
0400             break;
0401 
0402         case (int)eTransaction::Column::Payment:
0403             align |= Qt::AlignRight;
0404             if (d->m_split.value().isNegative()) {
0405                 txt = (-d->m_split.value(d->m_transaction.commodity(), d->m_splitCurrencyId)).formatMoney(d->m_account.fraction());
0406             }
0407             break;
0408 
0409         case (int)eTransaction::Column::Deposit:
0410             align |= Qt::AlignRight;
0411             if (!d->m_split.value().isNegative()) {
0412                 txt = d->m_split.value(d->m_transaction.commodity(), d->m_splitCurrencyId).formatMoney(d->m_account.fraction());
0413             }
0414             break;
0415 
0416         case (int)eTransaction::Column::Balance:
0417             align |= Qt::AlignRight;
0418             if (d->m_showBalance)
0419                 txt = d->m_balance.formatMoney(d->m_account.fraction());
0420             else
0421                 txt = "----";
0422             break;
0423 
0424         case (int)eTransaction::Column::Account:
0425             // txt = m_objects->account(m_transaction.splits()[0].accountId()).name();
0426             txt = MyMoneyFile::instance()->account(d->m_split.accountId()).name();
0427             break;
0428 
0429         default:
0430             break;
0431         }
0432         break;
0433 
0434     case 1:
0435         switch (col) {
0436         case (int)eTransaction::Column::Detail:
0437             switch (d->m_parent->getDetailsColumnType()) {
0438             case eRegister::DetailColumn::PayeeFirst:
0439                 txt = d->m_category;
0440                 if (txt.isEmpty() && !d->m_split.value().isZero()) {
0441                     txt = i18n("*** UNASSIGNED ***");
0442                     if (painter)
0443                         painter->setPen(KMyMoneySettings::schemeColor(SchemeColor::TransactionErroneous));
0444                 }
0445                 if (!d->m_tagList.isEmpty()) {
0446                     txt += " ( ";
0447                     for (auto i = 0; i < d->m_tagList.size() - 1; ++i) {
0448                         txt += "<span style='color: " + d->m_tagColorList[i].name() + "'>&#x25CF;</span> " + d->m_tagList[i] + ", ";
0449                     }
0450                     txt += "<span style='color: " + d->m_tagColorList.last().name() + "'>&#x25CF;</span> " + d->m_tagList.last() + " )";
0451                 }
0452                 break;
0453             case eRegister::DetailColumn::AccountFirst:
0454                 txt = d->m_payee;
0455                 if (txt.isEmpty()) {
0456                     singleLineMemo(txt, d->m_split);
0457                 }
0458                 break;
0459             }
0460             align |= Qt::AlignLeft;
0461             break;
0462 
0463         default:
0464             break;
0465         }
0466         break;
0467 
0468     case 2:
0469         switch (col) {
0470         case (int)eTransaction::Column::Detail:
0471             align |= Qt::AlignLeft;
0472             singleLineMemo(txt, d->m_split);
0473             break;
0474 
0475         default:
0476             break;
0477         }
0478         break;
0479     }
0480 }
0481 
0482 int StdTransaction::registerColWidth(int col, const QFontMetrics& cellFontMetrics)
0483 {
0484     QString txt;
0485     int firstRow = 0, lastRow = numRowsRegister();
0486 
0487     int nw = 0;
0488     for (int i = firstRow; i <= lastRow; ++i) {
0489         Qt::Alignment align;
0490         registerCellText(txt, align, i, col, 0);
0491         int w = cellFontMetrics.width(txt + "   ");
0492         if (w > nw)
0493             nw = w;
0494     }
0495     return nw;
0496 }
0497 
0498 void StdTransaction::arrangeWidgetsInForm(QMap<QString, QWidget*>& editWidgets)
0499 {
0500     Q_D(StdTransaction);
0501     if (!d->m_form || !d->m_parent)
0502         return;
0503 
0504     setupFormPalette(editWidgets);
0505 
0506     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Label1, editWidgets["account-label"]);
0507     arrangeWidget(d->m_form, 0, (int)eTransactionForm::Column::Value1, editWidgets["account"]);
0508     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Label1, editWidgets["cashflow"]);
0509     arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Value1, editWidgets["payee"]);
0510     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Label1, editWidgets["category-label"]);
0511     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Value1, editWidgets["category"]->parentWidget());
0512     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Label1, editWidgets["tag-label"]);
0513     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Value1, editWidgets["tag"]);
0514     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Label1, editWidgets["memo-label"]);
0515     arrangeWidget(d->m_form, 4, (int)eTransactionForm::Column::Value1, editWidgets["memo"]);
0516     if (haveNumberField()) {
0517         arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Label2, editWidgets["number-label"]);
0518         arrangeWidget(d->m_form, 1, (int)eTransactionForm::Column::Value2, editWidgets["number"]);
0519     }
0520     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Label2, editWidgets["date-label"]);
0521     arrangeWidget(d->m_form, 2, (int)eTransactionForm::Column::Value2, editWidgets["postdate"]);
0522     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Label2, editWidgets["amount-label"]);
0523     arrangeWidget(d->m_form, 3, (int)eTransactionForm::Column::Value2, editWidgets["amount"]);
0524     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Label2, editWidgets["status-label"]);
0525     arrangeWidget(d->m_form, 5, (int)eTransactionForm::Column::Value2, editWidgets["status"]);
0526 
0527     // get rid of the hints. we don't need them for the form
0528     QMap<QString, QWidget*>::iterator it;
0529     for (it = editWidgets.begin(); it != editWidgets.end(); ++it) {
0530         KMyMoneyCombo* combo = dynamic_cast<KMyMoneyCombo*>(*it);
0531         KMyMoneyLineEdit* edit = dynamic_cast<KMyMoneyLineEdit*>(*it);
0532         KMyMoneyPayeeCombo* payee = dynamic_cast<KMyMoneyPayeeCombo*>(*it);
0533         KTagContainer* tag = dynamic_cast<KTagContainer*>(*it);
0534         if (combo)
0535             combo->setPlaceholderText(QString());
0536         if (edit)
0537             edit->setPlaceholderText(QString());
0538         if (payee)
0539             payee->setPlaceholderText(QString());
0540         if (tag)
0541             tag->tagCombo()->setPlaceholderText(QString());
0542     }
0543 
0544     auto form = dynamic_cast<KMyMoneyTransactionForm::TransactionForm*>(d->m_form);
0545     auto w = dynamic_cast<KMyMoneyTransactionForm::TabBar*>(editWidgets["tabbar"]);
0546     if (w && form) {
0547         // insert the tabbar in the boxlayout so it will take the place of the original tabbar which was hidden
0548         if (auto boxLayout = dynamic_cast<QBoxLayout*>(form->getTabBar()->parentWidget()->layout()))
0549             boxLayout->insertWidget(0, w);
0550     }
0551 }
0552 
0553 void StdTransaction::tabOrderInForm(QWidgetList& tabOrderWidgets) const
0554 {
0555     Q_D(const StdTransaction);
0556     QStringList taborder = KMyMoneySettings::stdTransactionFormTabOrder().split(',', QString::SkipEmptyParts);
0557     QStringList::const_iterator it_s = taborder.constBegin();
0558     QWidget* w;
0559     while (it_s != taborder.constEnd()) {
0560         if (*it_s == "account") {
0561             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(0, (int)eTransactionForm::Column::Value1)));
0562         } else if (*it_s == "cashflow") {
0563             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(1, (int)eTransactionForm::Column::Label1)));
0564         } else if (*it_s == "payee") {
0565             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(1, (int)eTransactionForm::Column::Value1)));
0566         } else if (*it_s == "category") {
0567             // make sure to have the category field and the split button as separate tab order widgets
0568             // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
0569             // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
0570             // go haywire when someone changes the KMyMoneyCategory object ...
0571             w = d->m_form->cellWidget(2, (int)eTransactionForm::Column::Value1);
0572             tabOrderWidgets.append(focusWidget(w));
0573             w = w->findChild<QPushButton*>("splitButton");
0574             if (w)
0575                 tabOrderWidgets.append(w);
0576         } else if (*it_s == "tag") {
0577             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(3, (int)eTransactionForm::Column::Value1)));
0578         } else if (*it_s == "memo") {
0579             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(4, (int)eTransactionForm::Column::Value1)));
0580         } else if (*it_s == "number") {
0581             if (haveNumberField()) {
0582                 if ((w = focusWidget(d->m_form->cellWidget(1, (int)eTransactionForm::Column::Value2))))
0583                     tabOrderWidgets.append(w);
0584             }
0585         } else if (*it_s == "date") {
0586             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(2, (int)eTransactionForm::Column::Value2)));
0587         } else if (*it_s == "amount") {
0588             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(3, (int)eTransactionForm::Column::Value2)));
0589         } else if (*it_s == "state") {
0590             tabOrderWidgets.append(focusWidget(d->m_form->cellWidget(5, (int)eTransactionForm::Column::Value2)));
0591         }
0592         ++it_s;
0593     }
0594 }
0595 
0596 void StdTransaction::arrangeWidgetsInRegister(QMap<QString, QWidget*>& editWidgets)
0597 {
0598     Q_D(StdTransaction);
0599     if (!d->m_parent)
0600         return;
0601 
0602     setupRegisterPalette(editWidgets);
0603 
0604     if (haveNumberField())
0605         arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Number, editWidgets["number"]);
0606     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Date, editWidgets["postdate"]);
0607     arrangeWidget(d->m_parent, d->m_startRow + 1, (int)eTransaction::Column::Date, editWidgets["status"]);
0608     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Detail, editWidgets["payee"]);
0609     arrangeWidget(d->m_parent, d->m_startRow + 1, (int)eTransaction::Column::Detail, editWidgets["category"]->parentWidget());
0610     arrangeWidget(d->m_parent, d->m_startRow + 2, (int)eTransaction::Column::Detail, editWidgets["tag"]);
0611     arrangeWidget(d->m_parent, d->m_startRow + 3, (int)eTransaction::Column::Detail, editWidgets["memo"]);
0612     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Payment, editWidgets["payment"]);
0613     arrangeWidget(d->m_parent, d->m_startRow + 0, (int)eTransaction::Column::Deposit, editWidgets["deposit"]);
0614 
0615     // increase the height of the row containing the memo widget
0616     d->m_parent->setRowHeight(d->m_startRow + 3, d->m_parent->rowHeightHint() * 3);
0617 }
0618 
0619 void StdTransaction::tabOrderInRegister(QWidgetList& tabOrderWidgets) const
0620 {
0621     Q_D(const StdTransaction);
0622     QStringList taborder = KMyMoneySettings::stdTransactionRegisterTabOrder().split(',', QString::SkipEmptyParts);
0623     QStringList::const_iterator it_s = taborder.constBegin();
0624     QWidget* w;
0625     while (it_s != taborder.constEnd()) {
0626         if (*it_s == "number") {
0627             if (haveNumberField()) {
0628                 if ((w = focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Number))))
0629                     tabOrderWidgets.append(w);
0630             }
0631         } else if (*it_s == "date") {
0632             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Date)));
0633         } else if (*it_s == "payee") {
0634             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Detail)));
0635         } else if (*it_s == "category") {
0636             // make sure to have the category field and the split button as separate tab order widgets
0637             // ok, we have to have some internal knowledge about the KMyMoneyCategory object, but
0638             // it's one of our own widgets, so we actually don't care. Just make sure, that we don't
0639             // go haywire when someone changes the KMyMoneyCategory object ...
0640             w = d->m_parent->cellWidget(d->m_startRow + 1, (int)eTransaction::Column::Detail);
0641             tabOrderWidgets.append(focusWidget(w));
0642             w = w->findChild<QPushButton*>("splitButton");
0643             if (w)
0644                 tabOrderWidgets.append(w);
0645         } else if (*it_s == "tag") {
0646             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 2, (int)eTransaction::Column::Detail)));
0647         } else if (*it_s == "memo") {
0648             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 3, (int)eTransaction::Column::Detail)));
0649         } else if (*it_s == "payment") {
0650             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Payment)));
0651         } else if (*it_s == "deposit") {
0652             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 0, (int)eTransaction::Column::Deposit)));
0653         } else if (*it_s == "state") {
0654             tabOrderWidgets.append(focusWidget(d->m_parent->cellWidget(d->m_startRow + 1, (int)eTransaction::Column::Date)));
0655         }
0656         ++it_s;
0657     }
0658 }
0659 
0660 int StdTransaction::numRowsRegister(bool expanded) const
0661 {
0662     Q_D(const StdTransaction);
0663     int numRows = 1;
0664     if (expanded) {
0665         numRows = 4;
0666         if (!d->m_inEdit) {
0667             //When not in edit Tags haven't a separate row;
0668             numRows--;
0669             if (d->m_payee.isEmpty()) {
0670                 numRows--;
0671             }
0672             if (d->m_split.memo().isEmpty()) {
0673                 numRows--;
0674             }
0675             // For income and expense accounts that only have
0676             // two splits we only show one line, because the
0677             // account name is already contained in the account column.
0678             if (d->m_account.accountType() == eMyMoney::Account::Type::Income
0679                     || d->m_account.accountType() == eMyMoney::Account::Type::Expense) {
0680                 if (numRows > 2 && d->m_transaction.splitCount() == 2)
0681                     numRows = 1;
0682             }
0683         }
0684     }
0685     return numRows;
0686 }
0687 
0688 int StdTransaction::numRowsRegister() const
0689 {
0690     return RegisterItem::numRowsRegister();
0691 }
0692 
0693 TransactionEditor* StdTransaction::createEditor(TransactionEditorContainer* regForm, const KMyMoneyRegister::SelectedTransactions& list, const QDate& lastPostDate)
0694 {
0695 #ifndef KMM_DESIGNER
0696     Q_D(StdTransaction);
0697     d->m_inRegisterEdit = regForm == d->m_parent;
0698     return new StdTransactionEditor(regForm, this, list, lastPostDate);
0699 #else
0700     return NULL;
0701 #endif
0702 }