File indexing completed on 2024-05-19 05:06:50
0001 /* 0002 SPDX-FileCopyrightText: 2004-2020 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-FileCopyrightText: 2009-2010 Alvaro Soliverez <asoliverez@gmail.com> 0004 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kcurrencyeditdlg.h" 0009 0010 #include <locale.h> 0011 0012 // ---------------------------------------------------------------------------- 0013 // QT Includes 0014 0015 #include <QPixmap> 0016 #include <QBitmap> 0017 #include <QList> 0018 #include <QTreeWidget> 0019 #include <QStyledItemDelegate> 0020 #include <QIcon> 0021 #include <QPushButton> 0022 #include <QBitArray> 0023 #include <QInputDialog> 0024 #include <QMenu> 0025 0026 // ---------------------------------------------------------------------------- 0027 // KDE Includes 0028 0029 #include <KTreeWidgetSearchLineWidget> 0030 #include <KMessageBox> 0031 #include <KLocalizedString> 0032 0033 // ---------------------------------------------------------------------------- 0034 // Project Includes 0035 0036 #include "ui_kcurrencyeditdlg.h" 0037 0038 #include "mymoneyexception.h" 0039 #include "mymoneysecurity.h" 0040 #include "mymoneyfile.h" 0041 #include "mymoneyprice.h" 0042 #include "kavailablecurrencydlg.h" 0043 #include "kcurrencyeditordlg.h" 0044 #include "kmymoneyutils.h" 0045 #include "icons/icons.h" 0046 #include "storageenums.h" 0047 #include "mymoneyenums.h" 0048 0049 using namespace Icons; 0050 0051 // duplicated eMenu namespace from menuenums.h for consistency 0052 // there shouldn't be any clash, because we don't need menuenums.h here 0053 namespace eMenu { 0054 enum class Action { 0055 // ************* 0056 // The currency menu 0057 // ************* 0058 NewCurrency, RenameCurrency, DeleteCurrency, 0059 SetBaseCurrency, 0060 }; 0061 inline qHashSeedType qHash(const Action key, qHashSeedType seed) 0062 { 0063 return ::qHash(static_cast<uint>(key), seed); 0064 } 0065 } 0066 0067 // this delegate is needed to disable editing the currency id (column 1) 0068 // since QTreeWidgetItem has only one set of flags for the whole row 0069 // the column editable property couldn't be set in an easier way 0070 class KCurrencyEditDelegate : public QStyledItemDelegate 0071 { 0072 public: 0073 explicit KCurrencyEditDelegate(QObject *parent = 0); 0074 0075 protected: 0076 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const final override; 0077 }; 0078 0079 KCurrencyEditDelegate::KCurrencyEditDelegate(QObject* parent): QStyledItemDelegate(parent) 0080 { 0081 } 0082 0083 QWidget *KCurrencyEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const 0084 { 0085 if (index.column() == 1) 0086 return 0; 0087 return QStyledItemDelegate::createEditor(parent, option, index); 0088 } 0089 0090 class KCurrencyEditDlgPrivate 0091 { 0092 Q_DISABLE_COPY(KCurrencyEditDlgPrivate) 0093 Q_DECLARE_PUBLIC(KCurrencyEditDlg) 0094 0095 public: 0096 explicit KCurrencyEditDlgPrivate(KCurrencyEditDlg *qq) : 0097 q_ptr(qq), 0098 ui(new Ui::KCurrencyEditDlg), 0099 m_availableCurrencyDlg(nullptr), 0100 m_currencyEditorDlg(nullptr), 0101 m_searchWidget(nullptr), 0102 m_inLoading(false) 0103 { 0104 } 0105 0106 ~KCurrencyEditDlgPrivate() 0107 { 0108 delete ui; 0109 } 0110 0111 enum removalModeE :int { RemoveSelected, RemoveUnused }; 0112 0113 void removeCurrency(const removalModeE& mode) 0114 { 0115 Q_Q(KCurrencyEditDlg); 0116 auto file = MyMoneyFile::instance(); 0117 MyMoneyFileTransaction ft; 0118 QBitArray skip((int)eStorage::Reference::Count); 0119 skip.fill(false); // check reference to all... 0120 skip.setBit((int)eStorage::Reference::Price); // ...except price 0121 0122 QTreeWidgetItemIterator it (ui->m_currencyList); // iterate over whole tree 0123 if (mode == RemoveUnused) { 0124 while (*it) { 0125 MyMoneySecurity currency = (*it)->data(0, Qt::UserRole).value<MyMoneySecurity>(); 0126 if (file->baseCurrency() != currency && !file->isReferenced(currency, skip)) 0127 KMyMoneyUtils::deleteSecurity(currency, q); 0128 ++it; 0129 } 0130 } else if (mode == RemoveSelected) { 0131 const QList<QTreeWidgetItem*> currencyRows = ui->m_currencyList->selectedItems(); 0132 for (const auto& currencyRow : currencyRows) { 0133 MyMoneySecurity currency = currencyRow->data(0, Qt::UserRole).value<MyMoneySecurity>(); 0134 if (file->baseCurrency() != currency && !file->isReferenced(currency, skip)) 0135 KMyMoneyUtils::deleteSecurity(currency, q); 0136 } 0137 } 0138 ft.commit(); 0139 ui->m_removeUnusedCurrencyButton->setDisabled(file->currencyList().count() <= 1); 0140 } 0141 0142 void setBaseCurrency(const MyMoneySecurity& cur) 0143 { 0144 Q_Q(KCurrencyEditDlg); 0145 if (!cur.id().isEmpty()) { 0146 if (cur.id() != MyMoneyFile::instance()->baseCurrency().id()) { 0147 MyMoneyFileTransaction ft; 0148 try { 0149 MyMoneyFile::instance()->setBaseCurrency(cur); 0150 ft.commit(); 0151 } catch (const MyMoneyException &e) { 0152 KMessageBox::error(q, i18n("Cannot set %1 as base currency: %2", cur.name(), QString::fromLatin1(e.what())), i18n("Set base currency")); 0153 } 0154 } 0155 } 0156 } 0157 0158 void updateCurrency(const QString ¤cyId, const QString& currencyName, const QString& currencyTradingSymbol) 0159 { 0160 Q_Q(KCurrencyEditDlg); 0161 const auto file = MyMoneyFile::instance(); 0162 try { 0163 if (currencyName != m_currentCurrency.name() || currencyTradingSymbol != m_currentCurrency.tradingSymbol()) { 0164 MyMoneySecurity currency = file->currency(currencyId); 0165 currency.setName(currencyName); 0166 currency.setTradingSymbol(currencyTradingSymbol); 0167 MyMoneyFileTransaction ft; 0168 try { 0169 file->modifyCurrency(currency); 0170 m_currentCurrency = currency; 0171 ft.commit(); 0172 } catch (const MyMoneyException &e) { 0173 KMessageBox::error(q, i18n("Cannot update currency. %1", QString::fromLatin1(e.what())), i18n("Update currency")); 0174 } 0175 } 0176 } catch (const MyMoneyException &e) { 0177 KMessageBox::error(q, i18n("Cannot update currency. %1", QString::fromLatin1(e.what())), i18n("Update currency")); 0178 } 0179 } 0180 0181 /** 0182 * Edit or create a currency 0183 * 0184 * @param currency reference to currency object 0185 * 0186 * @returns @c true in case the operation was successful @c false otherwise 0187 * @note @a currency will be updated with the modified values 0188 */ 0189 bool editCurrency(MyMoneySecurity& currency) 0190 { 0191 QScopedPointer<KCurrencyEditorDlg> currencyEditorDlg(new KCurrencyEditorDlg(currency, q_ptr)); 0192 bool rc = true; 0193 do { 0194 if (currencyEditorDlg->exec() != QDialog::Rejected) { 0195 auto file = MyMoneyFile::instance(); 0196 MyMoneyFileTransaction ft; 0197 try { 0198 if (currency.id().isEmpty()) { 0199 file->addCurrency(currencyEditorDlg->currency()); 0200 } else { 0201 file->modifyCurrency(currencyEditorDlg->currency()); 0202 } 0203 ft.commit(); 0204 // if the modification worked, then we copy the data 0205 // to inform caller 0206 currency = currencyEditorDlg->currency(); 0207 0208 } catch (const MyMoneyException &e) { 0209 if (currency.id().isEmpty()) { 0210 KMessageBox::error(q_ptr, i18n("Cannot create new currency. %1", QString::fromLatin1(e.what())), i18n("New currency")); 0211 } else { 0212 KMessageBox::error(q_ptr, i18n("Cannot modify currency. %1", QString::fromLatin1(e.what())), i18n("Edit currency")); 0213 } 0214 } 0215 } else { 0216 rc = false; // aborted by user 0217 } 0218 } while(false); 0219 0220 return rc; 0221 } 0222 0223 KCurrencyEditDlg *q_ptr; 0224 Ui::KCurrencyEditDlg *ui; 0225 0226 KAvailableCurrencyDlg *m_availableCurrencyDlg; 0227 KCurrencyEditorDlg *m_currencyEditorDlg; 0228 MyMoneySecurity m_currentCurrency; 0229 /** 0230 * Search widget for the list 0231 */ 0232 KTreeWidgetSearchLineWidget* m_searchWidget; 0233 bool m_inLoading; 0234 }; 0235 0236 KCurrencyEditDlg::KCurrencyEditDlg(QWidget *parent) : 0237 QDialog(parent), 0238 d_ptr(new KCurrencyEditDlgPrivate(this)) 0239 { 0240 Q_D(KCurrencyEditDlg); 0241 d->ui->setupUi(this); 0242 d->m_searchWidget = new KTreeWidgetSearchLineWidget(this, d->ui->m_currencyList); 0243 d->m_searchWidget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); 0244 d->m_searchWidget->setFocus(); 0245 d->ui->verticalLayout->insertWidget(0, d->m_searchWidget); 0246 d->ui->m_currencyList->setItemDelegate(new KCurrencyEditDelegate(d->ui->m_currencyList)); 0247 d->ui->m_closeButton->setIcon(Icons::get(Icon::DialogClose)); 0248 d->ui->m_newCurrencyButton->setIcon(Icons::get(Icon::DocumentNew)); 0249 d->ui->m_editCurrencyButton->setIcon(Icons::get(Icon::DocumentEdit)); 0250 d->ui->m_selectBaseCurrencyButton->setIcon(Icons::get(Icon::KMyMoney)); 0251 0252 connect(d->ui->m_currencyList, &QWidget::customContextMenuRequested, this, &KCurrencyEditDlg::slotShowCurrencyMenu); 0253 connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KCurrencyEditDlg::slotLoadCurrencies); 0254 connect(d->ui->m_currencyList, &QTreeWidget::itemChanged, this, static_cast<void (KCurrencyEditDlg::*)(QTreeWidgetItem *, int)>(&KCurrencyEditDlg::slotUpdateCurrency)); 0255 connect(d->ui->m_currencyList, &QTreeWidget::itemSelectionChanged, this, &KCurrencyEditDlg::slotItemSelectionChanged); 0256 0257 connect(d->ui->m_selectBaseCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotSelectBaseCurrency); 0258 connect(d->ui->m_addCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotAddCurrency); 0259 connect(d->ui->m_newCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotNewCurrency); 0260 connect(d->ui->m_removeCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotRemoveCurrency); 0261 connect(d->ui->m_editCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotEditCurrency); 0262 connect(d->ui->m_removeUnusedCurrencyButton, &QAbstractButton::clicked, this, &KCurrencyEditDlg::slotRemoveUnusedCurrency); 0263 0264 QMetaObject::invokeMethod(this, "finishCtor", Qt::QueuedConnection); 0265 } 0266 0267 void KCurrencyEditDlg::finishCtor() 0268 { 0269 Q_D(KCurrencyEditDlg); 0270 slotLoadCurrencies(); 0271 0272 //resize the column widths 0273 for (auto i = 0; i < 3; ++i) 0274 d->ui->m_currencyList->resizeColumnToContents(i); 0275 0276 if (!d->m_currentCurrency.id().isEmpty()) { 0277 QTreeWidgetItemIterator it(d->ui->m_currencyList); 0278 QTreeWidgetItem* q; 0279 while ((q = *it) != 0) { 0280 if (q->text(1) == d->m_currentCurrency.id()) { 0281 d->ui->m_currencyList->scrollToItem(q); 0282 break; 0283 } 0284 ++it; 0285 } 0286 } 0287 } 0288 0289 KCurrencyEditDlg::~KCurrencyEditDlg() 0290 { 0291 Q_D(KCurrencyEditDlg); 0292 delete d; 0293 } 0294 0295 void KCurrencyEditDlg::slotLoadCurrencies() 0296 { 0297 const QSet<QString> metalSymbols { "XAU", "XPD", "XPT", "XAG" }; 0298 0299 Q_D(KCurrencyEditDlg); 0300 0301 // catch recursive calls and avoid them 0302 if (d->m_inLoading) 0303 return; 0304 d->m_inLoading = true; 0305 0306 disconnect(d->ui->m_currencyList, &QTreeWidget::currentItemChanged, this, static_cast<void (KCurrencyEditDlg::*)(QTreeWidgetItem *, QTreeWidgetItem *)>(&KCurrencyEditDlg::slotSelectCurrency)); 0307 disconnect(d->ui->m_currencyList, &QTreeWidget::itemChanged, this, static_cast<void (KCurrencyEditDlg::*)(QTreeWidgetItem *, int)>(&KCurrencyEditDlg::slotUpdateCurrency)); 0308 0309 QList<MyMoneySecurity> list = MyMoneyFile::instance()->currencyList(); 0310 QList<MyMoneySecurity>::ConstIterator it; 0311 QTreeWidgetItem *first = 0; 0312 0313 // sort the currencies ... 0314 // ... and make sure a few precious metals are at the end 0315 std::sort(list.begin(), list.end(), 0316 [=] (const MyMoneySecurity& c1, const MyMoneySecurity& c2) 0317 { 0318 const bool c1Metal = c1.tradingSymbol().startsWith(QLatin1Char('X')) && metalSymbols.contains(c1.tradingSymbol()); 0319 const bool c2Metal = c2.tradingSymbol().startsWith(QLatin1Char('X')) && metalSymbols.contains(c2.tradingSymbol()); 0320 if (c1Metal ^ c2Metal) 0321 return c2Metal; 0322 0323 return c1.name().compare(c2.name()) < 0; 0324 }); 0325 0326 QString localCurrency(localeconv()->int_curr_symbol); 0327 localCurrency.truncate(3); 0328 0329 QString baseCurrency; 0330 try { 0331 baseCurrency = MyMoneyFile::instance()->baseCurrency().id(); 0332 } catch (const MyMoneyException &e) { 0333 qDebug("%s", e.what()); 0334 } 0335 0336 // construct a transparent 16x16 pixmap 0337 QPixmap empty(16, 16); 0338 QBitmap mask(16, 16); 0339 mask.clear(); 0340 empty.setMask(mask); 0341 0342 d->ui->m_currencyList->setSortingEnabled(false); 0343 d->ui->m_currencyList->clear(); 0344 for (it = list.constBegin(); it != list.constEnd(); ++it) { 0345 QTreeWidgetItem *p = new QTreeWidgetItem(d->ui->m_currencyList); 0346 p->setText(0, (*it).name()); 0347 p->setData(0, Qt::UserRole, QVariant::fromValue(*it)); 0348 p->setFlags(p->flags() | Qt::ItemIsEditable); 0349 p->setText(1, (*it).id()); 0350 // fix the ATS problem 0351 QString symbol = (*it).tradingSymbol(); 0352 if (((*it).id() == QLatin1String("ATS")) && (symbol != QString::fromUtf8("ÖS"))) { 0353 MyMoneySecurity tmp = d->m_currentCurrency; 0354 symbol = QString::fromUtf8("ÖS"); 0355 d->updateCurrency((*it).id(), (*it).name(), symbol); 0356 d->m_currentCurrency = tmp; 0357 } 0358 p->setText(2, symbol); 0359 0360 if ((*it).id() == baseCurrency) { 0361 p->setData(0, Qt::DecorationRole, Icons::get(Icon::KMyMoney)); 0362 if (d->m_currentCurrency.id().isEmpty()) 0363 first = p; 0364 } else { 0365 p->setData(0, Qt::DecorationRole, empty); 0366 } 0367 0368 // if we had a previously selected 0369 if (!d->m_currentCurrency.id().isEmpty()) { 0370 if (d->m_currentCurrency.id() == p->text(1)) 0371 first = p; 0372 } else if ((*it).id() == localCurrency && !first) 0373 first = p; 0374 } 0375 d->ui->m_removeUnusedCurrencyButton->setDisabled(list.count() <= 1); 0376 0377 connect(d->ui->m_currencyList, &QTreeWidget::currentItemChanged, this, static_cast<void (KCurrencyEditDlg::*)(QTreeWidgetItem *, QTreeWidgetItem *)>(&KCurrencyEditDlg::slotSelectCurrency)); 0378 connect(d->ui->m_currencyList, &QTreeWidget::itemChanged, this, static_cast<void (KCurrencyEditDlg::*)(QTreeWidgetItem *, int)>(&KCurrencyEditDlg::slotUpdateCurrency)); 0379 0380 if (first == 0) 0381 first = d->ui->m_currencyList->invisibleRootItem()->child(0); 0382 if (first != 0) { 0383 d->ui->m_currencyList->setCurrentItem(first); 0384 d->ui->m_currencyList->scrollToItem(first); 0385 } 0386 0387 slotSelectCurrency(first); 0388 d->m_inLoading = false; 0389 } 0390 0391 void KCurrencyEditDlg::slotUpdateCurrency(QTreeWidgetItem* citem, int) 0392 { 0393 slotUpdateCurrency(citem, nullptr); 0394 } 0395 0396 void KCurrencyEditDlg::slotUpdateCurrency(QTreeWidgetItem* citem, QTreeWidgetItem *pitem) 0397 { 0398 Q_D(KCurrencyEditDlg); 0399 Q_UNUSED(pitem) 0400 // if there is no current item selected, exit 0401 if (!d->ui->m_currencyList->currentItem() || citem != d->ui->m_currencyList->currentItem()) 0402 return; 0403 0404 const auto newName = d->ui->m_currencyList->currentItem()->text(0); 0405 const auto newSymbol = d->ui->m_currencyList->currentItem()->text(2); 0406 0407 // verify that the stored currency id is not empty and the edited fields are not empty either 0408 if (!d->m_currentCurrency.id().isEmpty() 0409 && !newSymbol.isEmpty() 0410 && !newName.isEmpty()) { 0411 d->updateCurrency(d->m_currentCurrency.id(), newName, newSymbol); 0412 } 0413 } 0414 0415 void KCurrencyEditDlg::slotSelectCurrency(const QString& id) 0416 { 0417 Q_D(KCurrencyEditDlg); 0418 QTreeWidgetItemIterator it(d->ui->m_currencyList); 0419 0420 while (*it) { 0421 if ((*it)->text(1) == id) { 0422 QSignalBlocker blocked(d->ui->m_currencyList); 0423 slotSelectCurrency(*it); 0424 d->ui->m_currencyList->setCurrentItem(*it); 0425 d->ui->m_currencyList->scrollToItem(*it); 0426 break; 0427 } 0428 ++it; 0429 } 0430 } 0431 0432 void KCurrencyEditDlg::slotSelectCurrency(QTreeWidgetItem *citem, QTreeWidgetItem *pitem) 0433 { 0434 Q_UNUSED(pitem) 0435 slotSelectCurrency(citem); 0436 } 0437 0438 void KCurrencyEditDlg::slotSelectCurrency(QTreeWidgetItem *item) 0439 { 0440 Q_D(KCurrencyEditDlg); 0441 auto file = MyMoneyFile::instance(); 0442 QString baseId; 0443 try { 0444 baseId = MyMoneyFile::instance()->baseCurrency().id(); 0445 } catch (const MyMoneyException &) { 0446 } 0447 0448 if (item) { 0449 try { 0450 d->m_currentCurrency = file->security(item->text(1)); 0451 0452 } catch (const MyMoneyException &) { 0453 d->m_currentCurrency = MyMoneySecurity(); 0454 } 0455 0456 QBitArray skip((int)eStorage::Reference::Count); 0457 skip.fill(false); 0458 skip.setBit((int)eStorage::Reference::Price); 0459 0460 const bool rc1 = d->m_currentCurrency.id() == baseId; 0461 const bool rc2 = file->isReferenced(d->m_currentCurrency, skip); 0462 const int count = d->ui->m_currencyList->selectedItems().count(); 0463 0464 d->ui->m_selectBaseCurrencyButton->setDisabled(rc1 || count != 1); 0465 d->ui->m_editCurrencyButton->setDisabled(count != 1); 0466 d->ui->m_removeCurrencyButton->setDisabled((rc1 || rc2) && count <= 1); 0467 // Q_EMIT selectObject(d->m_currentCurrency); 0468 } 0469 } 0470 0471 void KCurrencyEditDlg::slotItemSelectionChanged() 0472 { 0473 Q_D(KCurrencyEditDlg); 0474 int count = d->ui->m_currencyList->selectedItems().count(); 0475 if (!d->ui->m_selectBaseCurrencyButton->isEnabled() && count == 1) 0476 slotSelectCurrency(d->ui->m_currencyList->currentItem()); 0477 if (count > 1) 0478 d->ui->m_removeCurrencyButton->setEnabled(true); 0479 } 0480 0481 void KCurrencyEditDlg::slotShowCurrencyMenu(const QPoint& p) 0482 { 0483 Q_D(KCurrencyEditDlg); 0484 auto item = d->ui->m_currencyList->itemAt(p); 0485 if (item) { 0486 const auto sec = item->data(0, Qt::UserRole).value<MyMoneySecurity>(); 0487 const auto file = MyMoneyFile::instance(); 0488 QBitArray skip((int)eStorage::Reference::Count); 0489 skip.fill(false); 0490 skip.setBit((int)eStorage::Reference::Transaction); 0491 const auto cond1 = !sec.id().isEmpty(); 0492 const auto cond2 = cond1 && !file->isReferenced(sec, skip); 0493 const auto cond3 = cond1 && sec.id() != file->baseCurrency().id(); 0494 auto menu = new QMenu; 0495 typedef void(KCurrencyEditDlg::*KCurrencyEditDlgFunc)(); 0496 struct actionInfo { 0497 eMenu::Action action; 0498 KCurrencyEditDlgFunc callback; 0499 QString text; 0500 Icon icon; 0501 bool enabled; 0502 }; 0503 0504 const QVector<actionInfo> actionInfos { 0505 {eMenu::Action::NewCurrency, &KCurrencyEditDlg::slotNewCurrency, i18n("New currency"), Icon::DocumentNew, true}, 0506 {eMenu::Action::RenameCurrency, &KCurrencyEditDlg::slotRenameCurrency, i18n("Rename currency"), Icon::EditRename, cond1}, 0507 {eMenu::Action::DeleteCurrency, &KCurrencyEditDlg::slotDeleteCurrency, i18n("Delete currency"), Icon::EditRemove, cond2}, 0508 {eMenu::Action::SetBaseCurrency, &KCurrencyEditDlg::slotSetBaseCurrency, i18n("Select as base currency"), Icon::KMyMoney, cond3}, 0509 }; 0510 0511 QList<QAction*> LUTActions; 0512 for (const auto& info : actionInfos) { 0513 auto a = new QAction(Icons::get(info.icon), info.text, nullptr); // WARNING: no empty Icon::Empty here 0514 a->setEnabled(info.enabled); 0515 connect(a, &QAction::triggered, this, info.callback); 0516 LUTActions.append(a); 0517 } 0518 menu->addSection(i18nc("@title:menu", "Currency options")); 0519 menu->addActions(LUTActions); 0520 menu->exec(QCursor::pos()); 0521 } 0522 } 0523 0524 void KCurrencyEditDlg::slotSelectBaseCurrency() 0525 { 0526 Q_D(KCurrencyEditDlg); 0527 if (!d->m_currentCurrency.id().isEmpty()) { 0528 QTreeWidgetItem* const p = d->ui->m_currencyList->currentItem(); 0529 d->setBaseCurrency(d->m_currentCurrency); 0530 // in case the dataChanged() signal was not sent out (nested FileTransaction) 0531 // we update the list manually 0532 if (p == d->ui->m_currencyList->currentItem()) 0533 slotLoadCurrencies(); 0534 } 0535 } 0536 0537 void KCurrencyEditDlg::slotAddCurrency() 0538 { 0539 Q_D(KCurrencyEditDlg); 0540 QTreeWidgetItemIterator it(d->ui->m_currencyList); // iterate over whole tree 0541 QList<QString> currencyIdList; 0542 while (*it) { 0543 const auto currencyId = (*it)->data(0, Qt::UserRole).value<MyMoneySecurity>().id(); 0544 if (!currencyId.isEmpty()) { 0545 currencyIdList.append(currencyId); 0546 } 0547 ++it; 0548 } 0549 d->m_availableCurrencyDlg = new KAvailableCurrencyDlg(currencyIdList); // create new dialog for selecting currencies to add 0550 if (d->m_availableCurrencyDlg->exec() != QDialog::Rejected) { 0551 auto file = MyMoneyFile::instance(); 0552 QMap<MyMoneySecurity, MyMoneyPrice> ancientCurrencies = file->ancientCurrencies(); 0553 MyMoneyFileTransaction ft; 0554 const QList<QTreeWidgetItem*> currencyRows = d->m_availableCurrencyDlg->selectedItems(); // get selected currencies from new dialog 0555 for (const auto& currencyRow : currencyRows) { 0556 MyMoneySecurity currency = currencyRow->data(0, Qt::UserRole).value<MyMoneySecurity>(); 0557 file->addCurrency(currency); 0558 if (ancientCurrencies.value(currency, MyMoneyPrice()) != MyMoneyPrice()) { // if ancient currency is added... 0559 file->addPrice(ancientCurrencies[currency]); // ...we want to add last known exchange rate as well 0560 } else { 0561 // check if a new currency is added and the old one is already on file. 0562 // in that case, we want to add the last know exchange rate as well 0563 for (const auto &price : qAsConst(ancientCurrencies)) { 0564 QString ancientCurrencyId; 0565 if (price.from() == currency.id()) { 0566 ancientCurrencyId = price.to(); 0567 } else if (price.to() == currency.id()) { 0568 ancientCurrencyId = price.from(); 0569 } 0570 if (!ancientCurrencyId.isEmpty()) { 0571 // we found a replacement record, so we look for the 0572 // older variant 0573 try { 0574 const auto ancientCurrency = file->currency(ancientCurrencyId); 0575 if (!ancientCurrency.id().isEmpty()) { 0576 file->addPrice(ancientCurrencies[ancientCurrency]); 0577 } 0578 } catch (MyMoneyException&) { 0579 // nothing to do because ancient currency is not on file 0580 } 0581 break; 0582 } 0583 } 0584 } 0585 } 0586 ft.commit(); 0587 d->ui->m_removeUnusedCurrencyButton->setDisabled(file->currencyList().count() <= 1); 0588 } 0589 delete d->m_availableCurrencyDlg; 0590 } 0591 0592 void KCurrencyEditDlg::slotRemoveCurrency() 0593 { 0594 Q_D(KCurrencyEditDlg); 0595 d->removeCurrency(KCurrencyEditDlgPrivate::RemoveSelected); 0596 } 0597 0598 void KCurrencyEditDlg::slotRemoveUnusedCurrency() 0599 { 0600 Q_D(KCurrencyEditDlg); 0601 d->removeCurrency(KCurrencyEditDlgPrivate::RemoveUnused); 0602 } 0603 0604 void KCurrencyEditDlg::slotEditCurrency() 0605 { 0606 Q_D(KCurrencyEditDlg); 0607 auto currency = d->ui->m_currencyList->currentItem()->data(0, Qt::UserRole).value<MyMoneySecurity>(); 0608 currency.setSecurityType(eMyMoney::Security::Type::Currency); 0609 d->editCurrency(currency); 0610 0611 // update the model data 0612 const auto item = d->ui->m_currencyList->currentItem(); 0613 item->setData(0, Qt::UserRole, QVariant::fromValue(currency)); 0614 item->setText(0, currency.name()); 0615 item->setText(1, currency.id()); 0616 item->setText(2, currency.tradingSymbol()); 0617 } 0618 0619 void KCurrencyEditDlg::slotNewCurrency() 0620 { 0621 Q_D(KCurrencyEditDlg); 0622 MyMoneySecurity currency; 0623 currency.setSecurityType(eMyMoney::Security::Type::Currency); 0624 currency.setRoundingMethod(AlkValue::RoundNever); 0625 if (d->editCurrency(currency)) { 0626 slotSelectCurrency(currency.id()); 0627 } 0628 } 0629 0630 void KCurrencyEditDlg::slotRenameCurrency() 0631 { 0632 Q_D(KCurrencyEditDlg); 0633 QTreeWidgetItemIterator it_l(d->ui->m_currencyList, QTreeWidgetItemIterator::Selected); 0634 QTreeWidgetItem* it_v; 0635 if ((it_v = *it_l) != nullptr) { 0636 d->ui->m_currencyList->editItem(it_v, 0); 0637 } 0638 } 0639 0640 void KCurrencyEditDlg::slotDeleteCurrency() 0641 { 0642 Q_D(KCurrencyEditDlg); 0643 if (!d->m_currentCurrency.id().isEmpty()) { 0644 MyMoneyFileTransaction ft; 0645 try { 0646 MyMoneyFile::instance()->removeCurrency(d->m_currentCurrency); 0647 ft.commit(); 0648 } catch (const MyMoneyException &e) { 0649 KMessageBox::error(this, i18n("Cannot delete currency %1. %2", d->m_currentCurrency.name(), QString::fromLatin1(e.what())), i18n("Delete currency")); 0650 } 0651 } 0652 } 0653 0654 void KCurrencyEditDlg::slotSetBaseCurrency() 0655 { 0656 Q_D(KCurrencyEditDlg); 0657 if (!d->m_currentCurrency.id().isEmpty()) { 0658 if (d->m_currentCurrency.id() != MyMoneyFile::instance()->baseCurrency().id()) { 0659 MyMoneyFileTransaction ft; 0660 try { 0661 MyMoneyFile::instance()->setBaseCurrency(d->m_currentCurrency); 0662 ft.commit(); 0663 } catch (const MyMoneyException &e) { 0664 KMessageBox::error(this, i18n("Cannot set %1 as base currency: %2", d->m_currentCurrency.name(), QString::fromLatin1(e.what())), i18n("Set base currency")); 0665 } 0666 } 0667 } 0668 }