[office/kmymoney] /: Add a button to adjust current split with unassigned amount
Thomas Baumgart
null at kde.org
Tue Nov 29 10:11:38 GMT 2022
Git commit 37641841e99f8a0842f3097f00d1249871d03847 by Thomas Baumgart, on behalf of Alexander Kuznetsov.
Committed on 29/11/2022 at 10:11.
Pushed by tbaumgart into branch 'master'.
Add a button to adjust current split with unassigned amount
Adds a button to adjust the selected split
with the unassigned or over-assigned amount
directly to balance the transaction without
using a calculator.
M +2 -0 .gitignore
M +23 -1 doc/details-ledgers.docbook
A +- -- doc/split_unassigned.png
M +73 -20 kmymoney/views/splitdialog.cpp
M +5 -0 kmymoney/views/splitdialog.h
M +16 -1 kmymoney/views/splitdialog.ui
https://invent.kde.org/office/kmymoney/commit/37641841e99f8a0842f3097f00d1249871d03847
diff --git a/.gitignore b/.gitignore
index cad01d5d7..3cd57c734 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@ CMakeSettings.json
.idea
.vs
docker/.env
+.vscode
+
diff --git a/doc/details-ledgers.docbook b/doc/details-ledgers.docbook
index 1d51d92ba..10c61f112 100644
--- a/doc/details-ledgers.docbook
+++ b/doc/details-ledgers.docbook
@@ -472,6 +472,29 @@
transaction unassigned.
</para>
+<para>
+ <screenshot>
+ <screeninfo>Split with unassigned amount</screeninfo>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="split_unasigned.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <phrase>Split with unasssigned amount</phrase>
+ </textobject>
+ </mediaobject>
+ </screenshot>
+</para>
+
+<para>
+ To redistribute an 'Unassigned' or 'Overassigned' amount, select a split item that has to be adjusted.
+ After that click on a button <guibutton>Apply Difference</guibutton>.
+ If 'Unassigned' was previously shown and non-zero, that amount will be added to the selected line item value.
+ If 'Overassigned' was previously shown and non-zero, that amount will be subtracted from the selected line item value.
+ As the result, the 'Unassigned' amount will be set to zero and a transaction could be saved
+ successfully.
+</para>
+
<para>
Note that the category field in the transaction form or the transaction
list now displays <emphasis>Split transaction</emphasis>.
@@ -729,4 +752,3 @@
</para>
</sect1>
</chapter>
-
diff --git a/doc/split_unassigned.png b/doc/split_unassigned.png
new file mode 100644
index 000000000..047666601
Binary files /dev/null and b/doc/split_unassigned.png differ
diff --git a/kmymoney/views/splitdialog.cpp b/kmymoney/views/splitdialog.cpp
index e2042b772..573f85ab5 100644
--- a/kmymoney/views/splitdialog.cpp
+++ b/kmymoney/views/splitdialog.cpp
@@ -15,9 +15,10 @@
// ----------------------------------------------------------------------------
// KDE Includes
+#include <KColorScheme>
+#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
-#include <KConfigGroup>
// ----------------------------------------------------------------------------
// Project Includes
@@ -81,7 +82,8 @@ static const int DiffRow = 1;
static const int AmountRow = 2;
static const int HeaderCol = 0;
static const int ValueCol = 1;
-
+static const int SummaryRows = 3;
+static const int SummaryCols = 2;
void SplitDialog::Private::deleteSplits(QModelIndexList indexList)
{
@@ -106,7 +108,7 @@ void SplitDialog::Private::deleteSplits(QModelIndexList indexList)
if (!(id.isEmpty() || id.endsWith('-'))) {
model->removeRow(*it);
}
- } while(it != sortedList.constBegin());
+ } while (it != sortedList.constBegin());
blockEditorStart(false);
}
@@ -125,7 +127,7 @@ void SplitDialog::Private::blockImmediateEditor()
void SplitDialog::Private::selectRow(int row)
{
if (row >= ui->splitView->model()->rowCount())
- row = ui->splitView->model()->rowCount()-1;
+ row = ui->splitView->model()->rowCount() - 1;
if (row >= 0) {
blockEditorStart(true);
ui->splitView->selectRow(row);
@@ -165,6 +167,7 @@ SplitDialog::SplitDialog(const MyMoneySecurity& commodity,
connect(d->ui->deleteAllButton, &QAbstractButton::pressed, this, &SplitDialog::deleteAllSplits);
connect(d->ui->deleteButton, &QAbstractButton::pressed, this, &SplitDialog::deleteSelectedSplits);
connect(d->ui->deleteZeroButton, &QAbstractButton::pressed, this, &SplitDialog::deleteZeroSplits);
+ connect(d->ui->adjustUnassigned, &QAbstractButton::pressed, this, &SplitDialog::adjustUnassigned);
connect(d->ui->mergeButton, &QAbstractButton::pressed, this, &SplitDialog::mergeSplits);
connect(d->ui->newSplitButton, &QAbstractButton::pressed, this, &SplitDialog::newSplit);
@@ -176,19 +179,24 @@ SplitDialog::SplitDialog(const MyMoneySecurity& commodity,
size.setHeight(size.height() - 1);
resize(size.expandedTo(minimumSizeHint()));
+ // m_unassigned_over = KColorScheme(QPalette::Normal).foreground(KColorScheme::PositiveText);
+ // m_unassigned_under = KColorScheme(QPalette::Normal).foreground(KColorScheme::NegativeText);
+ m_unassigned_error = KColorScheme(QPalette::Normal).foreground(KColorScheme::NegativeText);
+ m_unassigned_normal = KColorScheme(QPalette::Normal).foreground(KColorScheme::NormalText);
+
// finish polishing the widgets
QMetaObject::invokeMethod(this, "adjustSummary", Qt::QueuedConnection);
}
SplitDialog::~SplitDialog()
{
- auto grp = KSharedConfig::openConfig()->group("SplitTransactionEditor");
+ auto grp = KSharedConfig::openConfig()->group("SplitTransactionEditor");
grp.writeEntry("Geometry", size());
}
int SplitDialog::exec()
{
- if(!d->ui->splitView->model()) {
+ if (!d->ui->splitView->model()) {
qWarning() << "SplitDialog::exec() executed without a model. Use setModel() before calling exec().";
return QDialog::Rejected;
}
@@ -202,15 +210,15 @@ void SplitDialog::accept()
if (d->transactionTotal.isAutoCalc()) {
d->transactionTotal = d->splitsTotal;
- } else if(d->transactionTotal != d->splitsTotal) {
+ } else if (d->transactionTotal != d->splitsTotal) {
QPointer<SplitAdjustDialog> dlg = new SplitAdjustDialog(this);
dlg->setValues(d->ui->summaryView->item(AmountRow, ValueCol)->data(Qt::DisplayRole).toString(),
d->ui->summaryView->item(SumRow, ValueCol)->data(Qt::DisplayRole).toString(),
d->ui->summaryView->item(DiffRow, ValueCol)->data(Qt::DisplayRole).toString(),
d->ui->splitView->model()->rowCount());
accept = false;
- if(dlg->exec() == QDialog::Accepted && dlg) {
- switch(dlg->selectedOption()) {
+ if (dlg->exec() == QDialog::Accepted && dlg) {
+ switch (dlg->selectedOption()) {
case SplitAdjustDialog::SplitAdjustContinue:
break;
case SplitAdjustDialog::SplitAdjustChange:
@@ -229,7 +237,7 @@ void SplitDialog::accept()
delete dlg;
updateButtonState();
}
- if(accept)
+ if (accept)
QDialog::accept();
}
@@ -248,7 +256,7 @@ void SplitDialog::setModel(SplitModel* model)
d->splitModel = model;
d->ui->splitView->setModel(model);
- if(model->rowCount() > 0) {
+ if (model->rowCount() > 0) {
QModelIndex index = model->index(0, 0);
d->ui->splitView->setCurrentIndex(index);
}
@@ -262,6 +270,15 @@ void SplitDialog::setModel(SplitModel* model)
void SplitDialog::adjustSummary()
{
+ // Apply color scheme to the summary panel
+ for (int row = 0; row < SummaryRows; row++) {
+ for (int col = 0; col < SummaryCols; col++) {
+ if (row == DiffRow && col == ValueCol)
+ continue;
+ d->ui->summaryView->item(row, col)->setForeground(m_unassigned_normal);
+ }
+ }
+
// Only show the currency symbol when multiple currencies are involved
QString currencySymbol = d->commoditySymbol;
if (!d->splitModel->hasMultiCurrencySplits()) {
@@ -281,7 +298,7 @@ void SplitDialog::adjustSummary()
QString formattedValue = (d->splitsTotal * d->inversionFactor).formatMoney(currencySymbol, denom);
d->ui->summaryView->item(SumRow, ValueCol)->setData(Qt::DisplayRole, formattedValue);
- if(d->transactionEditor) {
+ if (d->transactionEditor) {
if (d->transactionTotal.isAutoCalc()) {
formattedValue = (d->splitsTotal * d->inversionFactor).formatMoney(currencySymbol, denom);
} else {
@@ -290,10 +307,17 @@ void SplitDialog::adjustSummary()
d->ui->summaryView->item(AmountRow, ValueCol)->setData(Qt::DisplayRole, formattedValue);
if (!d->transactionTotal.isAutoCalc()) {
- if ((d->transactionTotal.abs() - d->splitsTotal.abs()).isNegative()) {
- d->ui->summaryView->item(DiffRow, HeaderCol)->setData(Qt::DisplayRole, i18nc("Split editor summary", "Assigned too much"));
+ auto diff = d->transactionTotal.abs() - d->splitsTotal.abs();
+ if (diff.isNegative()) {
+ d->ui->summaryView->item(DiffRow, HeaderCol)->setData(Qt::DisplayRole, i18nc("Split editor summary", "Overassigned"));
+ d->ui->summaryView->item(DiffRow, ValueCol)->setForeground(m_unassigned_error);
} else {
d->ui->summaryView->item(DiffRow, HeaderCol)->setData(Qt::DisplayRole, i18nc("Split editor summary", "Unassigned"));
+ if (diff.isZero()) {
+ d->ui->summaryView->item(DiffRow, ValueCol)->setForeground(m_unassigned_normal);
+ } else {
+ d->ui->summaryView->item(DiffRow, ValueCol)->setForeground(m_unassigned_error);
+ }
}
formattedValue = (d->transactionTotal - d->splitsTotal).abs().formatMoney(currencySymbol, denom);
d->ui->summaryView->item(DiffRow, ValueCol)->setData(Qt::DisplayRole, formattedValue);
@@ -329,15 +353,15 @@ void SplitDialog::newSplit()
// are on this row already with the editor closed things
// are a bit more complicated.
QModelIndex index = d->ui->splitView->currentIndex();
- if(index.isValid()) {
+ if (index.isValid()) {
int row = index.row();
- if(row != d->ui->splitView->model()->rowCount()-1) {
- d->ui->splitView->selectRow(d->ui->splitView->model()->rowCount()-1);
+ if (row != d->ui->splitView->model()->rowCount() - 1) {
+ d->ui->splitView->selectRow(d->ui->splitView->model()->rowCount() - 1);
} else {
d->ui->splitView->edit(index);
}
} else {
- d->ui->splitView->selectRow(d->ui->splitView->model()->rowCount()-1);
+ d->ui->splitView->selectRow(d->ui->splitView->model()->rowCount() - 1);
}
}
@@ -357,6 +381,7 @@ void SplitDialog::updateButtonState()
d->ui->deleteAllButton->setEnabled(false);
d->ui->mergeButton->setEnabled(false);
d->ui->deleteZeroButton->setEnabled(false);
+ d->ui->adjustUnassigned->setEnabled(false);
if (!d->readOnly) {
if (d->ui->splitView->selectionModel()->selectedRows().count() > 0) {
@@ -367,6 +392,13 @@ void SplitDialog::updateButtonState()
d->ui->deleteAllButton->setEnabled(true);
}
+ if (d->ui->splitView->selectionModel()->selectedRows().count() == 1
+ && !d->ui->splitView->selectionModel()->selectedIndexes().at(0).data(eMyMoney::Model::IdRole).toString().isEmpty()) {
+ if (!d->transactionTotal.isAutoCalc()) {
+ d->ui->adjustUnassigned->setDisabled((d->transactionTotal.abs() - d->splitsTotal.abs()).isZero());
+ }
+ }
+
QAbstractItemModel* model = d->ui->splitView->model();
QSet<QString> accountIDs;
const auto rows = model->rowCount();
@@ -408,14 +440,35 @@ void SplitDialog::deleteAllSplits()
d->selectRow(row);
}
+void SplitDialog::adjustUnassigned()
+{
+ QModelIndex index = d->ui->splitView->currentIndex();
+ if (index.isValid()) {
+ // extract current values ...
+ auto shares = index.data(eMyMoney::Model::SplitSharesRole).value<MyMoneyMoney>();
+ auto value = index.data(eMyMoney::Model::SplitValueRole).value<MyMoneyMoney>();
+ const auto price = value / shares;
+ const auto diff = d->transactionTotal - d->splitsTotal;
+ // ... and adjust shares and value ...
+ value += diff;
+ shares = value / price;
+ // ... and update the model
+ auto model = d->ui->splitView->model();
+ model->setData(index, QVariant::fromValue<MyMoneyMoney>(shares), eMyMoney::Model::SplitSharesRole);
+ model->setData(index, QVariant::fromValue<MyMoneyMoney>(value), eMyMoney::Model::SplitValueRole);
+
+ adjustSummary();
+ }
+}
+
void SplitDialog::deleteZeroSplits()
{
QAbstractItemModel* model = d->ui->splitView->model();
QModelIndexList list = model->match(model->index(0, 0), eMyMoney::Model::IdRole, QLatin1String(".+"), -1, Qt::MatchRegularExpression);
- for(int row = 0; row < list.count();) {
+ for (int row = 0; row < list.count();) {
const auto idx = list.at(row);
- if(!idx.data(eMyMoney::Model::SplitSharesRole).value<MyMoneyMoney>().isZero()) {
+ if (!idx.data(eMyMoney::Model::SplitSharesRole).value<MyMoneyMoney>().isZero()) {
list.removeAt(row);
} else {
++row;
diff --git a/kmymoney/views/splitdialog.h b/kmymoney/views/splitdialog.h
index 0c874e13b..badf4a5dc 100644
--- a/kmymoney/views/splitdialog.h
+++ b/kmymoney/views/splitdialog.h
@@ -72,10 +72,15 @@ protected Q_SLOTS:
void mergeSplits();
void selectionChanged();
void updateButtonState();
+ void adjustUnassigned();
protected:
void resizeEvent(QResizeEvent* ev) final override;
void adjustSummaryWidth();
+ // QBrush m_unassigned_over;
+ // QBrush m_unassigned_under;
+ QBrush m_unassigned_normal;
+ QBrush m_unassigned_error;
private:
class Private;
diff --git a/kmymoney/views/splitdialog.ui b/kmymoney/views/splitdialog.ui
index 3536f0bab..490f28f73 100644
--- a/kmymoney/views/splitdialog.ui
+++ b/kmymoney/views/splitdialog.ui
@@ -33,7 +33,7 @@
<property name="minimumSize">
<size>
<width>0</width>
- <height>72</height>
+ <height>82</height>
</size>
</property>
<property name="palette">
@@ -621,6 +621,20 @@
</property>
</widget>
</item>
+
+ <item>
+ <widget class="QPushButton" name="adjustUnassigned">
+ <property name="toolTip">
+ <string>Apply 'Unassigned' or 'Overassigned' amount to the current split.
+'Unassigned' amount will be added or 'Overassigned' amount
+will be subtracted from the amount of the selected split.</string>
+ </property>
+ <property name="text">
+ <string>Apply Difference</string>
+ </property>
+ </widget>
+ </item>
+
<item>
<widget class="QPushButton" name="deleteZeroButton">
<property name="toolTip">
@@ -631,6 +645,7 @@
</property>
</widget>
</item>
+
<item>
<widget class="QPushButton" name="deleteButton">
<property name="text">
More information about the kde-doc-english
mailing list