File indexing completed on 2024-05-12 16:43:49
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: 2000-2002 Andreas Nicolai <Andreas.Nicolai@gmx.net> 0009 SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0010 SPDX-License-Identifier: GPL-2.0-or-later 0011 */ 0012 0013 #include "kpayeesview_p.h" 0014 0015 // ---------------------------------------------------------------------------- 0016 // QT Includes 0017 0018 #include <QMap> 0019 #include <QList> 0020 #include <QTimer> 0021 #include <QMenu> 0022 #include <QDesktopServices> 0023 #include <QIcon> 0024 0025 // ---------------------------------------------------------------------------- 0026 // KDE Includes 0027 0028 #include <KLocalizedString> 0029 #include <KMessageBox> 0030 #include <KGuiItem> 0031 #include <KHelpClient> 0032 #include <KSharedConfig> 0033 #include <KListWidgetSearchLine> 0034 0035 // ---------------------------------------------------------------------------- 0036 // Project Includes 0037 0038 #include <config-kmymoney.h> 0039 #include "ui_kpayeesview.h" 0040 #include "kmymoneyviewbase_p.h" 0041 #include "kpayeeidentifierview.h" 0042 #include "mymoneypayee.h" 0043 #include "mymoneyexception.h" 0044 #include "mymoneyfile.h" 0045 #include "mymoneyaccount.h" 0046 #include "mymoneymoney.h" 0047 #include "mymoneytransactionfilter.h" 0048 #include "kmymoneysettings.h" 0049 #include "models.h" 0050 #include "accountsmodel.h" 0051 #include "mymoneysecurity.h" 0052 #include "mymoneycontact.h" 0053 #include "mymoneyprice.h" 0054 #include "mymoneysplit.h" 0055 #include "mymoneytransaction.h" 0056 #include "icons/icons.h" 0057 #include "transaction.h" 0058 #include "widgetenums.h" 0059 #include "mymoneyenums.h" 0060 #include "modelenums.h" 0061 #include "menuenums.h" 0062 0063 using namespace Icons; 0064 0065 // *** KPayeesView Implementation *** 0066 0067 KPayeesView::KPayeesView(QWidget *parent) : 0068 KMyMoneyViewBase(*new KPayeesViewPrivate(this), parent) 0069 { 0070 connect(pActions[eMenu::Action::NewPayee], &QAction::triggered, this, &KPayeesView::slotNewPayee); 0071 connect(pActions[eMenu::Action::RenamePayee], &QAction::triggered, this, &KPayeesView::slotRenamePayee); 0072 connect(pActions[eMenu::Action::DeletePayee], &QAction::triggered, this, &KPayeesView::slotDeletePayee); 0073 connect(pActions[eMenu::Action::MergePayee], &QAction::triggered, this, &KPayeesView::slotMergePayee); 0074 } 0075 0076 KPayeesView::~KPayeesView() 0077 { 0078 } 0079 0080 void KPayeesView::slotChooseDefaultAccount() 0081 { 0082 Q_D(KPayeesView); 0083 MyMoneyFile* file = MyMoneyFile::instance(); 0084 QMap<QString, int> account_count; 0085 0086 KMyMoneyRegister::RegisterItem* item = d->ui->m_register->firstItem(); 0087 while (item) { 0088 //only walk through selectable items. eg. transactions and not group markers 0089 if (item->isSelectable()) { 0090 auto t = dynamic_cast<KMyMoneyRegister::Transaction*>(item); 0091 if (!t) 0092 return; 0093 MyMoneySplit s = t->transaction().splitByPayee(d->m_payee.id()); 0094 const MyMoneyAccount& acc = file->account(s.accountId()); 0095 0096 if (s.action() != MyMoneySplit::actionName(eMyMoney::Split::Action::Amortization) 0097 && acc.accountType() != eMyMoney::Account::Type::AssetLoan 0098 && !file->isTransfer(t->transaction()) 0099 && t->transaction().splitCount() == 2) { 0100 MyMoneySplit s0 = t->transaction().splitByAccount(s.accountId(), false); 0101 if (account_count.contains(s0.accountId())) { 0102 account_count[s0.accountId()]++; 0103 } else { 0104 account_count[s0.accountId()] = 1; 0105 } 0106 } 0107 } 0108 item = item->nextItem(); 0109 } 0110 0111 QMap<QString, int>::Iterator most_frequent, iter; 0112 most_frequent = account_count.begin(); 0113 for (iter = account_count.begin(); iter != account_count.end(); ++iter) { 0114 if (iter.value() > most_frequent.value()) { 0115 most_frequent = iter; 0116 } 0117 } 0118 0119 if (most_frequent != account_count.end()) { 0120 d->ui->checkEnableDefaultCategory->setChecked(true); 0121 d->ui->comboDefaultCategory->setSelected(most_frequent.key()); 0122 d->setDirty(true); 0123 } 0124 } 0125 0126 void KPayeesView::slotClosePayeeIdentifierSource() 0127 { 0128 Q_D(KPayeesView); 0129 if (!d->m_needLoad) 0130 d->ui->payeeIdentifiers->closeSource(); 0131 } 0132 0133 void KPayeesView::slotSelectByVariant(const QVariantList& variant, eView::Intent intent) 0134 { 0135 switch (intent) { 0136 case eView::Intent::ShowPayee: 0137 if (variant.count() == 3) 0138 slotSelectPayeeAndTransaction(variant.at(0).toString(), variant.at(1).toString(), variant.at(2).toString()); 0139 break; 0140 default: 0141 break; 0142 } 0143 } 0144 0145 0146 void KPayeesView::slotStartRename(QListWidgetItem* item) 0147 { 0148 Q_D(KPayeesView); 0149 d->m_allowEditing = true; 0150 d->ui->m_payeesList->editItem(item); 0151 } 0152 0153 // This variant is only called when a single payee is selected and renamed. 0154 void KPayeesView::slotRenameSinglePayee(QListWidgetItem* p) 0155 { 0156 Q_D(KPayeesView); 0157 //if there is no current item selected, exit 0158 if (d->m_allowEditing == false || !d->ui->m_payeesList->currentItem() || p != d->ui->m_payeesList->currentItem()) 0159 return; 0160 0161 //qDebug() << "[KPayeesView::slotRenamePayee]"; 0162 // create a copy of the new name without appended whitespaces 0163 QString new_name = p->text(); 0164 if (d->m_payee.name() != new_name) { 0165 MyMoneyFileTransaction ft; 0166 try { 0167 // check if we already have a payee with the new name 0168 try { 0169 // this function call will throw an exception, if the payee 0170 // hasn't been found. 0171 MyMoneyFile::instance()->payeeByName(new_name); 0172 // the name already exists, ask the user whether he's sure to keep the name 0173 if (KMessageBox::questionYesNo(this, 0174 i18n("A payee with the name '%1' already exists. It is not advisable to have " 0175 "multiple payees with the same identification name. Are you sure you would like " 0176 "to rename the payee?", new_name)) != KMessageBox::Yes) { 0177 p->setText(d->m_payee.name()); 0178 return; 0179 } 0180 } catch (const MyMoneyException &) { 0181 // all ok, the name is unique 0182 } 0183 0184 d->m_payee.setName(new_name); 0185 d->m_newName = new_name; 0186 MyMoneyFile::instance()->modifyPayee(d->m_payee); 0187 0188 // the above call to modifyPayee will reload the view so 0189 // all references and pointers to the view have to be 0190 // re-established. 0191 0192 // make sure, that the record is visible even if it moved 0193 // out of sight due to the rename operation 0194 d->ensurePayeeVisible(d->m_payee.id()); 0195 0196 ft.commit(); 0197 0198 } catch (const MyMoneyException &e) { 0199 KMessageBox::detailedSorry(this, i18n("Unable to modify payee"), QString::fromLatin1(e.what())); 0200 } 0201 } else { 0202 p->setText(new_name); 0203 } 0204 } 0205 0206 void KPayeesView::slotSelectPayee(QListWidgetItem* cur, QListWidgetItem* prev) 0207 { 0208 Q_D(KPayeesView); 0209 Q_UNUSED(cur); 0210 Q_UNUSED(prev); 0211 0212 d->m_allowEditing = false; 0213 } 0214 0215 void KPayeesView::slotSelectPayee() 0216 { 0217 Q_D(KPayeesView); 0218 // check if the content of a currently selected payee was modified 0219 // and ask to store the data 0220 if (d->isDirty()) { 0221 if (KMessageBox::questionYesNo(this, 0222 i18n("<qt>Do you want to save the changes for <b>%1</b>?</qt>", d->m_newName), 0223 i18n("Save changes")) == KMessageBox::Yes) { 0224 d->m_inSelection = true; 0225 slotUpdatePayee(); 0226 d->m_inSelection = false; 0227 } 0228 } 0229 0230 // make sure we always clear the selected list when listing again 0231 d->m_selectedPayeesList.clear(); 0232 0233 // loop over all payees and count the number of payees, also 0234 // obtain last selected payee 0235 d->selectedPayees(d->m_selectedPayeesList); 0236 updatePayeeActions(d->m_selectedPayeesList); 0237 0238 emit selectObjects(d->m_selectedPayeesList); 0239 0240 if (d->m_selectedPayeesList.isEmpty()) { 0241 d->ui->m_tabWidget->setEnabled(false); // disable tab widget 0242 d->ui->m_balanceLabel->hide(); 0243 d->ui->m_deleteButton->setEnabled(false); //disable delete, rename and merge buttons 0244 d->ui->m_renameButton->setEnabled(false); 0245 d->ui->m_mergeButton->setEnabled(false); 0246 d->clearItemData(); 0247 d->m_payee = MyMoneyPayee(); 0248 d->ui->m_syncAddressbook->setEnabled(false); 0249 return; // make sure we don't access an undefined payee 0250 } 0251 0252 d->ui->m_deleteButton->setEnabled(true); //re-enable delete button 0253 0254 d->ui->m_syncAddressbook->setEnabled(true); 0255 0256 // if we have multiple payees selected, clear and disable the payee information 0257 if (d->m_selectedPayeesList.count() > 1) { 0258 d->ui->m_tabWidget->setEnabled(false); // disable tab widget 0259 d->ui->m_renameButton->setEnabled(false); // disable also the rename button 0260 d->ui->m_mergeButton->setEnabled(true); 0261 d->ui->m_balanceLabel->hide(); 0262 d->clearItemData(); 0263 } else { 0264 d->ui->m_mergeButton->setEnabled(false); 0265 d->ui->m_renameButton->setEnabled(true); 0266 } 0267 0268 // otherwise we have just one selected, enable payee information widget 0269 d->ui->m_tabWidget->setEnabled(true); 0270 d->ui->m_balanceLabel->show(); 0271 0272 // as of now we are updating only the last selected payee, and until 0273 // selection mode of the QListView has been changed to Extended, this 0274 // will also be the only selection and behave exactly as before - Andreas 0275 try { 0276 d->m_payee = d->m_selectedPayeesList[0]; 0277 0278 d->m_newName = d->m_payee.name(); 0279 0280 d->ui->addressEdit->setEnabled(true); 0281 d->ui->addressEdit->setText(d->m_payee.address()); 0282 d->ui->payeecityEdit->setEnabled(true); 0283 d->ui->payeecityEdit->setText(d->m_payee.city()); 0284 d->ui->payeestateEdit->setEnabled(true); 0285 d->ui->payeestateEdit->setText(d->m_payee.state()); 0286 d->ui->postcodeEdit->setEnabled(true); 0287 d->ui->postcodeEdit->setText(d->m_payee.postcode()); 0288 d->ui->telephoneEdit->setEnabled(true); 0289 d->ui->telephoneEdit->setText(d->m_payee.telephone()); 0290 d->ui->emailEdit->setEnabled(true); 0291 d->ui->emailEdit->setText(d->m_payee.email()); 0292 d->ui->notesEdit->setText(d->m_payee.notes()); 0293 0294 QStringList keys; 0295 bool ignorecase = false; 0296 auto type = d->m_payee.matchData(ignorecase, keys); 0297 0298 d->ui->matchTypeCombo->setCurrentIndex(d->ui->matchTypeCombo->findData(static_cast<int>(type))); 0299 d->ui->matchKeyEditList->clear(); 0300 d->ui->matchKeyEditList->insertStringList(keys); 0301 d->ui->checkMatchIgnoreCase->setChecked(ignorecase); 0302 0303 d->ui->checkEnableDefaultCategory->setChecked(!d->m_payee.defaultAccountId().isEmpty()); 0304 d->ui->comboDefaultCategory->setCurrentIndex(-1); 0305 d->ui->comboDefaultCategory->setSelected(d->m_payee.defaultAccountId()); 0306 0307 d->ui->payeeIdentifiers->setSource(d->m_payee); 0308 0309 slotPayeeDataChanged(); 0310 0311 d->showTransactions(); 0312 0313 } catch (const MyMoneyException &e) { 0314 qDebug("exception during display of payee: %s", e.what()); 0315 d->ui->m_register->clear(); 0316 d->m_selectedPayeesList.clear(); 0317 d->m_payee = MyMoneyPayee(); 0318 } 0319 d->m_allowEditing = true; 0320 } 0321 0322 void KPayeesView::slotKeyListChanged() 0323 { 0324 Q_D(KPayeesView); 0325 bool rc = false; 0326 bool ignorecase = false; 0327 QStringList keys; 0328 0329 d->m_payee.matchData(ignorecase, keys); 0330 if (static_cast<eMyMoney::Payee::MatchType>(d->ui->matchTypeCombo->currentData().toUInt()) == eMyMoney::Payee::MatchType::Key) { 0331 rc |= (keys != d->ui->matchKeyEditList->items()); 0332 } 0333 d->setDirty(rc); 0334 } 0335 0336 void KPayeesView::slotPayeeDataChanged() 0337 { 0338 Q_D(KPayeesView); 0339 bool rc = false; 0340 0341 if (d->ui->m_tabWidget->isEnabled()) { 0342 rc |= ((d->m_payee.email().isEmpty() != d->ui->emailEdit->text().isEmpty()) 0343 || (!d->ui->emailEdit->text().isEmpty() && d->m_payee.email() != d->ui->emailEdit->text())); 0344 rc |= ((d->m_payee.address().isEmpty() != d->ui->addressEdit->toPlainText().isEmpty()) 0345 || (!d->ui->addressEdit->toPlainText().isEmpty() && d->m_payee.address() != d->ui->addressEdit->toPlainText())); 0346 rc |= ((d->m_payee.city().isEmpty() != d->ui->payeecityEdit->text().isEmpty()) 0347 || (!d->ui->payeecityEdit->text().isEmpty() && d->m_payee.city() != d->ui->payeecityEdit->text())); 0348 rc |= ((d->m_payee.state().isEmpty() != d->ui->payeestateEdit->text().isEmpty()) 0349 || (!d->ui->payeestateEdit->text().isEmpty() && d->m_payee.state() != d->ui->payeestateEdit->text())); 0350 rc |= ((d->m_payee.postcode().isEmpty() != d->ui->postcodeEdit->text().isEmpty()) 0351 || (!d->ui->postcodeEdit->text().isEmpty() && d->m_payee.postcode() != d->ui->postcodeEdit->text())); 0352 rc |= ((d->m_payee.telephone().isEmpty() != d->ui->telephoneEdit->text().isEmpty()) 0353 || (!d->ui->telephoneEdit->text().isEmpty() && d->m_payee.telephone() != d->ui->telephoneEdit->text())); 0354 rc |= ((d->m_payee.name().isEmpty() != d->m_newName.isEmpty()) 0355 || (!d->m_newName.isEmpty() && d->m_payee.name() != d->m_newName)); 0356 rc |= ((d->m_payee.notes().isEmpty() != d->ui->notesEdit->toPlainText().isEmpty()) 0357 || (!d->ui->notesEdit->toPlainText().isEmpty() && d->m_payee.notes() != d->ui->notesEdit->toPlainText())); 0358 0359 bool ignorecase = false; 0360 QStringList keys; 0361 0362 const auto selectedMatchType = static_cast<eMyMoney::Payee::MatchType>(d->ui->matchTypeCombo->currentData().toUInt()); 0363 const auto storedMatchType = d->m_payee.matchData(ignorecase, keys); 0364 rc |= (storedMatchType != selectedMatchType); 0365 0366 d->ui->checkMatchIgnoreCase->setEnabled(false); 0367 d->ui->matchKeyEditList->setEnabled(false); 0368 0369 if (selectedMatchType != eMyMoney::Payee::MatchType::Disabled) { 0370 d->ui->checkMatchIgnoreCase->setEnabled(true); 0371 // if we turn matching on, we default to 'ignore case' 0372 // TODO maybe make the default a user option 0373 if (storedMatchType == eMyMoney::Payee::MatchType::Disabled && (selectedMatchType != eMyMoney::Payee::MatchType::Disabled)) 0374 d->ui->checkMatchIgnoreCase->setChecked(true); 0375 rc |= (ignorecase != d->ui->checkMatchIgnoreCase->isChecked()); 0376 if (selectedMatchType == eMyMoney::Payee::MatchType::Key) { 0377 d->ui->matchKeyEditList->setEnabled(true); 0378 rc |= (keys != d->ui->matchKeyEditList->items()); 0379 } 0380 } 0381 0382 rc |= (d->ui->checkEnableDefaultCategory->isChecked() != !d->m_payee.defaultAccountId().isEmpty()); 0383 if (d->ui->checkEnableDefaultCategory->isChecked()) { 0384 d->ui->comboDefaultCategory->setEnabled(true); 0385 d->ui->labelDefaultCategory->setEnabled(true); 0386 // this is only going to understand the first in the list of selected accounts 0387 if (d->ui->comboDefaultCategory->getSelected().isEmpty()) { 0388 rc |= !d->m_payee.defaultAccountId().isEmpty(); 0389 } else { 0390 QString temp = d->ui->comboDefaultCategory->getSelected(); 0391 rc |= (temp.isEmpty() != d->m_payee.defaultAccountId().isEmpty()) 0392 || (!d->m_payee.defaultAccountId().isEmpty() && temp != d->m_payee.defaultAccountId()); 0393 } 0394 } else { 0395 d->ui->comboDefaultCategory->setEnabled(false); 0396 d->ui->labelDefaultCategory->setEnabled(false); 0397 } 0398 0399 rc |= (d->m_payee.payeeIdentifiers() != d->ui->payeeIdentifiers->identifiers()); 0400 } 0401 d->setDirty(rc); 0402 } 0403 0404 void KPayeesView::slotUpdatePayee() 0405 { 0406 Q_D(KPayeesView); 0407 if (d->isDirty()) { 0408 MyMoneyFileTransaction ft; 0409 d->setDirty(false); 0410 try { 0411 d->m_payee.setName(d->m_newName); 0412 d->m_payee.setAddress(d->ui->addressEdit->toPlainText()); 0413 d->m_payee.setCity(d->ui->payeecityEdit->text()); 0414 d->m_payee.setState(d->ui->payeestateEdit->text()); 0415 d->m_payee.setPostcode(d->ui->postcodeEdit->text()); 0416 d->m_payee.setTelephone(d->ui->telephoneEdit->text()); 0417 d->m_payee.setEmail(d->ui->emailEdit->text()); 0418 d->m_payee.setNotes(d->ui->notesEdit->toPlainText()); 0419 d->m_payee.setMatchData(static_cast<eMyMoney::Payee::MatchType>(d->ui->matchTypeCombo->currentData().toUInt()), d->ui->checkMatchIgnoreCase->isChecked(), d->ui->matchKeyEditList->items()); 0420 d->m_payee.setDefaultAccountId(); 0421 d->m_payee.resetPayeeIdentifiers(d->ui->payeeIdentifiers->identifiers()); 0422 0423 if (d->ui->checkEnableDefaultCategory->isChecked()) { 0424 QString temp; 0425 if (!d->ui->comboDefaultCategory->getSelected().isEmpty()) { 0426 temp = d->ui->comboDefaultCategory->getSelected(); 0427 d->m_payee.setDefaultAccountId(temp); 0428 } 0429 } 0430 0431 MyMoneyFile::instance()->modifyPayee(d->m_payee); 0432 ft.commit(); 0433 0434 } catch (const MyMoneyException &e) { 0435 KMessageBox::detailedSorry(this, i18n("Unable to modify payee"), QString::fromLatin1(e.what())); 0436 } 0437 } 0438 } 0439 0440 void KPayeesView::slotSyncAddressBook() 0441 { 0442 Q_D(KPayeesView); 0443 if (d->m_payeeRows.isEmpty()) { // empty list means no syncing is pending... 0444 foreach (auto item, d->ui->m_payeesList->selectedItems()) { 0445 d->m_payeeRows.append(d->ui->m_payeesList->row(item)); // ...so initialize one 0446 } 0447 d->ui->m_payeesList->clearSelection(); // otherwise slotSelectPayee will be run after every payee update 0448 // d->ui->m_syncAddressbook->setEnabled(false); // disallow concurrent syncs 0449 } 0450 0451 if (d->m_payeeRows.count() <= d->m_payeeRow) { 0452 if (auto item = dynamic_cast<KPayeeListItem*>(d->ui->m_payeesList->currentItem())) { // update ui if something is selected 0453 d->m_payee = item->payee(); 0454 d->ui->addressEdit->setText(d->m_payee.address()); 0455 d->ui->payeecityEdit->setText(d->m_payee.city()); 0456 d->ui->payeestateEdit->setText(d->m_payee.state()); 0457 d->ui->postcodeEdit->setText(d->m_payee.postcode()); 0458 d->ui->telephoneEdit->setText(d->m_payee.telephone()); 0459 } 0460 d->m_payeeRows.clear(); // that means end of sync 0461 d->m_payeeRow = 0; 0462 return; 0463 } 0464 0465 if (auto item = dynamic_cast<KPayeeListItem*>(d->ui->m_payeesList->item(d->m_payeeRows.at(d->m_payeeRow)))) 0466 d->m_payee = item->payee(); 0467 ++d->m_payeeRow; 0468 0469 d->m_contact->fetchContact(d->m_payee.email()); // search for payee's data in addressbook and receive it in slotContactFetched 0470 } 0471 0472 void KPayeesView::slotContactFetched(const ContactData &identity) 0473 { 0474 Q_D(KPayeesView); 0475 if (!identity.email.isEmpty()) { // empty e-mail means no identity fetched 0476 QString txt; 0477 if (!identity.street.isEmpty()) 0478 txt.append(identity.street + '\n'); 0479 if (!identity.locality.isEmpty()) { 0480 txt.append(identity.locality); 0481 if (!identity.postalCode.isEmpty()) 0482 txt.append(' ' + identity.postalCode + '\n'); 0483 else 0484 txt.append('\n'); 0485 } 0486 if (!identity.country.isEmpty()) 0487 txt.append(identity.country + '\n'); 0488 0489 if (!txt.isEmpty() && d->m_payee.address().compare(txt) != 0) 0490 d->m_payee.setAddress(txt); 0491 0492 if (!identity.city.isEmpty() && d->m_payee.city().compare(identity.city) != 0) 0493 d->m_payee.setCity(identity.city); 0494 0495 if (!identity.state.isEmpty() && d->m_payee.state().compare(identity.state) != 0) 0496 d->m_payee.setState(identity.state); 0497 0498 if (!identity.postalCode.isEmpty() && d->m_payee.postcode().compare(identity.postalCode) != 0) 0499 d->m_payee.setPostcode(identity.postalCode); 0500 0501 if (!identity.phoneNumber.isEmpty() && d->m_payee.telephone().compare(identity.phoneNumber) != 0) 0502 d->m_payee.setTelephone(identity.phoneNumber); 0503 0504 MyMoneyFileTransaction ft; 0505 try { 0506 MyMoneyFile::instance()->modifyPayee(d->m_payee); 0507 ft.commit(); 0508 } catch (const MyMoneyException &e) { 0509 KMessageBox::detailedSorry(this, i18n("Unable to modify payee"), QString::fromLatin1(e.what())); 0510 } 0511 } 0512 0513 slotSyncAddressBook(); // process next payee 0514 } 0515 0516 void KPayeesView::slotSendMail() 0517 { 0518 Q_D(KPayeesView); 0519 QRegularExpression re(".+@.+"); 0520 if (re.match(d->m_payee.email()).hasMatch()) 0521 QDesktopServices::openUrl(QUrl(QStringLiteral("mailto:?to=") + d->m_payee.email(), QUrl::TolerantMode)); 0522 } 0523 0524 void KPayeesView::executeCustomAction(eView::Action action) 0525 { 0526 Q_D(KPayeesView); 0527 switch(action) { 0528 case eView::Action::Refresh: 0529 refresh(); 0530 break; 0531 0532 case eView::Action::SetDefaultFocus: 0533 QTimer::singleShot(0, d->m_searchWidget, SLOT(setFocus())); 0534 break; 0535 0536 case eView::Action::ClosePayeeIdentifierSource: 0537 slotClosePayeeIdentifierSource(); 0538 break; 0539 0540 default: 0541 break; 0542 } 0543 } 0544 0545 void KPayeesView::refresh() 0546 { 0547 Q_D(KPayeesView); 0548 if (isVisible()) { 0549 if (d->m_inSelection) { 0550 QTimer::singleShot(0, this, SLOT(refresh())); 0551 } else { 0552 d->loadPayees(); 0553 d->m_needsRefresh = false; 0554 } 0555 } else { 0556 d->m_needsRefresh = true; 0557 } 0558 } 0559 0560 void KPayeesView::showEvent(QShowEvent* event) 0561 { 0562 if (MyMoneyFile::instance()->storageAttached()) { 0563 Q_D(KPayeesView); 0564 if (d->m_needLoad) 0565 d->init(); 0566 0567 emit customActionRequested(View::Payees, eView::Action::AboutToShow); 0568 0569 if (d->m_needsRefresh) 0570 refresh(); 0571 0572 QList<MyMoneyPayee> list; 0573 d->selectedPayees(list); 0574 emit selectObjects(list); 0575 } 0576 0577 // don't forget base class implementation 0578 QWidget::showEvent(event); 0579 } 0580 0581 void KPayeesView::updatePayeeActions(const QList<MyMoneyPayee> &payees) 0582 { 0583 pActions[eMenu::Action::NewPayee]->setEnabled(true); 0584 const auto payeesCount = payees.count(); 0585 auto b = payeesCount == 1 ? true : false; 0586 pActions[eMenu::Action::RenamePayee]->setEnabled(b); 0587 b = payeesCount > 1 ? true : false; 0588 pActions[eMenu::Action::MergePayee]->setEnabled(b); 0589 b = payeesCount == 0 ? false : true; 0590 pActions[eMenu::Action::DeletePayee]->setEnabled(b); 0591 } 0592 0593 void KPayeesView::slotSelectTransaction() 0594 { 0595 Q_D(KPayeesView); 0596 auto list = d->ui->m_register->selectedItems(); 0597 if (!list.isEmpty()) { 0598 const auto t = dynamic_cast<KMyMoneyRegister::Transaction*>(list[0]); 0599 if (t) 0600 emit selectByVariant(QVariantList {QVariant(t->split().accountId()), QVariant(t->transaction().id()) }, eView::Intent::ShowTransaction); 0601 } 0602 } 0603 0604 void KPayeesView::slotSelectPayeeAndTransaction(const QString& payeeId, const QString& accountId, const QString& transactionId) 0605 { 0606 Q_D(KPayeesView); 0607 if (!isVisible()) 0608 return; 0609 0610 try { 0611 // clear filter 0612 d->m_searchWidget->clear(); 0613 d->m_searchWidget->updateSearch(); 0614 0615 // deselect all other selected items 0616 QList<QListWidgetItem *> selectedItems = d->ui->m_payeesList->selectedItems(); 0617 QList<QListWidgetItem *>::const_iterator payeesIt = selectedItems.constBegin(); 0618 while (payeesIt != selectedItems.constEnd()) { 0619 if (auto item = dynamic_cast<KPayeeListItem*>(*payeesIt)) 0620 item->setSelected(false); 0621 ++payeesIt; 0622 } 0623 0624 // find the payee in the list 0625 QListWidgetItem* it; 0626 for (int i = 0; i < d->ui->m_payeesList->count(); ++i) { 0627 it = d->ui->m_payeesList->item(i); 0628 auto item = dynamic_cast<KPayeeListItem *>(it); 0629 if (item && item->payee().id() == payeeId) { 0630 d->ui->m_payeesList->scrollToItem(it, QAbstractItemView::PositionAtCenter); 0631 0632 d->ui->m_payeesList->setCurrentItem(it); // active item and deselect all others 0633 d->ui->m_payeesList->setCurrentRow(i, QItemSelectionModel::ClearAndSelect); // and select it 0634 0635 //make sure the payee selection is updated and transactions are updated accordingly 0636 slotSelectPayee(); 0637 0638 KMyMoneyRegister::RegisterItem *registerItem = 0; 0639 for (i = 0; i < d->ui->m_register->rowCount(); ++i) { 0640 registerItem = d->ui->m_register->itemAtRow(i); 0641 if (auto t = dynamic_cast<KMyMoneyRegister::Transaction*>(registerItem)) { 0642 if (t->transaction().id() == transactionId && t->transaction().accountReferenced(accountId)) { 0643 d->ui->m_register->selectItem(registerItem); 0644 d->ui->m_register->ensureItemVisible(registerItem); 0645 break; 0646 } 0647 } 0648 } 0649 // quit out of outer for() loop 0650 break; 0651 } 0652 } 0653 } catch (const MyMoneyException &e) { 0654 qWarning("Unexpected exception in KPayeesView::slotSelectPayeeAndTransaction %s", e.what()); 0655 } 0656 } 0657 0658 void KPayeesView::slotShowPayeesMenu(const QPoint& /*p*/) 0659 { 0660 Q_D(KPayeesView); 0661 if (dynamic_cast<KPayeeListItem*>(d->ui->m_payeesList->currentItem())) { 0662 slotSelectPayee(); 0663 pMenus[eMenu::Menu::Payee]->exec(QCursor::pos()); 0664 } 0665 } 0666 0667 void KPayeesView::slotHelp() 0668 { 0669 KHelpClient::invokeHelp("details.payees"); 0670 } 0671 0672 void KPayeesView::slotChangeFilter(int index) 0673 { 0674 Q_D(KPayeesView); 0675 //update the filter type then reload the payees list 0676 d->m_payeeFilterType = index; 0677 d->loadPayees(); 0678 } 0679 0680 void KPayeesView::slotNewPayee() 0681 { 0682 QString id; 0683 KMyMoneyUtils::newPayee(i18n("New Payee"), id); 0684 slotSelectPayeeAndTransaction(id); 0685 } 0686 0687 void KPayeesView::slotRenamePayee() 0688 { 0689 Q_D(KPayeesView); 0690 if (d->ui->m_payeesList->currentItem() && d->ui->m_payeesList->selectedItems().count() == 1) { 0691 slotStartRename(d->ui->m_payeesList->currentItem()); 0692 } 0693 } 0694 0695 void KPayeesView::slotDeletePayee() 0696 { 0697 Q_D(KPayeesView); 0698 if (d->m_selectedPayeesList.isEmpty()) 0699 return; // shouldn't happen 0700 0701 // get confirmation from user 0702 QString prompt; 0703 if (d->m_selectedPayeesList.size() == 1) 0704 prompt = i18n("<p>Do you really want to remove the payee <b>%1</b>?</p>", d->m_selectedPayeesList.front().name()); 0705 else 0706 prompt = i18n("Do you really want to remove all selected payees?"); 0707 0708 if (KMessageBox::questionYesNo(this, prompt, i18n("Remove Payee")) == KMessageBox::No) 0709 return; 0710 0711 d->payeeReassign(KPayeeReassignDlg::TypeDelete); 0712 } 0713 0714 void KPayeesView::slotMergePayee() 0715 { 0716 Q_D(KPayeesView); 0717 if (d->m_selectedPayeesList.size() < 1) 0718 return; // shouldn't happen 0719 0720 if (KMessageBox::questionYesNo(this, i18n("<p>Do you really want to merge the selected payees?"), 0721 i18n("Merge Payees")) == KMessageBox::No) 0722 return; 0723 0724 if (d->payeeReassign(KPayeeReassignDlg::TypeMerge)) 0725 // clean selection since we just deleted the selected payees 0726 d->m_selectedPayeesList.clear(); 0727 }