[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kmymoney] kmymoney/views: Improve the new ledger
From:       Thomas Baumgart <null () kde ! org>
Date:       2017-12-31 14:15:42
Message-ID: E1eVeOs-0007Ih-Rh () code ! kde ! org
[Download RAW message or body]

Git commit b9e168955e73afa59925527b8ce8b32618bc4bfa by Thomas Baumgart.
Committed on 31/12/2017 at 14:15.
Pushed by tbaumgart into branch 'master'.

Improve the new ledger

The following changes have been made

- Display online balance if available
- Use standard colors from KColorScheme for separator background
- Paint separator text centered based on the view width
  and not centered in detail column

M  +186  -36   kmymoney/views/ledgerdelegate.cpp
M  +6    -0    kmymoney/views/ledgerdelegate.h
M  +28   -0    kmymoney/views/ledgerview.cpp
M  +2    -0    kmymoney/views/ledgerview.h

https://commits.kde.org/kmymoney/b9e168955e73afa59925527b8ce8b32618bc4bfa

diff --git a/kmymoney/views/ledgerdelegate.cpp b/kmymoney/views/ledgerdelegate.cpp
index f3a74d1a..04dadfac 100644
--- a/kmymoney/views/ledgerdelegate.cpp
+++ b/kmymoney/views/ledgerdelegate.cpp
@@ -30,6 +30,7 @@
 // KDE Includes
 
 #include <KLocalizedString>
+#include <KColorScheme>
 
 // ----------------------------------------------------------------------------
 // Project Includes
@@ -124,6 +125,7 @@ QColor LedgerDelegate::m_erroneousColor = QColor(Qt::red);
 QColor LedgerDelegate::m_importedColor = QColor(Qt::yellow);
 QColor LedgerDelegate::m_separatorColor = QColor(0xff, 0xf2, 0x9b);
 
+
 class LedgerSeperatorDate : public LedgerSeperator
 {
 public:
@@ -132,12 +134,30 @@ public:
 
   virtual bool rowHasSeperator(const QModelIndex& index) const;
   virtual QString separatorText(const QModelIndex& index) const;
+  virtual void adjustBackgroundScheme(QPalette& palette, const QModelIndex& index) \
const;  
-private:
+protected:
   QString getEntry(const QModelIndex& index, const QModelIndex& nextIndex) const;
   QMap<QDate, QString>      m_entries;
 };
 
+class LedgerSeparatorOnlineBalance : public LedgerSeperatorDate
+{
+public:
+  LedgerSeparatorOnlineBalance(eLedgerModel::Role role);
+  virtual ~LedgerSeparatorOnlineBalance() {}
+
+  virtual bool rowHasSeperator(const QModelIndex& index) const;
+  virtual QString separatorText(const QModelIndex& index) const;
+  virtual void adjustBackgroundScheme(QPalette& palette, const QModelIndex& index) \
const; +
+  void setSeparatorData(const QDate& date, const MyMoneyMoney& amount, int \
fraction); +
+private:
+  QString m_balanceAmount;
+};
+
+
 
 QDate LedgerSeperator::firstFiscalDate;
 bool  LedgerSeperator::showFiscalDate = true;
@@ -161,8 +181,6 @@ QModelIndex LedgerSeperator::nextIndex(const QModelIndex& index) \
const  return QModelIndex();
 }
 
