File indexing completed on 2024-05-12 16:43:51
0001 /* 0002 SPDX-FileCopyrightText: 2000-2002 Michael Edwardes <mte@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2000-2002 Javier Campos Morales <javi_c@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2000-2002 Felix Rodriguez <frodriguez@users.sourceforge.net> 0005 SPDX-FileCopyrightText: 2000-2002 John C <thetacoturtle@users.sourceforge.net> 0006 SPDX-FileCopyrightText: 2000-2002 Thomas Baumgart <ipwizard@users.sourceforge.net> 0007 SPDX-FileCopyrightText: 2000-2002 Kevin Tambascio <ktambascio@users.sourceforge.net> 0008 SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #ifndef KSCHEDULEDVIEW_P_H 0013 #define KSCHEDULEDVIEW_P_H 0014 0015 #include "kscheduledview.h" 0016 0017 // ---------------------------------------------------------------------------- 0018 // QT Includes 0019 0020 #include <QList> 0021 #include <QTimer> 0022 #include <QPushButton> 0023 #include <QMenu> 0024 #include <QIcon> 0025 #include <QScopedPointer> 0026 #include <QDebug> 0027 0028 // ---------------------------------------------------------------------------- 0029 // KDE Includes 0030 0031 #include <KLocalizedString> 0032 #include <KConfig> 0033 #include <KMessageBox> 0034 #include <KSharedConfig> 0035 #include <KTreeWidgetSearchLine> 0036 #include <KTreeWidgetSearchLineWidget> 0037 0038 // ---------------------------------------------------------------------------- 0039 // Project Includes 0040 0041 #include "ui_kscheduledview.h" 0042 #include "kmymoneyviewbase_p.h" 0043 #include "kenterscheduledlg.h" 0044 #include "kbalancewarning.h" 0045 #include "transactioneditor.h" 0046 #include "kconfirmmanualenterdlg.h" 0047 #include "kmymoneymvccombo.h" 0048 #include "kmymoneyutils.h" 0049 #include "kmymoneysettings.h" 0050 #include "mymoneyexception.h" 0051 #include "kscheduletreeitem.h" 0052 #include "ktreewidgetfilterlinewidget.h" 0053 #include "icons/icons.h" 0054 #include "mymoneyutils.h" 0055 #include "mymoneyaccount.h" 0056 #include "mymoneymoney.h" 0057 #include "mymoneysecurity.h" 0058 #include "mymoneyschedule.h" 0059 #include "mymoneyfile.h" 0060 #include "mymoneypayee.h" 0061 #include "mymoneysplit.h" 0062 #include "mymoneytransaction.h" 0063 #include "mymoneyenums.h" 0064 #include "menuenums.h" 0065 #include "dialogenums.h" 0066 0067 using namespace Icons; 0068 0069 class KScheduledViewPrivate : public KMyMoneyViewBasePrivate 0070 { 0071 Q_DECLARE_PUBLIC(KScheduledView) 0072 0073 public: 0074 explicit KScheduledViewPrivate(KScheduledView *qq) : 0075 KMyMoneyViewBasePrivate(), 0076 q_ptr(qq), 0077 ui(new Ui::KScheduledView), 0078 m_kaccPopup(nullptr), 0079 m_openBills(true), 0080 m_openDeposits(true), 0081 m_openTransfers(true), 0082 m_openLoans(true), 0083 m_needLoad(true), 0084 m_searchWidget(nullptr), 0085 m_balanceWarning(nullptr) 0086 { 0087 } 0088 0089 ~KScheduledViewPrivate() 0090 { 0091 if(!m_needLoad) 0092 writeConfig(); 0093 delete ui; 0094 } 0095 0096 void init() 0097 { 0098 Q_Q(KScheduledView); 0099 m_needLoad = false; 0100 ui->setupUi(q); 0101 0102 // create the searchline widget 0103 // and insert it into the existing layout 0104 m_searchWidget = new KTreeWidgetFilterLineWidget(q, ui->m_scheduleTree); 0105 ui->vboxLayout->insertWidget(1, m_searchWidget); 0106 0107 //enable custom context menu 0108 ui->m_scheduleTree->setContextMenuPolicy(Qt::CustomContextMenu); 0109 ui->m_scheduleTree->setSelectionMode(QAbstractItemView::SingleSelection); 0110 0111 readConfig(); 0112 0113 q->connect(ui->m_qbuttonNew, &QAbstractButton::clicked, pActions[eMenu::Action::NewSchedule], &QAction::trigger); 0114 0115 // attach popup to 'Filter...' button 0116 m_kaccPopup = new QMenu(q); 0117 ui->m_accountsCombo->setMenu(m_kaccPopup); 0118 q->connect(m_kaccPopup, &QMenu::triggered, q, &KScheduledView::slotAccountActivated); 0119 0120 KGuiItem::assign(ui->m_qbuttonNew, KMyMoneyUtils::scheduleNewGuiItem()); 0121 KGuiItem::assign(ui->m_accountsCombo, KMyMoneyUtils::accountsFilterGuiItem()); 0122 0123 q->connect(ui->m_scheduleTree, &QWidget::customContextMenuRequested, q, &KScheduledView::customContextMenuRequested); 0124 q->connect(ui->m_scheduleTree, &QTreeWidget::itemSelectionChanged, 0125 q, &KScheduledView::slotSetSelectedItem); 0126 0127 q->connect(ui->m_scheduleTree, &QTreeWidget::itemDoubleClicked, 0128 q, &KScheduledView::slotListItemExecuted); 0129 q->connect(ui->m_scheduleTree, &QTreeWidget::itemExpanded, 0130 q, &KScheduledView::slotListViewExpanded); 0131 q->connect(ui->m_scheduleTree, &QTreeWidget::itemCollapsed, 0132 q, &KScheduledView::slotListViewCollapsed); 0133 0134 q->connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, q, &KScheduledView::refresh); 0135 } 0136 0137 static bool accountNameLessThan(const MyMoneyAccount& acc1, const MyMoneyAccount& acc2) 0138 { 0139 return acc1.name().toLower() < acc2.name().toLower(); 0140 } 0141 0142 void refreshSchedule(bool full, const QString& schedId) 0143 { 0144 Q_Q(KScheduledView); 0145 ui->m_scheduleTree->header()->setFont(KMyMoneySettings::listHeaderFontEx()); 0146 0147 ui->m_scheduleTree->clear(); 0148 0149 try { 0150 if (full) { 0151 try { 0152 m_kaccPopup->clear(); 0153 0154 MyMoneyFile* file = MyMoneyFile::instance(); 0155 0156 // extract a list of all accounts under the asset group 0157 // and sort them by name 0158 QList<MyMoneyAccount> list; 0159 QStringList accountList = file->asset().accountList(); 0160 accountList.append(file->liability().accountList()); 0161 file->accountList(list, accountList, true); 0162 qStableSort(list.begin(), list.end(), accountNameLessThan); 0163 0164 QList<MyMoneyAccount>::ConstIterator it_a; 0165 for (it_a = list.constBegin(); it_a != list.constEnd(); ++it_a) { 0166 if (!(*it_a).isClosed()) { 0167 QAction* act; 0168 act = m_kaccPopup->addAction((*it_a).name()); 0169 act->setCheckable(true); 0170 act->setChecked(true); 0171 } 0172 } 0173 0174 } catch (const MyMoneyException &e) { 0175 KMessageBox::detailedError(q, i18n("Unable to load accounts: "), e.what()); 0176 } 0177 } 0178 0179 MyMoneyFile *file = MyMoneyFile::instance(); 0180 QList<MyMoneySchedule> scheduledItems = file->scheduleList(); 0181 0182 if (scheduledItems.count() == 0) 0183 return; 0184 0185 //disable sorting for performance 0186 ui->m_scheduleTree->setSortingEnabled(false); 0187 0188 KScheduleTreeItem *itemBills = new KScheduleTreeItem(ui->m_scheduleTree); 0189 itemBills->setIcon(0, Icons::get(Icon::Expense)); 0190 itemBills->setText(0, i18n("Bills")); 0191 itemBills->setData(0, KScheduleTreeItem::OrderRole, QVariant("0")); 0192 itemBills->setFirstColumnSpanned(true); 0193 itemBills->setFlags(Qt::ItemIsEnabled); 0194 QFont bold = itemBills->font(0); 0195 bold.setBold(true); 0196 itemBills->setFont(0, bold); 0197 KScheduleTreeItem *itemDeposits = new KScheduleTreeItem(ui->m_scheduleTree); 0198 itemDeposits->setIcon(0, Icons::get(Icon::Income)); 0199 itemDeposits->setText(0, i18n("Deposits")); 0200 itemDeposits->setData(0, KScheduleTreeItem::OrderRole, QVariant("1")); 0201 itemDeposits->setFirstColumnSpanned(true); 0202 itemDeposits->setFlags(Qt::ItemIsEnabled); 0203 itemDeposits->setFont(0, bold); 0204 KScheduleTreeItem *itemLoans = new KScheduleTreeItem(ui->m_scheduleTree); 0205 itemLoans->setIcon(0, Icons::get(Icon::Loan)); 0206 itemLoans->setText(0, i18n("Loans")); 0207 itemLoans->setData(0, KScheduleTreeItem::OrderRole, QVariant("2")); 0208 itemLoans->setFirstColumnSpanned(true); 0209 itemLoans->setFlags(Qt::ItemIsEnabled); 0210 itemLoans->setFont(0, bold); 0211 KScheduleTreeItem *itemTransfers = new KScheduleTreeItem(ui->m_scheduleTree); 0212 itemTransfers->setIcon(0, Icons::get(Icon::Transaction)); 0213 itemTransfers->setText(0, i18n("Transfers")); 0214 itemTransfers->setData(0, KScheduleTreeItem::OrderRole, QVariant("3")); 0215 itemTransfers->setFirstColumnSpanned(true); 0216 itemTransfers->setFlags(Qt::ItemIsEnabled); 0217 itemTransfers->setFont(0, bold); 0218 0219 QList<MyMoneySchedule>::Iterator it; 0220 0221 QTreeWidgetItem *openItem = 0; 0222 0223 for (it = scheduledItems.begin(); it != scheduledItems.end(); ++it) { 0224 MyMoneySchedule schedData = (*it); 0225 QTreeWidgetItem* item = 0; 0226 0227 bool bContinue = true; 0228 QStringList::iterator accIt; 0229 for (accIt = m_filterAccounts.begin(); accIt != m_filterAccounts.end(); ++accIt) { 0230 if (*accIt == schedData.account().id()) { 0231 bContinue = false; // Filter it out 0232 break; 0233 } 0234 } 0235 0236 if (!bContinue) 0237 continue; 0238 0239 QTreeWidgetItem* parent = 0; 0240 switch (schedData.type()) { 0241 case eMyMoney::Schedule::Type::Any: 0242 // Should we display an error ? 0243 // We just sort it as bill and fall through here 0244 0245 case eMyMoney::Schedule::Type::Bill: 0246 parent = itemBills; 0247 break; 0248 0249 case eMyMoney::Schedule::Type::Deposit: 0250 parent = itemDeposits; 0251 break; 0252 0253 case eMyMoney::Schedule::Type::Transfer: 0254 parent = itemTransfers; 0255 break; 0256 0257 case eMyMoney::Schedule::Type::LoanPayment: 0258 parent = itemLoans; 0259 break; 0260 0261 } 0262 if (parent) { 0263 if (!KMyMoneySettings::hideFinishedSchedules() || !schedData.isFinished()) { 0264 item = addScheduleItem(parent, schedData); 0265 if (schedData.id() == schedId) 0266 openItem = item; 0267 } 0268 } 0269 } 0270 0271 if (openItem) { 0272 ui->m_scheduleTree->setCurrentItem(openItem); 0273 } 0274 // using a timeout is the only way, I got the 'ensureTransactionVisible' 0275 // working when coming from hidden form to visible form. I assume, this 0276 // has something to do with the delayed update of the display somehow. 0277 q->resize(q->width(), q->height() - 1); 0278 QTimer::singleShot(10, q, SLOT(slotTimerDone())); 0279 ui->m_scheduleTree->update(); 0280 0281 // force repaint in case the filter is set 0282 m_searchWidget->searchLine()->updateSearch(QString()); 0283 0284 if (m_openBills) 0285 itemBills->setExpanded(true); 0286 0287 if (m_openDeposits) 0288 itemDeposits->setExpanded(true); 0289 0290 if (m_openTransfers) 0291 itemTransfers->setExpanded(true); 0292 0293 if (m_openLoans) 0294 itemLoans->setExpanded(true); 0295 0296 } catch (const MyMoneyException &e) { 0297 KMessageBox::error(q, e.what()); 0298 } 0299 0300 for (int i = 0; i < ui->m_scheduleTree->columnCount(); ++i) { 0301 ui->m_scheduleTree->resizeColumnToContents(i); 0302 } 0303 0304 //reenable sorting after loading items 0305 ui->m_scheduleTree->setSortingEnabled(true); 0306 } 0307 0308 void readConfig() 0309 { 0310 KSharedConfigPtr config = KSharedConfig::openConfig(); 0311 KConfigGroup grp = config->group("Last Use Settings"); 0312 m_openBills = grp.readEntry("KScheduleView_openBills", true); 0313 m_openDeposits = grp.readEntry("KScheduleView_openDeposits", true); 0314 m_openTransfers = grp.readEntry("KScheduleView_openTransfers", true); 0315 m_openLoans = grp.readEntry("KScheduleView_openLoans", true); 0316 QByteArray columns; 0317 columns = grp.readEntry("KScheduleView_treeState", columns); 0318 ui->m_scheduleTree->header()->restoreState(columns); 0319 ui->m_scheduleTree->header()->setFont(KMyMoneySettings::listHeaderFontEx()); 0320 } 0321 0322 void writeConfig() 0323 { 0324 KSharedConfigPtr config = KSharedConfig::openConfig(); 0325 KConfigGroup grp = config->group("Last Use Settings"); 0326 grp.writeEntry("KScheduleView_openBills", m_openBills); 0327 grp.writeEntry("KScheduleView_openDeposits", m_openDeposits); 0328 grp.writeEntry("KScheduleView_openTransfers", m_openTransfers); 0329 grp.writeEntry("KScheduleView_openLoans", m_openLoans); 0330 QByteArray columns = ui->m_scheduleTree->header()->saveState(); 0331 grp.writeEntry("KScheduleView_treeState", columns); 0332 0333 config->sync(); 0334 } 0335 0336 QTreeWidgetItem* addScheduleItem(QTreeWidgetItem* parent, MyMoneySchedule& schedule) 0337 { 0338 KScheduleTreeItem* item = new KScheduleTreeItem(parent); 0339 item->setData(0, Qt::UserRole, QVariant::fromValue(schedule)); 0340 item->setData(0, KScheduleTreeItem::OrderRole, schedule.name()); 0341 if (!schedule.isFinished()) { 0342 if (schedule.isOverdue()) { 0343 item->setIcon(0, Icons::get(Icon::UpcomingEvents)); 0344 QBrush brush = item->foreground(0); 0345 brush.setColor(Qt::red); 0346 for (int i = 0; i < ui->m_scheduleTree->columnCount(); ++i) { 0347 item->setForeground(i, brush); 0348 } 0349 } else { 0350 item->setIcon(0, Icons::get(Icon::CalendarDay)); 0351 } 0352 } else { 0353 item->setIcon(0, Icons::get(Icon::DialogClose)); 0354 QBrush brush = item->foreground(0); 0355 brush.setColor(Qt::darkGreen); 0356 for (int i = 0; i < ui->m_scheduleTree->columnCount(); ++i) { 0357 item->setForeground(i, brush); 0358 } 0359 } 0360 0361 try { 0362 MyMoneyTransaction transaction = schedule.transaction(); 0363 MyMoneySplit s1 = (transaction.splits().size() < 1) ? MyMoneySplit() : transaction.splits()[0]; 0364 MyMoneySplit s2 = (transaction.splits().size() < 2) ? MyMoneySplit() : transaction.splits()[1]; 0365 MyMoneySplit split; 0366 MyMoneyAccount acc; 0367 0368 switch (schedule.type()) { 0369 case eMyMoney::Schedule::Type::Deposit: 0370 if (s1.value().isNegative()) 0371 split = s2; 0372 else 0373 split = s1; 0374 break; 0375 0376 case eMyMoney::Schedule::Type::LoanPayment: 0377 { 0378 auto found = false; 0379 foreach (const auto it_split, transaction.splits()) { 0380 acc = MyMoneyFile::instance()->account(it_split.accountId()); 0381 if (acc.accountGroup() == eMyMoney::Account::Type::Asset 0382 || acc.accountGroup() == eMyMoney::Account::Type::Liability) { 0383 if (acc.accountType() != eMyMoney::Account::Type::Loan 0384 && acc.accountType() != eMyMoney::Account::Type::AssetLoan) { 0385 split = it_split; 0386 found = true; 0387 break; 0388 } 0389 } 0390 } 0391 if (!found) { 0392 qWarning("Split for payment account not found in %s:%d.", __FILE__, __LINE__); 0393 } 0394 break; 0395 } 0396 default: 0397 if (!s1.value().isPositive()) 0398 split = s1; 0399 else 0400 split = s2; 0401 break; 0402 } 0403 acc = MyMoneyFile::instance()->account(split.accountId()); 0404 0405 item->setText(0, schedule.name()); 0406 MyMoneySecurity currency = MyMoneyFile::instance()->currency(acc.currencyId()); 0407 0408 QString accName = acc.name(); 0409 if (!accName.isEmpty()) { 0410 item->setText(1, accName); 0411 } else { 0412 item->setText(1, "---"); 0413 } 0414 item->setData(1, KScheduleTreeItem::OrderRole, QVariant(accName)); 0415 0416 QString payeeName; 0417 if (!s1.payeeId().isEmpty()) { 0418 payeeName = MyMoneyFile::instance()->payee(s1.payeeId()).name(); 0419 item->setText(2, payeeName); 0420 } else { 0421 item->setText(2, "---"); 0422 } 0423 item->setData(2, KScheduleTreeItem::OrderRole, QVariant(payeeName)); 0424 0425 MyMoneyMoney amount = split.shares().abs(); 0426 item->setData(3, Qt::UserRole, QVariant::fromValue(amount)); 0427 if (!accName.isEmpty()) { 0428 item->setText(3, QString("%1 ").arg(MyMoneyUtils::formatMoney(amount, acc, currency))); 0429 } else { 0430 //there are some cases where the schedule does not have an account 0431 //in those cases the account will not have a fraction 0432 //use base currency instead 0433 item->setText(3, QString("%1 ").arg(MyMoneyUtils::formatMoney(amount, MyMoneyFile::instance()->baseCurrency()))); 0434 } 0435 item->setTextAlignment(3, Qt::AlignRight | Qt::AlignVCenter); 0436 item->setData(3, KScheduleTreeItem::OrderRole, QVariant::fromValue(amount)); 0437 0438 // Do the real next payment like ms-money etc 0439 QDate nextDueDate; 0440 if (schedule.isFinished()) { 0441 item->setText(4, i18nc("Finished schedule", "Finished")); 0442 } else { 0443 nextDueDate = schedule.adjustedNextDueDate(); 0444 item->setText(4, QLocale().toString(schedule.adjustedNextDueDate(), QLocale::ShortFormat)); 0445 } 0446 item->setData(4, KScheduleTreeItem::OrderRole, QVariant(nextDueDate)); 0447 item->setText(5, i18nc("Frequency of schedule", schedule.occurrenceToString().toLatin1())); 0448 item->setText(6, KMyMoneyUtils::paymentMethodToString(schedule.paymentType())); 0449 } catch (const MyMoneyException &e) { 0450 item->setText(0, "Error:"); 0451 item->setText(1, e.what()); 0452 } 0453 return item; 0454 } 0455 0456 /** 0457 * This method allows to enter the next scheduled transaction of 0458 * the given schedule @a s. In case @a extendedKeys is @a true, 0459 * the given schedule can also be skipped or ignored. 0460 * If @a autoEnter is @a true and the schedule does not contain 0461 * an estimated value, the schedule is entered as is without further 0462 * interaction with the user. In all other cases, the user will 0463 * be presented a dialog and allowed to adjust the values for this 0464 * instance of the schedule. 0465 * 0466 * The transaction will be created and entered into the ledger 0467 * and the schedule updated. 0468 */ 0469 eDialogs::ScheduleResultCode enterSchedule(MyMoneySchedule& schedule, bool autoEnter = false, bool extendedKeys = false) 0470 { 0471 Q_Q(KScheduledView); 0472 auto rc = eDialogs::ScheduleResultCode::Cancel; 0473 if (!schedule.id().isEmpty()) { 0474 try { 0475 schedule = MyMoneyFile::instance()->schedule(schedule.id()); 0476 } catch (const MyMoneyException &e) { 0477 KMessageBox::detailedSorry(q, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); 0478 return rc; 0479 } 0480 0481 QWidget* parent = QApplication::activeWindow(); 0482 QPointer<KEnterScheduleDlg> dlg = new KEnterScheduleDlg(parent, schedule); 0483 0484 try { 0485 QDate origDueDate = schedule.nextDueDate(); 0486 0487 dlg->showExtendedKeys(extendedKeys); 0488 0489 QPointer<TransactionEditor> transactionEditor = dlg->startEdit(); 0490 if (transactionEditor) { 0491 KMyMoneyMVCCombo::setSubstringSearchForChildren(dlg, !KMyMoneySettings::stringMatchFromStart()); 0492 MyMoneyTransaction torig, taccepted; 0493 transactionEditor->createTransaction(torig, dlg->transaction(), 0494 schedule.transaction().splits().isEmpty() ? MyMoneySplit() : schedule.transaction().splits().front(), true); 0495 // force actions to be available no matter what (will be updated according to the state during 0496 // slotTransactionsEnter or slotTransactionsCancel) 0497 0498 KConfirmManualEnterDlg::Action action = KConfirmManualEnterDlg::ModifyOnce; 0499 if (!autoEnter || !schedule.isFixed()) { 0500 for (; dlg != 0;) { 0501 rc = eDialogs::ScheduleResultCode::Cancel; 0502 if (dlg->exec() == QDialog::Accepted && dlg != 0) { 0503 pActions[eMenu::Action::CancelTransaction]->setEnabled(true); 0504 pActions[eMenu::Action::EnterTransaction]->setEnabled(true); 0505 rc = dlg->resultCode(); 0506 if (rc == eDialogs::ScheduleResultCode::Enter) { 0507 transactionEditor->createTransaction(taccepted, torig, torig.splits().isEmpty() ? MyMoneySplit() : torig.splits().front(), true); 0508 // make sure to suppress comparison of some data: postDate 0509 torig.setPostDate(taccepted.postDate()); 0510 if (torig != taccepted) { 0511 QPointer<KConfirmManualEnterDlg> cdlg = 0512 new KConfirmManualEnterDlg(schedule, q); 0513 cdlg->loadTransactions(torig, taccepted); 0514 if (cdlg->exec() == QDialog::Accepted) { 0515 action = cdlg->action(); 0516 delete cdlg; 0517 break; 0518 } 0519 delete cdlg; 0520 // the user has chosen 'cancel' during confirmation, 0521 // we go back to the editor 0522 continue; 0523 } 0524 } else if (rc == eDialogs::ScheduleResultCode::Skip) { 0525 slotTransactionsCancel(transactionEditor, schedule); 0526 skipSchedule(schedule); 0527 } else { 0528 slotTransactionsCancel(transactionEditor, schedule); 0529 } 0530 } else { 0531 pActions[eMenu::Action::CancelTransaction]->setEnabled(true); 0532 pActions[eMenu::Action::EnterTransaction]->setEnabled(true); 0533 if (autoEnter) { 0534 if (KMessageBox::warningYesNo(q, i18n("Are you sure you wish to stop this scheduled transaction from being entered into the register?\n\nKMyMoney will prompt you again next time it starts unless you manually enter it later.")) == KMessageBox::No) { 0535 // the user has chosen 'No' for the above question, 0536 // we go back to the editor 0537 continue; 0538 } 0539 } 0540 slotTransactionsCancel(transactionEditor, schedule); 0541 } 0542 break; 0543 } 0544 } 0545 0546 // if we still have the editor around here, the user did not cancel 0547 if ((transactionEditor != 0) && (dlg != 0)) { 0548 MyMoneyFileTransaction ft; 0549 try { 0550 MyMoneyTransaction t; 0551 // add the new transaction 0552 switch (action) { 0553 case KConfirmManualEnterDlg::UseOriginal: 0554 // setup widgets with original transaction data 0555 transactionEditor->setTransaction(dlg->transaction(), dlg->transaction().splits().isEmpty() ? MyMoneySplit() : dlg->transaction().splits().front()); 0556 // and create a transaction based on that data 0557 taccepted = MyMoneyTransaction(); 0558 transactionEditor->createTransaction(taccepted, dlg->transaction(), 0559 dlg->transaction().splits().isEmpty() ? MyMoneySplit() : dlg->transaction().splits().front(), true); 0560 break; 0561 0562 case KConfirmManualEnterDlg::ModifyAlways: 0563 torig = taccepted; 0564 torig.setPostDate(origDueDate); 0565 schedule.setTransaction(torig); 0566 break; 0567 0568 case KConfirmManualEnterDlg::ModifyOnce: 0569 break; 0570 } 0571 0572 QString newId; 0573 q->connect(transactionEditor, SIGNAL(balanceWarning(QWidget*,MyMoneyAccount,QString)), m_balanceWarning.data(), SLOT(slotShowMessage(QWidget*,MyMoneyAccount,QString))); 0574 if (transactionEditor->enterTransactions(newId, false)) { 0575 if (!newId.isEmpty()) { 0576 t = MyMoneyFile::instance()->transaction(newId); 0577 schedule.setLastPayment(t.postDate()); 0578 } 0579 // in case the next due date is invalid, the schedule is finished 0580 // we mark it as such by setting the next due date to one day past the end 0581 QDate nextDueDate = schedule.nextPayment(origDueDate); 0582 if (!nextDueDate.isValid()) { 0583 schedule.setNextDueDate(schedule.endDate().addDays(1)); 0584 } else { 0585 schedule.setNextDueDate(nextDueDate); 0586 } 0587 MyMoneyFile::instance()->modifySchedule(schedule); 0588 rc = eDialogs::ScheduleResultCode::Enter; 0589 0590 // delete the editor before we emit the dataChanged() signal from the 0591 // engine. Calling this twice in a row does not hurt. 0592 delete transactionEditor; 0593 ft.commit(); 0594 } 0595 } catch (const MyMoneyException &e) { 0596 KMessageBox::detailedSorry(q, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); 0597 } 0598 delete transactionEditor; 0599 } 0600 } 0601 } catch (const MyMoneyException &e) { 0602 KMessageBox::detailedSorry(q, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); 0603 } 0604 delete dlg; 0605 } 0606 return rc; 0607 } 0608 0609 void slotTransactionsCancel(TransactionEditor* editor, const MyMoneySchedule& schedule) 0610 { 0611 Q_Q(KScheduledView); 0612 // since we jump here via code, we have to make sure to react only 0613 // if the action is enabled 0614 if (pActions[eMenu::Action::CancelTransaction]->isEnabled()) { 0615 // make sure, we block the enter function 0616 pActions[eMenu::Action::EnterTransaction]->setEnabled(false); 0617 // qDebug("KMyMoneyApp::slotTransactionsCancel"); 0618 delete editor; 0619 emit q->selectByObject(schedule, eView::Intent::None); 0620 } 0621 } 0622 0623 /** 0624 * This method allows to skip the next scheduled transaction of 0625 * the given schedule @a s. 0626 * 0627 */ 0628 void skipSchedule(MyMoneySchedule& schedule) 0629 { 0630 const auto parentWidget = QApplication::activeWindow(); 0631 0632 if (!schedule.id().isEmpty()) { 0633 try { 0634 schedule = MyMoneyFile::instance()->schedule(schedule.id()); 0635 if (!schedule.isFinished()) { 0636 if (schedule.occurrence() != eMyMoney::Schedule::Occurrence::Once) { 0637 QDate next = schedule.nextDueDate(); 0638 if (!schedule.isFinished() && (KMessageBox::questionYesNo(parentWidget, i18n("<qt>Do you really want to skip the <b>%1</b> transaction scheduled for <b>%2</b>?</qt>", schedule.name(), QLocale().toString(next, QLocale::ShortFormat)))) == KMessageBox::Yes) { 0639 MyMoneyFileTransaction ft; 0640 schedule.setLastPayment(next); 0641 schedule.setNextDueDate(schedule.nextPayment(next)); 0642 MyMoneyFile::instance()->modifySchedule(schedule); 0643 ft.commit(); 0644 } 0645 } 0646 } 0647 } catch (const MyMoneyException &e) { 0648 KMessageBox::detailedSorry(parentWidget, i18n("<qt>Unable to skip scheduled transaction <b>%1</b>.</qt>", schedule.name()), e.what()); 0649 } 0650 } 0651 } 0652 0653 KScheduledView *q_ptr; 0654 Ui::KScheduledView *ui; 0655 /// The selected schedule id in the list view. 0656 QMenu *m_kaccPopup; 0657 QStringList m_filterAccounts; 0658 bool m_openBills; 0659 bool m_openDeposits; 0660 bool m_openTransfers; 0661 bool m_openLoans; 0662 0663 /** 0664 * This member holds the load state of page 0665 */ 0666 bool m_needLoad; 0667 0668 /** 0669 * Search widget for the list 0670 */ 0671 KTreeWidgetSearchLineWidget* m_searchWidget; 0672 MyMoneySchedule m_currentSchedule; 0673 0674 QScopedPointer<KBalanceWarning> m_balanceWarning; 0675 }; 0676 0677 #endif