[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