diff --git a/kmymoney/models/ledgertransaction.cpp b/kmymoney/models/ledgertransaction.cpp index b1824b5cf..d00fb6124 100644 --- a/kmymoney/models/ledgertransaction.cpp +++ b/kmymoney/models/ledgertransaction.cpp @@ -1,315 +1,315 @@ /* * Copyright 2016-2018 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ledgertransaction.h" #include "ledgertransaction_p.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneymoney.h" #include "mymoneyenums.h" using namespace eMyMoney; LedgerTransaction::LedgerTransaction() : LedgerItem(), d_ptr(new LedgerTransactionPrivate) { } LedgerTransaction::LedgerTransaction(const MyMoneyTransaction& t, const MyMoneySplit& s) : LedgerItem(), d_ptr(new LedgerTransactionPrivate) { Q_D(LedgerTransaction); d->init(t,s); } LedgerTransaction::LedgerTransaction(LedgerTransactionPrivate &dd) : d_ptr(&dd) { } LedgerTransaction::LedgerTransaction(LedgerTransactionPrivate &dd, const MyMoneyTransaction& t, const MyMoneySplit& s) : d_ptr(&dd) { Q_D(LedgerTransaction); d->init(t,s); } LedgerTransaction::LedgerTransaction(const LedgerTransaction& other) : d_ptr(new LedgerTransactionPrivate(*other.d_func())) { } LedgerTransaction::~LedgerTransaction() { delete d_ptr; } QDate LedgerTransaction::postDate() const { Q_D(const LedgerTransaction); return d->m_transaction.postDate(); } MyMoneyTransaction LedgerTransaction::transaction() const { Q_D(const LedgerTransaction); return d->m_transaction; } const MyMoneySplit& LedgerTransaction::split() const { Q_D(const LedgerTransaction); return d->m_split; } QString LedgerTransaction::accountId() const { Q_D(const LedgerTransaction); return d->m_split.accountId(); } QString LedgerTransaction::account() const { Q_D(const LedgerTransaction); return d->m_account; } QString LedgerTransaction::counterAccountId() const { Q_D(const LedgerTransaction); return d->m_counterAccountId; } QString LedgerTransaction::counterAccount() const { Q_D(const LedgerTransaction); return d->m_counterAccount; } QString LedgerTransaction::costCenterId() const { Q_D(const LedgerTransaction); return d->m_costCenterId; } QString LedgerTransaction::payeeName() const { Q_D(const LedgerTransaction); return d->m_payeeName; } QString LedgerTransaction::payeeId() const { Q_D(const LedgerTransaction); return d->m_payeeId; } QString LedgerTransaction::transactionNumber() const { Q_D(const LedgerTransaction); return d->m_split.number(); } Qt::ItemFlags LedgerTransaction::flags() const { return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); } QString LedgerTransaction::transactionSplitId() const { Q_D(const LedgerTransaction); QString rc; if(!d->m_transaction.id().isEmpty()) { - rc = QString("%1-%2").arg(d->m_transaction.id()).arg(d->m_split.id()); + rc = QString("%1-%2").arg(d->m_transaction.id(), d->m_split.id()); } return rc; } int LedgerTransaction::splitCount() const { Q_D(const LedgerTransaction); return d->m_transaction.splitCount(); } QString LedgerTransaction::transactionId() const { Q_D(const LedgerTransaction); return d->m_transaction.id(); } eMyMoney::Split::State LedgerTransaction::reconciliationState() const { Q_D(const LedgerTransaction); return d->m_split.reconcileFlag(); } QString LedgerTransaction::reconciliationStateShort() const { Q_D(const LedgerTransaction); QString rc; switch(d->m_split.reconcileFlag()) { case eMyMoney::Split::State::NotReconciled: default: break; case eMyMoney::Split::State::Cleared: rc = i18nc("Reconciliation flag C", "C"); break; case eMyMoney::Split::State::Reconciled: rc = i18nc("Reconciliation flag R", "R"); break; case eMyMoney::Split::State::Frozen: rc = i18nc("Reconciliation flag F", "F"); break; } return rc; } QString LedgerTransaction::reconciliationStateLong() const { Q_D(const LedgerTransaction); QString rc; switch(d->m_split.reconcileFlag()) { case eMyMoney::Split::State::NotReconciled: default: rc = i18nc("Reconciliation flag empty", "Not reconciled"); break; case eMyMoney::Split::State::Cleared: rc = i18nc("Reconciliation flag C", "Cleared"); break; case eMyMoney::Split::State::Reconciled: rc = i18nc("Reconciliation flag R", "Reconciled"); break; case eMyMoney::Split::State::Frozen: rc = i18nc("Reconciliation flag F", "Frozen"); break; } return rc; } QString LedgerTransaction::payment() const { Q_D(const LedgerTransaction); return d->m_payment; } QString LedgerTransaction::deposit() const { Q_D(const LedgerTransaction); return d->m_deposit; } void LedgerTransaction::setBalance(QString txt) { Q_D(LedgerTransaction); d->m_balance = txt; } QString LedgerTransaction::balance() const { Q_D(const LedgerTransaction); return d->m_balance; } MyMoneyMoney LedgerTransaction::shares() const { Q_D(const LedgerTransaction); return d->m_split.shares(); } QString LedgerTransaction::sharesAmount() const { Q_D(const LedgerTransaction); return d->m_shares; } QString LedgerTransaction::signedSharesAmount() const { Q_D(const LedgerTransaction); return d->m_signedShares; } QString LedgerTransaction::sharesSuffix() const { Q_D(const LedgerTransaction); return d->m_sharesSuffix; } MyMoneyMoney LedgerTransaction::value() const { Q_D(const LedgerTransaction); return d->m_split.value(); } QString LedgerTransaction::memo() const { Q_D(const LedgerTransaction); auto memo = d->m_split.memo(); if(memo.isEmpty()) { memo = d->m_transaction.memo(); } return memo; } bool LedgerTransaction::isErroneous() const { Q_D(const LedgerTransaction); return d->m_erroneous; } bool LedgerTransaction::isImported() const { Q_D(const LedgerTransaction); return d->m_transaction.isImported(); } LedgerTransaction LedgerTransaction::newTransactionEntry() { // create a dummy entry for new transactions MyMoneyTransaction t; t.setPostDate(QDate(2900,12,31)); return LedgerTransaction(t, MyMoneySplit()); } bool LedgerTransaction::isNewTransactionEntry() const { Q_D(const LedgerTransaction); return d->m_transaction.id().isEmpty() && d->m_split.id().isEmpty(); } QString LedgerTransaction::transactionCommodity() const { Q_D(const LedgerTransaction); return d->m_transaction.commodity(); } diff --git a/kmymoney/models/splitmodel.cpp b/kmymoney/models/splitmodel.cpp index 5552bd0b4..fcebc5427 100644 --- a/kmymoney/models/splitmodel.cpp +++ b/kmymoney/models/splitmodel.cpp @@ -1,447 +1,447 @@ /* * Copyright 2016-2018 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "splitmodel.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "models.h" #include "costcentermodel.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "mymoneypayee.h" #include "mymoneymoney.h" #include "mymoneyexception.h" #include "kmymoneyutils.h" #include "modelenums.h" using namespace eLedgerModel; using namespace eMyMoney; class SplitModelPrivate { public: SplitModelPrivate() : m_invertValues(false) {} bool isCreateSplitEntry(const QString& id) const { return id.isEmpty(); } MyMoneyTransaction m_transaction; QVector m_splits; bool m_invertValues; }; SplitModel::SplitModel(QObject* parent) : QAbstractTableModel(parent), d_ptr(new SplitModelPrivate) { } SplitModel::~SplitModel() { } QString SplitModel::newSplitId() { return QLatin1String("New-ID"); } bool SplitModel::isNewSplitId(const QString& id) { return id.compare(newSplitId()) == 0; } int SplitModel::rowCount(const QModelIndex& parent) const { Q_D(const SplitModel); Q_UNUSED(parent); return d->m_splits.count(); } int SplitModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return (int)Column::LastColumn; } void SplitModel::deepCopy(const SplitModel& right, bool revertSplitSign) { Q_D(SplitModel); beginInsertRows(QModelIndex(), 0, right.rowCount()); d->m_splits = right.d_func()->m_splits; d->m_transaction = right.d_func()->m_transaction; if(revertSplitSign) { for(int idx = 0; idx < d->m_splits.count(); ++idx) { MyMoneySplit& split = d->m_splits[idx]; split.setShares(-split.shares()); split.setValue(-split.value()); } } endInsertRows(); } QVariant SplitModel::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch(section) { case (int)Column::CostCenter: return i18n("Cost Center"); case (int)Column::Detail: return i18n("Category"); case (int)Column::Number: return i18n("No"); case (int)Column::Date: return i18n("Date"); case (int)Column::Security: return i18n("Security"); case (int)Column::Reconciliation: return i18n("C"); case (int)Column::Payment: return i18n("Payment"); case (int)Column::Deposit: return i18n("Deposit"); case (int)Column::Quantity: return i18n("Quantity"); case (int)Column::Price: return i18n("Price"); case (int)Column::Amount: return i18n("Amount"); case (int)Column::Value: return i18n("Value"); case (int)Column::Balance: return i18n("Balance"); } } return QAbstractItemModel::headerData(section, orientation, role); } QVariant SplitModel::data(const QModelIndex& index, int role) const { Q_D(const SplitModel); if(!index.isValid()) return QVariant(); if(index.row() < 0 || index.row() >= d->m_splits.count()) return QVariant(); QVariant rc; MyMoneyAccount acc; MyMoneyMoney value; const MyMoneySplit& split = d->m_splits[index.row()]; QModelIndex subIndex; CostCenterModel* ccModel = Models::instance()->costCenterModel(); switch(role) { case Qt::DisplayRole: // make sure to never return any displayable text for the dummy entry if(!d->isCreateSplitEntry(split.id())) { switch(index.column()) { case (int)Column::Detail: rc = MyMoneyFile::instance()->accountToCategory(split.accountId()); break; case (int)Column::CostCenter: subIndex = Models::indexById(ccModel, CostCenterModel::CostCenterIdRole, split.costCenterId()); rc = ccModel->data(subIndex); break; case (int)Column::Number: rc = split.number(); break; case (int)Column::Reconciliation: rc = KMyMoneyUtils::reconcileStateToString(split.reconcileFlag(), false); break; case (int)Column::Payment: if(split.value().isNegative()) { acc = MyMoneyFile::instance()->account(split.accountId()); rc = (-split).value(d->m_transaction.commodity(), acc.currencyId()).formatMoney(acc.fraction()); } break; case (int)Column::Deposit: if(!split.value().isNegative()) { acc = MyMoneyFile::instance()->account(split.accountId()); rc = split.value(d->m_transaction.commodity(), acc.currencyId()).formatMoney(acc.fraction()); } break; default: break; } } break; case Qt::TextAlignmentRole: switch(index.column()) { case (int)Column::Payment: case (int)Column::Deposit: case (int)Column::Amount: case (int)Column::Balance: case (int)Column::Value: rc = QVariant(Qt::AlignRight| Qt::AlignTop); break; case (int)Column::Reconciliation: rc = QVariant(Qt::AlignHCenter | Qt::AlignTop); break; default: rc = QVariant(Qt::AlignLeft | Qt::AlignTop); break; } break; case (int)Role::AccountId: rc = split.accountId(); break; case (int)Role::Account: rc = MyMoneyFile::instance()->accountToCategory(split.accountId()); break; case (int)Role::TransactionId: rc = QString("%1").arg(d->m_transaction.id()); break; case (int)Role::TransactionSplitId: - rc = QString("%1-%2").arg(d->m_transaction.id()).arg(split.id()); + rc = QString("%1-%2").arg(d->m_transaction.id(), split.id()); break; case (int)Role::SplitId: rc = split.id(); break; case (int)Role::Memo: case (int)Role::SingleLineMemo: rc = split.memo(); if(role == (int)Role::SingleLineMemo) { QString txt = rc.toString(); // remove empty lines txt.replace("\n\n", "\n"); // replace '\n' with ", " txt.replace('\n', ", "); rc = txt; } break; case (int)Role::SplitShares: rc = QVariant::fromValue(split.shares()); break; case (int)Role::SplitValue: acc = MyMoneyFile::instance()->account(split.accountId()); rc = QVariant::fromValue(split.value(d->m_transaction.commodity(), acc.currencyId())); break; case (int)Role::PayeeName: try { rc = MyMoneyFile::instance()->payee(split.payeeId()).name(); } catch (const MyMoneyException &e) { } break; case (int)Role::CostCenterId: rc = split.costCenterId(); break; case (int)Role::TransactionCommodity: return d->m_transaction.commodity(); break; case (int)Role::Number: rc = split.number(); break; case (int)Role::PayeeId: rc = split.payeeId(); break; default: if(role >= Qt::UserRole) { qWarning() << "Undefined role" << role << "(" << role-Qt::UserRole << ") in SplitModel::data"; } break; } return rc; } bool SplitModel::setData(const QModelIndex& index, const QVariant& value, int role) { Q_D(SplitModel); bool rc = false; if(index.isValid()) { MyMoneySplit& split = d->m_splits[index.row()]; if(split.id().isEmpty()) { split = MyMoneySplit(newSplitId(), split); } QString val; rc = true; switch(role) { case (int)Role::PayeeId: split.setPayeeId(value.toString()); break; case (int)Role::AccountId: split.setAccountId(value.toString()); break; case (int)Role::Memo: split.setMemo(value.toString()); break; case (int)Role::CostCenterId: val = value.toString(); split.setCostCenterId(value.toString()); break; case (int)Role::Number: split.setNumber(value.toString()); break; case (int)Role::SplitShares: split.setShares(value.value()); break; case (int)Role::SplitValue: split.setValue(value.value()); break; case (int)Role::EmitDataChanged: { // the whole row changed QModelIndex topLeft = this->index(index.row(), 0); QModelIndex bottomRight = this->index(index.row(), this->columnCount()-1); emit dataChanged(topLeft, bottomRight); } break; default: rc = false; break; } } return rc; } void SplitModel::addSplit(const QString& transactionSplitId) { Q_D(SplitModel); QRegExp transactionSplitIdExp("^(\\w+)-(\\w+)$"); if(transactionSplitIdExp.exactMatch(transactionSplitId)) { const QString transactionId = transactionSplitIdExp.cap(1); const QString splitId = transactionSplitIdExp.cap(2); if(transactionId != d->m_transaction.id()) { try { d->m_transaction = MyMoneyFile::instance()->transaction(transactionId); } catch (const MyMoneyException &e) { d->m_transaction = MyMoneyTransaction(); } } try { beginInsertRows(QModelIndex(), rowCount(), rowCount()); d->m_splits.append(d->m_transaction.splitById(splitId)); endInsertRows(); } catch (const MyMoneyException &e) { d->m_transaction = MyMoneyTransaction(); } } } void SplitModel::addEmptySplitEntry() { Q_D(SplitModel); QModelIndexList list = match(index(0, 0), (int)Role::SplitId, QString(), -1, Qt::MatchExactly); if(list.count() == 0) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); // d->m_splits.append(MyMoneySplit(d->newSplitEntryId(), MyMoneySplit())); d->m_splits.append(MyMoneySplit()); endInsertRows(); } } void SplitModel::removeEmptySplitEntry() { Q_D(SplitModel); // QModelIndexList list = match(index(0, 0), SplitIdRole, d->newSplitEntryId(), -1, Qt::MatchExactly); QModelIndexList list = match(index(0, 0), (int)Role::SplitId, QString(), -1, Qt::MatchExactly); if(list.count()) { QModelIndex index = list.at(0); beginRemoveRows(QModelIndex(), index.row(), index.row()); d->m_splits.remove(index.row(), 1); endRemoveRows(); } } bool SplitModel::removeRows(int row, int count, const QModelIndex& parent) { Q_D(SplitModel); bool rc = false; if(count > 0) { beginRemoveRows(parent, row, row + count - 1); d->m_splits.remove(row, count); endRemoveRows(); rc = true; } return rc; } Qt::ItemFlags SplitModel::flags(const QModelIndex& index) const { Q_D(const SplitModel); Qt::ItemFlags flags; if(!index.isValid()) return flags; if(index.row() < 0 || index.row() >= d->m_splits.count()) return flags; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } #if 0 void SplitModel::removeSplit(const LedgerTransaction& t) { Q_D(SplitModel); QModelIndexList list = match(index(0, 0), TransactionSplitIdRole, t.transactionSplitId(), -1, Qt::MatchExactly); if(list.count()) { QModelIndex index = list.at(0); beginRemoveRows(QModelIndex(), index.row(), index.row()); delete d->m_ledgerItems[index.row()]; d->m_ledgerItems.remove(index.row(), 1); endRemoveRows(); // just make sure we're in sync Q_ASSERT(d->m_ledgerItems.count() == rowCount()); } } #endif