File indexing completed on 2024-05-12 05:07:48
0001 /* 0002 SPDX-FileCopyrightText: 2016-2022 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "newspliteditor.h" 0007 0008 // ---------------------------------------------------------------------------- 0009 // QT Includes 0010 0011 #include <QAction> 0012 #include <QCompleter> 0013 #include <QConcatenateTablesProxyModel> 0014 #include <QDate> 0015 #include <QDebug> 0016 #include <QHeaderView> 0017 #include <QSortFilterProxyModel> 0018 #include <QStringList> 0019 #include <QTreeView> 0020 0021 // ---------------------------------------------------------------------------- 0022 // KDE Includes 0023 0024 #include <KLocalizedString> 0025 0026 // ---------------------------------------------------------------------------- 0027 // Project Includes 0028 0029 #include "accountcreator.h" 0030 #include "accountsmodel.h" 0031 #include "costcentermodel.h" 0032 #include "creditdebitedit.h" 0033 #include "icons.h" 0034 #include "journalmodel.h" 0035 #include "kcurrencycalculator.h" 0036 #include "kmymoneyaccountcombo.h" 0037 #include "kmymoneysettings.h" 0038 #include "kmymoneyutils.h" 0039 #include "menuenums.h" 0040 #include "mymoneyaccount.h" 0041 #include "mymoneyenums.h" 0042 #include "mymoneyexception.h" 0043 #include "mymoneyfile.h" 0044 #include "mymoneysecurity.h" 0045 #include "payeecreator.h" 0046 #include "payeesmodel.h" 0047 #include "securitiesmodel.h" 0048 #include "splitmodel.h" 0049 #include "splitview.h" 0050 #include "tagcreator.h" 0051 #include "tagsmodel.h" 0052 #include "widgethintframe.h" 0053 0054 #include "ui_newspliteditor.h" 0055 0056 using namespace Icons; 0057 0058 struct NewSplitEditor::Private 0059 { 0060 Q_DISABLE_COPY_MOVE(Private) 0061 0062 Private(NewSplitEditor* parent) 0063 : q(parent) 0064 , ui(new Ui_NewSplitEditor) 0065 , tabOrderUi(nullptr) 0066 , accountsModel(new AccountNamesFilterProxyModel(parent)) 0067 , payeesModel(new QSortFilterProxyModel(parent)) 0068 , costCenterModel(new QSortFilterProxyModel(parent)) 0069 , splitModel(nullptr) 0070 , accepted(false) 0071 , costCenterRequired(false) 0072 , showValuesInverted(false) 0073 , loadingSplit(false) 0074 , isIncomeExpense(false) 0075 , readOnly(false) 0076 , postDate(QDate::currentDate()) 0077 , frameCollection(nullptr) 0078 { 0079 accountsModel->setObjectName("AccountNamesFilterProxyModel"); 0080 costCenterModel->setObjectName("SortedCostCenterModel"); 0081 payeesModel->setObjectName("SortedPayeesModel"); 0082 0083 costCenterModel->setSortLocaleAware(true); 0084 costCenterModel->setSortCaseSensitivity(Qt::CaseInsensitive); 0085 0086 payeesModel->setSortLocaleAware(true); 0087 payeesModel->setSortCaseSensitivity(Qt::CaseInsensitive); 0088 } 0089 0090 ~Private() 0091 { 0092 delete ui; 0093 } 0094 0095 bool checkForValidSplit(bool doUserInteraction = true); 0096 0097 bool costCenterChanged(int costCenterIndex); 0098 bool categoryChanged(const QString& accountId); 0099 bool numberChanged(const QString& newNumber); 0100 bool amountChanged(); 0101 void setupTabOrder(); 0102 void createCategory(); 0103 void createPayee(); 0104 void createTag(); 0105 0106 NewSplitEditor* q; 0107 Ui_NewSplitEditor* ui; 0108 Ui_NewSplitEditor* tabOrderUi; 0109 AccountNamesFilterProxyModel* accountsModel; 0110 QSortFilterProxyModel* payeesModel; 0111 QSortFilterProxyModel* costCenterModel; 0112 SplitModel* splitModel; 0113 bool accepted; 0114 bool costCenterRequired; 0115 bool showValuesInverted; 0116 bool loadingSplit; 0117 bool isIncomeExpense; 0118 bool readOnly; 0119 MyMoneyAccount counterAccount; 0120 MyMoneyAccount category; 0121 MyMoneySecurity commodity; 0122 MyMoneyMoney value; 0123 MyMoneyMoney shares; 0124 QDate postDate; 0125 WidgetHintFrameCollection* frameCollection; 0126 }; 0127 0128 bool NewSplitEditor::Private::checkForValidSplit(bool doUserInteraction) 0129 { 0130 QStringList infos; 0131 bool rc = true; 0132 if(!costCenterChanged(ui->costCenterCombo->currentIndex())) { 0133 infos << ui->costCenterCombo->toolTip(); 0134 rc = false; 0135 } 0136 0137 if (!categoryChanged(ui->accountCombo->getSelected())) { 0138 infos << ui->accountCombo->toolTip(); 0139 rc = false; 0140 } 0141 0142 if(doUserInteraction) { 0143 /// @todo add dialog here that shows the @a infos 0144 } 0145 return rc; 0146 } 0147 0148 bool NewSplitEditor::Private::costCenterChanged(int costCenterIndex) 0149 { 0150 bool rc = true; 0151 WidgetHintFrame::hide(ui->costCenterCombo, 0152 i18nc("@info:tooltip costcenter combo in split editor", "The cost center this transaction should be assigned to.")); 0153 if(costCenterIndex != -1) { 0154 if(costCenterRequired && ui->costCenterCombo->currentText().isEmpty()) { 0155 WidgetHintFrame::show( 0156 ui->costCenterCombo, 0157 i18nc("@info:tooltip costcenter combo in split editor", "A cost center assignment is required for a transaction in the selected category.")); 0158 rc = false; 0159 } 0160 } 0161 return rc; 0162 } 0163 0164 bool NewSplitEditor::Private::categoryChanged(const QString& accountId) 0165 { 0166 bool rc = true; 0167 isIncomeExpense = false; 0168 WidgetHintFrame::hide(ui->accountCombo, i18nc("@info:tooltip category combo in split editor", "The category this split should be assigned to.")); 0169 if(!accountId.isEmpty()) { 0170 try { 0171 const auto account = MyMoneyFile::instance()->account(accountId); 0172 const bool isCategory = account.isIncomeExpense(); 0173 ui->costCenterCombo->setEnabled(isCategory); 0174 ui->costCenterLabel->setEnabled(isCategory); 0175 ui->numberEdit->setDisabled(isCategory); 0176 ui->numberLabel->setDisabled(isCategory); 0177 0178 if (isCategory) { 0179 ui->numberEdit->clear(); 0180 } else { 0181 numberChanged(ui->numberEdit->text()); 0182 } 0183 0184 const auto accountIdx = MyMoneyFile::instance()->accountsModel()->indexById(accountId); 0185 const auto currencyId = accountIdx.data(eMyMoney::Model::AccountCurrencyIdRole).toString(); 0186 const auto currency = MyMoneyFile::instance()->currenciesModel()->itemById(currencyId); 0187 0188 // in case the commodity changes, we need to update the shares part 0189 if (currency.id() != ui->creditDebitEdit->sharesCommodity().id()) { 0190 ui->creditDebitEdit->setSharesCommodity(currency); 0191 const auto sharesAmount = ui->creditDebitEdit->value(); 0192 ui->creditDebitEdit->setShares(sharesAmount); 0193 // switch to value display so that we show the transaction commodity 0194 // for single currency data entry this does not have an effect 0195 ui->creditDebitEdit->setDisplayState(MultiCurrencyEdit::DisplayValue); 0196 0197 if (!sharesAmount.isZero()) { 0198 KCurrencyCalculator::updateConversion(ui->creditDebitEdit, postDate); 0199 } 0200 } 0201 0202 costCenterRequired = account.isCostCenterRequired(); 0203 rc &= costCenterChanged(ui->costCenterCombo->currentIndex()); 0204 0205 } catch (MyMoneyException&) { 0206 qDebug() << "Ooops: invalid account id" << accountId << "in" << Q_FUNC_INFO; 0207 } 0208 } else { 0209 WidgetHintFrame::show(ui->accountCombo, i18nc("@info:tooltip category combo in split editor", "A category assignment is required for a split.")); 0210 rc = false; 0211 } 0212 return rc; 0213 } 0214 0215 bool NewSplitEditor::Private::numberChanged(const QString& newNumber) 0216 { 0217 bool rc = true; 0218 WidgetHintFrame::hide(ui->numberEdit, i18n("The check number used for this transaction.")); 0219 if(!newNumber.isEmpty()) { 0220 const auto model = MyMoneyFile::instance()->journalModel(); 0221 const auto rows = model->rowCount(); 0222 const auto accountId = ui->accountCombo->getSelected(); 0223 for (int row = 0; row < rows; ++row) { 0224 const auto idx = model->index(row, 0); 0225 if (idx.data(eMyMoney::Model::JournalSplitAccountIdRole).toString() == accountId) { 0226 if (idx.data(eMyMoney::Model::JournalSplitNumberRole).toString() == newNumber) { 0227 WidgetHintFrame::show(ui->numberEdit, i18n("The check number <b>%1</b> has already been used in this account.", newNumber)); 0228 rc = false; 0229 break; 0230 } 0231 } 0232 } 0233 } 0234 return rc; 0235 } 0236 0237 bool NewSplitEditor::Private::amountChanged() 0238 { 0239 // bypass a simple reverse in sign because the exchange rate does not change 0240 if ((shares != -ui->creditDebitEdit->shares()) || (value != -ui->creditDebitEdit->value())) { 0241 // and if there is no real change, don't call the currency calculator 0242 if ((shares != ui->creditDebitEdit->shares()) || (value != ui->creditDebitEdit->value())) { 0243 KCurrencyCalculator::updateConversion(ui->creditDebitEdit, postDate); 0244 shares = ui->creditDebitEdit->shares(); 0245 value = ui->creditDebitEdit->value(); 0246 } 0247 } else { 0248 shares = -shares; 0249 value = -value; 0250 } 0251 return true; 0252 } 0253 0254 void NewSplitEditor::Private::setupTabOrder() 0255 { 0256 const auto defaultTabOrder = QStringList{ 0257 QLatin1String("creditDebitEdit"), 0258 QLatin1String("payeeEdit"), 0259 QLatin1String("numberEdit"), 0260 QLatin1String("accountCombo"), 0261 QLatin1String("costCenterCombo"), 0262 QLatin1String("tagContainer"), 0263 QLatin1String("memoEdit"), 0264 QLatin1String("enterButton"), 0265 QLatin1String("cancelButton"), 0266 }; 0267 q->setProperty("kmm_defaulttaborder", defaultTabOrder); 0268 q->setProperty("kmm_currenttaborder", KMyMoneyUtils::tabOrder(QLatin1String("splitTransactionEditor"), defaultTabOrder)); 0269 0270 KMyMoneyUtils::setupTabOrder(q, q->property("kmm_currenttaborder").toStringList()); 0271 } 0272 0273 void NewSplitEditor::Private::createCategory() 0274 { 0275 // delay the execution of this code for 150ms so 0276 // that a click on the cancel or enter button has 0277 // a chance to be executed before. 0278 auto creator = new AccountCreator(q); 0279 creator->setComboBox(ui->accountCombo); 0280 creator->addButton(ui->cancelButton); 0281 creator->addButton(ui->enterButton); 0282 creator->setAccountType(eMyMoney::Account::Type::Expense); 0283 if (ui->creditDebitEdit->haveValue() && ui->creditDebitEdit->value().isPositive()) { 0284 creator->setAccountType(eMyMoney::Account::Type::Income); 0285 } 0286 creator->createAccount(); 0287 } 0288 0289 void NewSplitEditor::Private::createPayee() 0290 { 0291 auto creator = new PayeeCreator(q); 0292 creator->setComboBox(ui->payeeEdit); 0293 creator->addButton(ui->cancelButton); 0294 creator->addButton(ui->enterButton); 0295 creator->createPayee(); 0296 } 0297 0298 void NewSplitEditor::Private::createTag() 0299 { 0300 auto creator = new TagCreator(q); 0301 creator->setTagContainer(ui->tagContainer); 0302 creator->addButton(ui->cancelButton); 0303 creator->addButton(ui->enterButton); 0304 creator->createTag(); 0305 } 0306 0307 NewSplitEditor::NewSplitEditor(QWidget* parent, const MyMoneySecurity& commodity, const QString& counterAccountId) 0308 : QWidget(parent) 0309 , d(new Private(this)) 0310 { 0311 d->commodity = commodity; 0312 auto const file = MyMoneyFile::instance(); 0313 auto view = qobject_cast<SplitView*>(parent->parentWidget()); 0314 Q_ASSERT(view != nullptr); 0315 d->splitModel = qobject_cast<SplitModel*>(view->model()); 0316 0317 auto const model = MyMoneyFile::instance()->accountsModel(); 0318 d->counterAccount = model->itemById(counterAccountId); 0319 0320 d->ui->setupUi(this); 0321 d->ui->enterButton->setIcon(Icons::get(Icon::DialogOK)); 0322 d->ui->cancelButton->setIcon(Icons::get(Icon::DialogCancel)); 0323 0324 auto concatModel = new QConcatenateTablesProxyModel(parent); 0325 concatModel->addSourceModel(file->payeesModel()->emptyPayee()); 0326 concatModel->addSourceModel(file->payeesModel()); 0327 d->payeesModel->setSortRole(Qt::DisplayRole); 0328 d->payeesModel->setSourceModel(concatModel); 0329 d->payeesModel->sort(0); 0330 0331 d->ui->payeeEdit->setEditable(true); 0332 d->ui->payeeEdit->lineEdit()->setClearButtonEnabled(true); 0333 d->ui->payeeEdit->setModel(d->payeesModel); 0334 d->ui->payeeEdit->setModelColumn(0); 0335 d->ui->payeeEdit->completer()->setCompletionMode(QCompleter::PopupCompletion); 0336 d->ui->payeeEdit->completer()->setFilterMode(Qt::MatchContains); 0337 0338 d->accountsModel->addAccountGroup(QVector<eMyMoney::Account::Type> {eMyMoney::Account::Type::Asset, eMyMoney::Account::Type::Liability, eMyMoney::Account::Type::Income, eMyMoney::Account::Type::Expense, eMyMoney::Account::Type::Equity,}); 0339 d->accountsModel->setHideEquityAccounts(false); 0340 d->accountsModel->setHideZeroBalancedEquityAccounts(false); 0341 d->accountsModel->setHideZeroBalancedAccounts(false); 0342 d->accountsModel->setShowAllEntries(KMyMoneySettings::showAllAccounts()); 0343 d->accountsModel->setSourceModel(model); 0344 d->accountsModel->sort(AccountsModel::Column::AccountName); 0345 d->ui->accountCombo->setModel(d->accountsModel); 0346 d->ui->accountCombo->setSplitActionVisible(false); 0347 0348 d->ui->tagContainer->setModel(file->tagsModel()->modelWithEmptyItem()); 0349 0350 d->costCenterModel->setSortRole(Qt::DisplayRole); 0351 d->costCenterModel->setSourceModel(MyMoneyFile::instance()->costCenterModel()); 0352 d->costCenterModel->sort(AccountsModel::Column::AccountName); 0353 0354 d->ui->costCenterCombo->setEditable(true); 0355 d->ui->costCenterCombo->setModel(d->costCenterModel); 0356 d->ui->costCenterCombo->setModelColumn(0); 0357 d->ui->costCenterCombo->completer()->setFilterMode(Qt::MatchContains); 0358 0359 d->frameCollection = new WidgetHintFrameCollection(this); 0360 d->frameCollection->addFrame(new WidgetHintFrame(d->ui->costCenterCombo)); 0361 d->frameCollection->addFrame(new WidgetHintFrame(d->ui->accountCombo)); 0362 d->frameCollection->addFrame(new WidgetHintFrame(d->ui->numberEdit, WidgetHintFrame::Warning)); 0363 d->frameCollection->addWidget(d->ui->enterButton); 0364 0365 d->ui->creditDebitEdit->setAllowEmpty(true); 0366 d->ui->creditDebitEdit->setCommodity(commodity); 0367 0368 connect(d->ui->numberEdit, &QLineEdit::textChanged, this, [&](const QString& txt) { 0369 d->numberChanged(txt); 0370 }); 0371 connect(d->ui->costCenterCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int costCenterIndex) { 0372 d->costCenterChanged(costCenterIndex); 0373 }); 0374 connect(d->ui->accountCombo, &KMyMoneyAccountCombo::accountSelected, this, [&](const QString& categoryId) { 0375 d->categoryChanged(categoryId); 0376 }); 0377 connect(d->ui->creditDebitEdit, &CreditDebitEdit::amountChanged, this, [&]() { 0378 d->amountChanged(); 0379 }); 0380 0381 connect(d->ui->cancelButton, &QToolButton::clicked, this, &NewSplitEditor::reject); 0382 connect(d->ui->enterButton, &QToolButton::clicked, this, &NewSplitEditor::acceptEdit); 0383 0384 d->ui->accountCombo->installEventFilter(this); 0385 d->ui->payeeEdit->installEventFilter(this); 0386 0387 // setup the tab order 0388 d->setupTabOrder(); 0389 0390 // determine order of credit and debit edit widgets 0391 // based on their visual order in the ledger 0392 int creditColumn = SplitModel::Column::Payment; 0393 int debitColumn = SplitModel::Column::Deposit; 0394 0395 QWidget* w(this); 0396 do { 0397 w = w->parentWidget(); 0398 const auto v = qobject_cast<const QTableView*>(w); 0399 if (v) { 0400 creditColumn = v->horizontalHeader()->visualIndex(creditColumn); 0401 debitColumn = v->horizontalHeader()->visualIndex(debitColumn); 0402 break; 0403 } 0404 } while (w); 0405 0406 // in case they are in the opposite order, we swap the edit widgets 0407 if (debitColumn < creditColumn) { 0408 d->ui->creditDebitEdit->swapCreditDebit(); 0409 } 0410 0411 // set focus to first tab field once we return to event loop 0412 const auto tabOrder = property("kmm_currenttaborder").toStringList(); 0413 if (!tabOrder.isEmpty()) { 0414 const auto focusWidget = findChild<QWidget*>(tabOrder.first()); 0415 if (focusWidget) { 0416 QMetaObject::invokeMethod(focusWidget, "setFocus", Qt::QueuedConnection); 0417 } 0418 } 0419 } 0420 0421 NewSplitEditor::~NewSplitEditor() 0422 { 0423 } 0424 0425 void NewSplitEditor::setAmountPlaceHolderText(const QAbstractItemModel* model) 0426 { 0427 d->ui->creditDebitEdit->setPlaceholderText(model->headerData(SplitModel::Column::Payment, Qt::Horizontal).toString(), 0428 model->headerData(SplitModel::Column::Deposit, Qt::Horizontal).toString()); 0429 } 0430 0431 void NewSplitEditor::setPostDate(const QDate& date) 0432 { 0433 d->postDate = date; 0434 } 0435 0436 void NewSplitEditor::setShowValuesInverted(bool inverse) 0437 { 0438 d->showValuesInverted = inverse; 0439 } 0440 0441 bool NewSplitEditor::showValuesInverted() 0442 { 0443 return d->showValuesInverted; 0444 } 0445 0446 bool NewSplitEditor::accepted() const 0447 { 0448 return d->accepted; 0449 } 0450 0451 void NewSplitEditor::acceptEdit() 0452 { 0453 if(d->checkForValidSplit()) { 0454 d->accepted = true; 0455 Q_EMIT done(); 0456 } 0457 } 0458 0459 void NewSplitEditor::reject() 0460 { 0461 Q_EMIT done(); 0462 } 0463 0464 void NewSplitEditor::keyPressEvent(QKeyEvent* event) 0465 { 0466 if (!event->modifiers() || (event->modifiers() & Qt::KeypadModifier && event->key() == Qt::Key_Enter)) { 0467 switch (event->key()) { 0468 case Qt::Key_Enter: 0469 case Qt::Key_Return: 0470 { 0471 if(focusWidget() == d->ui->cancelButton) { 0472 reject(); 0473 } else { 0474 if (d->ui->enterButton->isEnabled() && !d->readOnly) { 0475 d->ui->enterButton->setFocus(); 0476 d->ui->enterButton->click(); 0477 } 0478 return; 0479 } 0480 } 0481 break; 0482 0483 case Qt::Key_Escape: 0484 reject(); 0485 break; 0486 0487 default: 0488 event->ignore(); 0489 return; 0490 } 0491 } else { 0492 const auto keySeq = QKeySequence(event->modifiers() | event->key()); 0493 0494 if (keySeq.matches(pActions[eMenu::Action::EditTabOrder]->shortcut())) { 0495 QPointer<TabOrderDialog> tabOrderDialog = new TabOrderDialog(this); 0496 auto tabOrderWidget = static_cast<TabOrderEditorInterface*>(qt_metacast("TabOrderEditorInterface")); 0497 if (tabOrderWidget) { 0498 tabOrderDialog->setTarget(tabOrderWidget); 0499 auto tabOrder = property("kmm_defaulttaborder").toStringList(); 0500 tabOrderDialog->setDefaultTabOrder(tabOrder); 0501 tabOrder = property("kmm_currenttaborder").toStringList(); 0502 tabOrderDialog->setTabOrder(tabOrder); 0503 0504 if ((tabOrderDialog->exec() == QDialog::Accepted) && tabOrderDialog) { 0505 tabOrderWidget->storeTabOrder(tabOrderDialog->tabOrder()); 0506 d->setupTabOrder(); 0507 } 0508 } 0509 tabOrderDialog->deleteLater(); 0510 } 0511 event->ignore(); 0512 } 0513 } 0514 0515 QString NewSplitEditor::accountId() const 0516 { 0517 return d->ui->accountCombo->getSelected(); 0518 } 0519 0520 void NewSplitEditor::setAccountId(const QString& id) 0521 { 0522 d->ui->accountCombo->clearEditText(); 0523 d->ui->accountCombo->setSelected(id); 0524 } 0525 0526 0527 QString NewSplitEditor::memo() const 0528 { 0529 return d->ui->memoEdit->toPlainText(); 0530 } 0531 0532 void NewSplitEditor::setMemo(const QString& memo) 0533 { 0534 d->ui->memoEdit->setPlainText(memo); 0535 } 0536 0537 MyMoneyMoney NewSplitEditor::shares() const 0538 { 0539 return d->ui->creditDebitEdit->shares(); 0540 } 0541 0542 void NewSplitEditor::setShares(const MyMoneyMoney& amount) 0543 { 0544 d->shares = amount; 0545 d->ui->creditDebitEdit->setShares(amount); 0546 } 0547 0548 MyMoneyMoney NewSplitEditor::value() const 0549 { 0550 return d->ui->creditDebitEdit->value(); 0551 } 0552 0553 void NewSplitEditor::setValue(const MyMoneyMoney& amount) 0554 { 0555 d->value = amount; 0556 d->ui->creditDebitEdit->setValue(amount); 0557 } 0558 0559 QString NewSplitEditor::costCenterId() const 0560 { 0561 const int row = d->ui->costCenterCombo->currentIndex(); 0562 QModelIndex index = d->ui->costCenterCombo->model()->index(row, 0); 0563 return d->ui->costCenterCombo->model()->data(index, eMyMoney::Model::Roles::IdRole).toString(); 0564 } 0565 0566 void NewSplitEditor::setCostCenterId(const QString& id) 0567 { 0568 const auto baseIdx = MyMoneyFile::instance()->costCenterModel()->indexById(id); 0569 if (baseIdx.isValid()) { 0570 const auto index = MyMoneyFile::baseModel()->mapFromBaseSource(d->costCenterModel, baseIdx); 0571 if(index.isValid()) { 0572 d->ui->costCenterCombo->setCurrentIndex(index.row()); 0573 } 0574 } 0575 } 0576 0577 QString NewSplitEditor::number() const 0578 { 0579 return d->ui->numberEdit->text(); 0580 } 0581 0582 void NewSplitEditor::setNumber(const QString& number) 0583 { 0584 d->ui->numberEdit->setText(number); 0585 } 0586 0587 QString NewSplitEditor::payeeId() const 0588 { 0589 const auto idx = d->payeesModel->index(d->ui->payeeEdit->currentIndex(), 0); 0590 return idx.data(eMyMoney::Model::IdRole).toString(); 0591 } 0592 0593 void NewSplitEditor::setPayeeId(const QString& id) 0594 { 0595 QModelIndexList indexes = d->payeesModel->match(d->payeesModel->index(0, 0), eMyMoney::Model::IdRole, QVariant(id), 1, Qt::MatchFlags(Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive))); 0596 int row(0); 0597 if (!indexes.isEmpty()) { 0598 row = indexes.first().row(); 0599 } 0600 d->ui->payeeEdit->setCurrentIndex(row); 0601 } 0602 0603 void NewSplitEditor::setTagIdList(const QList<QString>& tagIds) 0604 { 0605 d->ui->tagContainer->loadTags(tagIds); 0606 } 0607 0608 QList<QString> NewSplitEditor::tagIdList() const 0609 { 0610 return d->ui->tagContainer->selectedTags(); 0611 } 0612 0613 void NewSplitEditor::startLoadingSplit() 0614 { 0615 d->loadingSplit = true; 0616 } 0617 0618 void NewSplitEditor::finishLoadingSplit() 0619 { 0620 d->loadingSplit = false; 0621 } 0622 0623 void NewSplitEditor::setReadOnly(bool readOnly) 0624 { 0625 if (d->readOnly != readOnly) { 0626 d->readOnly = readOnly; 0627 if (readOnly) { 0628 d->frameCollection->removeWidget(d->ui->enterButton); 0629 d->ui->enterButton->setDisabled(true); 0630 } else { 0631 // no need to enable the enter button here as the 0632 // framewidget will take care of it anyway 0633 d->frameCollection->addWidget(d->ui->enterButton); 0634 } 0635 } 0636 } 0637 0638 void NewSplitEditor::setupUi(QWidget* parent) 0639 { 0640 if (d->tabOrderUi == nullptr) { 0641 d->tabOrderUi = new Ui::NewSplitEditor; 0642 } 0643 d->tabOrderUi->setupUi(parent); 0644 } 0645 0646 void NewSplitEditor::storeTabOrder(const QStringList& tabOrder) 0647 { 0648 KMyMoneyUtils::storeTabOrder(QLatin1String("splitTransactionEditor"), tabOrder); 0649 } 0650 0651 bool NewSplitEditor::focusNextPrevChild(bool next) 0652 { 0653 auto rc = KMyMoneyUtils::tabFocusHelper(this, next); 0654 0655 if (rc == false) { 0656 rc = QWidget::focusNextPrevChild(next); 0657 } 0658 return rc; 0659 } 0660 0661 bool NewSplitEditor::eventFilter(QObject* o, QEvent* e) 0662 { 0663 auto cb = qobject_cast<QComboBox*>(o); 0664 if (o) { 0665 // filter out wheel events for combo boxes if the popup view is not visible 0666 if ((e->type() == QEvent::Wheel) && !cb->view()->isVisible()) { 0667 return true; 0668 } 0669 0670 if (e->type() == QEvent::FocusOut) { 0671 if (o == d->ui->accountCombo) { 0672 if (!d->ui->accountCombo->popup()->isVisible() && !cb->currentText().isEmpty()) { 0673 const auto accountId = d->ui->accountCombo->getSelected(); 0674 const auto accountIdx = MyMoneyFile::instance()->accountsModel()->indexById(accountId); 0675 if (!accountIdx.isValid() || accountIdx.data(eMyMoney::Model::AccountFullNameRole).toString().compare(cb->currentText())) { 0676 d->createCategory(); 0677 } 0678 } 0679 0680 } else if (o == d->ui->payeeEdit) { 0681 if (!cb->currentText().isEmpty()) { 0682 const auto index(cb->findText(cb->currentText(), Qt::MatchExactly | Qt::MatchCaseSensitive)); 0683 if (index != -1) { 0684 cb->setCurrentIndex(index); 0685 } else { 0686 d->createPayee(); 0687 } 0688 } 0689 } else if (o == d->ui->tagContainer->tagCombo()) { 0690 if (!cb->currentText().isEmpty()) { 0691 const auto index(cb->findText(cb->currentText(), Qt::MatchExactly | Qt::MatchCaseSensitive)); 0692 if (index != -1) { 0693 cb->setCurrentIndex(index); 0694 } else { 0695 d->createTag(); 0696 } 0697 } 0698 } 0699 } 0700 } 0701 return QWidget::eventFilter(o, e); 0702 }