-
-
 LedgerSeperatorDate::LedgerSeperatorDate(eLedgerModel::Role role)
   : LedgerSeperator(role)
 {
@@ -206,13 +224,15 @@ QString LedgerSeperatorDate::getEntry(const QModelIndex& index, \
const QModelInde  
   const QAbstractItemModel* model = index.model();
   QString rc;
-  if (model->data(index, (int)m_role).toDate() != model->data(nextIndex, \
                (int)m_role).toDate()) {
-    const QDate key = model->data(index, (int)m_role).toDate();
-    const QDate endKey = model->data(nextIndex, (int)m_role).toDate();
-    QMap<QDate, QString>::const_iterator it = m_entries.upperBound(key);
-    while((it != m_entries.cend()) && (it.key() <= endKey)) {
-      rc = *it;
-      ++it;
+  if(!m_entries.isEmpty()) {
+    if (model->data(index, (int)m_role).toDate() != model->data(nextIndex, \
(int)m_role).toDate()) { +      const QDate key = model->data(index, \
(int)m_role).toDate(); +      const QDate endKey = model->data(nextIndex, \
(int)m_role).toDate(); +      QMap<QDate, QString>::const_iterator it = \
m_entries.upperBound(key); +      while((it != m_entries.cend()) && (it.key() <= \
endKey)) { +        rc = *it;
+        ++it;
+      }
     }
   }
   return rc;
@@ -221,14 +241,16 @@ QString LedgerSeperatorDate::getEntry(const QModelIndex& index, \
const QModelInde  bool LedgerSeperatorDate::rowHasSeperator(const QModelIndex& index) \
const  {
   bool rc = false;
-  QModelIndex nextIdx = nextIndex(index);
-  if(nextIdx.isValid() ) {
-    const QString id = nextIdx.model()->data(nextIdx, \
                (int)eLedgerModel::Role::TransactionSplitId).toString();
-    // For a new transaction the id is completely empty, for a split view the \
                transaction
-    // part is filled but the split id is empty and the string ends with a dash
-    // and we never draw a separator in front of that row
-    if(!id.isEmpty() && !id.endsWith('-')) {
-      rc = !getEntry(index, nextIdx).isEmpty();
+  if(!m_entries.isEmpty()) {
+    QModelIndex nextIdx = nextIndex(index);
+    if(nextIdx.isValid() ) {
+      const QString id = nextIdx.model()->data(nextIdx, \
(int)eLedgerModel::Role::TransactionSplitId).toString(); +      // For a new \
transaction the id is completely empty, for a split view the transaction +      // \
part is filled but the split id is empty and the string ends with a dash +      // \
and we never draw a separator in front of that row +      if(!id.isEmpty() && \
!id.endsWith('-')) { +        rc = !getEntry(index, nextIdx).isEmpty();
+      }
     }
   }
   return rc;
@@ -243,6 +265,74 @@ QString LedgerSeperatorDate::separatorText(const QModelIndex& \
index) const  return QString();
 }
 
+void LedgerSeperatorDate::adjustBackgroundScheme(QPalette& palette, const \
QModelIndex& index) const +{
+  Q_UNUSED(index);
+  KColorScheme::adjustBackground(palette, KColorScheme::ActiveBackground, \
QPalette::Base, KColorScheme::Button, KSharedConfigPtr()); +}
+
+
+
+LedgerSeparatorOnlineBalance::LedgerSeparatorOnlineBalance(eLedgerModel::Role role)
+  : LedgerSeperatorDate(role)
+{
+  // we don't need the standard values
+  m_entries.clear();
+}
+
+void LedgerSeparatorOnlineBalance::setSeparatorData(const QDate& date, const \
MyMoneyMoney& amount, int fraction) +{
+  m_entries.clear();
+  if (date.isValid()) {
+    m_balanceAmount = amount.formatMoney(fraction);
+    m_entries[date] = i18n("Online statement balance: %1").arg(m_balanceAmount);
+  }
+}
+
+bool LedgerSeparatorOnlineBalance::rowHasSeperator(const QModelIndex& index) const
+{
+  bool rc = false;
+  if(!m_entries.isEmpty()) {
+    QModelIndex nextIdx = nextIndex(index);
+    const QAbstractItemModel* model = index.model();
+    // if this is not the last entry?
+    if(nextIdx.isValid() ) {
+      // index points to the last entry of a date
+      rc = (model->data(index, (int)m_role).toDate() != model->data(nextIdx, \
(int)m_role).toDate()); +      if (rc) {
+        // check if this the spot for the online balance data
+        rc &= ((model->data(index, (int)m_role).toDate() <= m_entries.firstKey())
+          && (model->data(nextIdx, (int)m_role).toDate() > m_entries.firstKey()));
+      }
+    } else {
+      rc = (model->data(index, (int)m_role).toDate() <= m_entries.firstKey());
+    }
+  }
+  return rc;
+}
+
+QString LedgerSeparatorOnlineBalance::separatorText(const QModelIndex& index) const
+{
+  if(rowHasSeperator(index)) {
+    return m_entries.first();
+  }
+  return QString();
+}
+
+void LedgerSeparatorOnlineBalance::adjustBackgroundScheme(QPalette& palette, const \
QModelIndex& index) const +{
+  const QAbstractItemModel* model = index.model();
+  QModelIndex amountIndex = model->index(index.row(), \
(int)eLedgerModel::Column::Balance); +  QString amount = \
model->data(amountIndex).toString(); +  KColorScheme::BackgroundRole role = \
KColorScheme::PositiveBackground; +
+  if (!m_entries.isEmpty()) {
+    if(amount != m_balanceAmount) {
+      role = KColorScheme::NegativeBackground;
+    }
+  }
+  KColorScheme::adjustBackground(palette, role, QPalette::Base, \
KColorScheme::Button, KSharedConfigPtr()); +}
 
 
 
@@ -253,8 +343,9 @@ public:
   Private()
   : m_editor(0)
   , m_view(0)
-  , m_separator(0)
   , m_editorRow(-1)
+  , m_separator(0)
+  , m_onlineBalanceSeparator(0)
   {}
 
   ~Private()
@@ -267,10 +358,16 @@ public:
     return m_separator && m_separator->rowHasSeperator(index);
   }
 
+  inline bool displayOnlineBalanceSeparator(const QModelIndex& index) const
+  {
+    return m_onlineBalanceSeparator && \
m_onlineBalanceSeparator->rowHasSeperator(index); +  }
+
   NewTransactionEditor*         m_editor;
   LedgerView*                   m_view;
-  LedgerSeperator*              m_separator;
   int                           m_editorRow;
+  LedgerSeperator*              m_separator;
+  LedgerSeparatorOnlineBalance* m_onlineBalanceSeparator;
 };
 
 
@@ -289,10 +386,14 @@ LedgerDelegate::~LedgerDelegate()
 void LedgerDelegate::setSortRole(eLedgerModel::Role role)
 {
   delete d->m_separator;
+  delete d->m_onlineBalanceSeparator;
   d->m_separator = 0;
+  d->m_onlineBalanceSeparator = 0;
+
   switch(role) {
     case eLedgerModel::Role::PostDate:
       d->m_separator = new LedgerSeperatorDate(role);
+      d->m_onlineBalanceSeparator = new LedgerSeparatorOnlineBalance(role);
       break;
     default:
       qDebug() << "LedgerDelegate::setSortRole role" << (int)role << "not \
implemented"; @@ -300,12 +401,17 @@ void \
LedgerDelegate::setSortRole(eLedgerModel::Role role)  }
 }
 
-
 void LedgerDelegate::setErroneousColor(const QColor& color)
 {
   m_erroneousColor = color;
 }
 
+void LedgerDelegate::setOnlineBalance(const QDate& date, const MyMoneyMoney& amount, \
int fraction) +{
+  if(d->m_onlineBalanceSeparator) {
+    d->m_onlineBalanceSeparator->setSeparatorData(date, amount, fraction);
+  }
+}
 
 QWidget* LedgerDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& \
option, const QModelIndex& index) const  {
@@ -366,6 +472,7 @@ void LedgerDelegate::paint(QPainter* painter, const \
QStyleOptionViewItem& option  QAbstractItemView* view = qobject_cast< \
QAbstractItemView* >(parent());  const bool editWidgetIsVisible = d->m_view && \
d->m_view->indexWidget(index);  const bool rowHasSeperator = \
d->displaySeperator(index); +  const bool rowHasOnlineBalance = \
d->displayOnlineBalanceSeparator(index);  
   // Background
   QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
@@ -376,9 +483,15 @@ void LedgerDelegate::paint(QPainter* painter, const \
QStyleOptionViewItem& option  // don't draw over the separator space
     opt.rect.setHeight(opt.rect.height() - lineHeight );
   }
+  if (rowHasOnlineBalance) {
+    // don't draw over the online balance space
+    opt.rect.setHeight(opt.rect.height() - lineHeight );
+  }
 
   style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
 
+  QPalette::ColorGroup cg;
+
   // Do not paint text if the edit widget is shown
   if (!editWidgetIsVisible) {
     if(view && (index.column() == (int)eLedgerModel::Column::Detail)) {
@@ -418,29 +531,27 @@ void LedgerDelegate::paint(QPainter* painter, const \
QStyleOptionViewItem& option  opt.state &= ~QStyle::State_Enabled;
       }
 
-      QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
-                                ? QPalette::Normal : QPalette::Disabled;
+      cg = (opt.state & QStyle::State_Enabled) ? QPalette::Normal : \
QPalette::Disabled;  
       if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) {
         cg = QPalette::Inactive;
       }
-      if (opt.state & QStyle::State_Selected) {
+      if (selected) {
         // always use the normal palette since the background is also in normal
         painter->setPen(opt.palette.color(QPalette::ColorGroup(QPalette::Normal), \
QPalette::HighlightedText)); +
+      } else if (erroneous) {
+        painter->setPen(m_erroneousColor);
+
       } else {
         painter->setPen(opt.palette.color(cg, QPalette::Text));
       }
+
       if (opt.state & QStyle::State_Editing) {
         painter->setPen(opt.palette.color(cg, QPalette::Text));
         painter->drawRect(textArea.adjusted(0, 0, -1, -1));
       }
 
-      // Don't play with the color if it's selected
-      // otherwise switch the color if the transaction has errors
-      if(erroneous && !selected) {
-        painter->setPen(m_erroneousColor);
-      }
-
       // collect data for the various columns
       if(index.column() == (int)eLedgerModel::Column::Detail) {
         for(int i = 0; i < lines.count(); ++i) {
@@ -460,8 +571,7 @@ void LedgerDelegate::paint(QPainter* painter, const \
QStyleOptionViewItem& option  o.state |= QStyle::State_KeyboardFocusChange;
       o.state |= QStyle::State_Item;
 
-      QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
-                                ? QPalette::Normal : QPalette::Disabled;
+      cg = (opt.state & QStyle::State_Enabled) ? QPalette::Normal : \
                QPalette::Disabled;
       o.backgroundColor = opt.palette.color(cg, (opt.state & QStyle::State_Selected)
                                               ? QPalette::Highlight : \
                QPalette::Window);
       style->proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, \
opt.widget); @@ -477,10 +587,40 @@ void LedgerDelegate::paint(QPainter* painter, \
const QStyleOptionViewItem& option  }
 
   // draw a separator if any
+  if (rowHasOnlineBalance) {
+    opt.rect.setY(opt.rect.y() + opt.rect.height());
+    opt.rect.setHeight(lineHeight);
+    d->m_onlineBalanceSeparator->adjustBackgroundScheme(opt.palette, index);
+    opt.backgroundBrush = opt.palette.base();
+
+    // never draw it as selected but always enabled
+    opt.state &= ~QStyle::State_Selected;
+    style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
+
+    // when the editor is shown, the row has only a single column
+    // so we need to paint the seperator if we get here in this casee
+    bool needPaint = editWidgetIsVisible;
+
+    if(!needPaint && (index.column() == (int)eLedgerModel::Column::Detail)) {
+      needPaint = true;
+      // adjust the rect to cover all columns
+      if(view && view->viewport()) {
+        opt.rect.setX(0);
+        opt.rect.setWidth(view->viewport()->width());
+      }
+    }
+
+    if(needPaint) {
+      painter->setPen(opt.palette.color(QPalette::Normal, QPalette::Text));
+      painter->drawText(opt.rect, Qt::AlignCenter, \
d->m_onlineBalanceSeparator->separatorText(index)); +    }
+  }
+
   if (rowHasSeperator) {
     opt.rect.setY(opt.rect.y() + opt.rect.height());
-    opt.rect.setHeight(lineHeight + margin);
-    opt.backgroundBrush = m_separatorColor;
+    opt.rect.setHeight(lineHeight);
+    d->m_separator->adjustBackgroundScheme(opt.palette, index);
+    opt.backgroundBrush = opt.palette.base();
 
     // never draw it as selected but always enabled
     opt.state &= ~QStyle::State_Selected;
@@ -500,8 +640,7 @@ void LedgerDelegate::paint(QPainter* painter, const \
QStyleOptionViewItem& option  }
 
     if(needPaint) {
-      QPalette::ColorGroup cg = QPalette::Normal;
-      painter->setPen(opt.palette.color(cg, QPalette::Text));
+      painter->setPen(opt.palette.foreground().color());
       painter->drawText(opt.rect, Qt::AlignCenter, \
d->m_separator->separatorText(index));  }
   }
@@ -542,6 +681,10 @@ QSize LedgerDelegate::sizeHint(const QStyleOptionViewItem& \
option, const QModelI  // don't draw over the separator space
             size += QSize(0, lineHeight + margin);
           }
+          if(d->displayOnlineBalanceSeparator(index)) {
+            // don't draw over the separator space
+            size += QSize(0, lineHeight + margin);
+          }
           return size;
         }
       }
@@ -568,6 +711,9 @@ QSize LedgerDelegate::sizeHint(const QStyleOptionViewItem& \
option, const QModelI  if (d->m_separator && d->m_separator->rowHasSeperator(index)) \
{  size.setHeight(size.height() + lineHeight + margin);
   }
+  if (d->m_onlineBalanceSeparator && \
d->m_onlineBalanceSeparator->rowHasSeperator(index)) { +    \
size.setHeight(size.height() + lineHeight + margin); +  }
   return size;
 }
 
@@ -593,6 +739,10 @@ void LedgerDelegate::updateEditorGeometry(QWidget* editor, const \
QStyleOptionVie  // consider the separator space
     r.setHeight(r.height() - lineHeight - margin);
   }
+  if(d->displayOnlineBalanceSeparator(index)) {
+    // consider the separator space
+    r.setHeight(r.height() - lineHeight - margin);
+  }
   editor->setGeometry(r);
   editor->update();
 }
diff --git a/kmymoney/views/ledgerdelegate.h b/kmymoney/views/ledgerdelegate.h
index 66f93872..de088824 100644
--- a/kmymoney/views/ledgerdelegate.h
+++ b/kmymoney/views/ledgerdelegate.h
@@ -22,6 +22,7 @@
 // QT Includes
 
 #include <QStyledItemDelegate>
+class QColor;
 
 // ----------------------------------------------------------------------------
 // KDE Includes
@@ -33,6 +34,7 @@
 #include "modelenums.h"
 
 class LedgerView;
+class MyMoneyMoney;
 
 class LedgerSeperator
 {
@@ -43,6 +45,8 @@ public:
   virtual bool rowHasSeperator(const QModelIndex& index) const = 0;
   virtual QString separatorText(const QModelIndex& index) const = 0;
 
+  virtual void adjustBackgroundScheme(QPalette& palette, const QModelIndex& index) \
const = 0; +
   static void setFirstFiscalDate(int firstMonth, int firstDay);
   static void setShowFiscalDate(bool show) { showFiscalDate = show; }
   static void setShowFancyDate(bool show) { showFancyDate = show; }
@@ -82,6 +86,8 @@ public:
    */
   virtual int editorRow() const;
 
+  void setOnlineBalance(const QDate& date, const MyMoneyMoney& amount, int fraction \
= 0); +
   static void setErroneousColor(const QColor& color);
   static void setImportedColor(const QColor& color);
 
diff --git a/kmymoney/views/ledgerview.cpp b/kmymoney/views/ledgerview.cpp
index c724fee6..825e745c 100644
--- a/kmymoney/views/ledgerview.cpp
+++ b/kmymoney/views/ledgerview.cpp
@@ -23,6 +23,7 @@
 #include <QHeaderView>
 #include <QPainter>
 #include <QResizeEvent>
+#include <QDate>
 
 // ----------------------------------------------------------------------------
 // KDE Includes
@@ -37,6 +38,7 @@
 #include "mymoneymoney.h"
 #include "mymoneyfile.h"
 #include "mymoneyaccount.h"
+#include "accountsmodel.h"
 
 class LedgerView::Private
 {
@@ -175,6 +177,14 @@ void LedgerView::setAccount(const MyMoneyAccount& acc)
   d->filterModel->setAccountType(acc.accountType());
   d->setSortRole(eLedgerModel::Role::PostDate, (int)eLedgerModel::Column::Date);
 
+  if (acc.hasOnlineMapping()) {
+    connect(Models::instance()->accountsModel(), &AccountsModel::dataChanged, this, \
&LedgerView::accountChanged); +    accountChanged();
+  } else {
+    disconnect(Models::instance()->accountsModel(), &AccountsModel::dataChanged, \
this, &LedgerView::accountChanged); +    d->delegate->setOnlineBalance(QDate(), \
MyMoneyMoney()); +  }
+
   // if balance calculation has not been triggered, then run it immediately
   if(!d->balanceCalculationPending) {
     recalculateBalances();
@@ -205,6 +215,24 @@ QString LedgerView::accountId() const
   return id;
 }
 
+void LedgerView::accountChanged()
+{
+  QString id = accountId();
+  if(!id.isEmpty()) {
+    d->account = MyMoneyFile::instance()->account(id);
+    QDate onlineBalanceDate = \
QDate::fromString(d->account.value(QLatin1String("lastImportedTransactionDate")), \
Qt::ISODate); +    MyMoneyMoney \
amount(d->account.value(QLatin1String("lastStatementBalance"))); +    if \
(d->showValuesInverted) { +      amount = -amount;
+    }
+    d->delegate->setOnlineBalance(onlineBalanceDate, amount, d->account.fraction());
+  } else {
+    d->delegate->setOnlineBalance(QDate(), MyMoneyMoney());
+  }
+  // force redraw
+  d->filterModel->invalidate();
+}
+
 void LedgerView::recalculateBalances()
 {
   d->recalculateBalances();
diff --git a/kmymoney/views/ledgerview.h b/kmymoney/views/ledgerview.h
index 6cffcecd..3e1c9fba 100644
--- a/kmymoney/views/ledgerview.h
+++ b/kmymoney/views/ledgerview.h
@@ -87,6 +87,8 @@ protected Q_SLOTS:
 
   virtual void recalculateBalances();
 
+  virtual void accountChanged();
+
 Q_SIGNALS:
   void transactionSelected(const QString& transactionSplitId);
   void aboutToStartEdit();


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic