[office/kmymoney] /: Enhance date entry widget keyboard support.

Ralf Habacker null at kde.org
Tue Apr 14 21:33:34 BST 2026


Git commit d06d043fc0c435918af450f60fe7ac11ceabfcdf by Ralf Habacker, on behalf of Dawid Wróbel.
Committed on 14/04/2026 at 19:32.
Pushed by habacker into branch 'master'.

Enhance date entry widget keyboard support.

- Add new keyboard shortcuts for increasing/decreasing month and year,
  wrapping around dates as needed, while keeping the original day
  whenever possible.
- Add new keyboard shortcuts for quick selection or start/end of
  month and year.
- Simplifies the adjustDay(), adjustMonth() and adjustYear() logic.

All new keyboard shortcuts follow the GnuCash standard:
https://www.gnucash.org/docs/v5/C/gnucash-guide/chapter_txns.html

M  +32   -4    doc/details-widgets.docbook
M  +77   -60   kmymoney/widgets/kmymoneydateedit.cpp

https://invent.kde.org/office/kmymoney/-/commit/d06d043fc0c435918af450f60fe7ac11ceabfcdf

diff --git a/doc/details-widgets.docbook b/doc/details-widgets.docbook
index 5301a5a3c..4c152bc81 100644
--- a/doc/details-widgets.docbook
+++ b/doc/details-widgets.docbook
@@ -46,10 +46,38 @@
   Within the date entry widget, the &Left;/&Right; cursor keys can be used to switch
   between the <emphasis>day</emphasis>, the <emphasis>month</emphasis>, and the
   <emphasis>year</emphasis> fields. Using the &Up;/&Down; cursor keys, the value of
-  the selected field can be incremented/decremented.  The <keycap>+</keycap> and
-  <keycap>-</keycap> keys can be used to increment/decrement a single day.  Month and
-  year boundaries are considered and incremented/decremented if necessary.  Pressing
-  <keycap>T</keycap> will set the date to today's date.
+  the selected field can be incremented/decremented.  The <keycap>+</keycap> or
+  <keycap>=</keycap> and <keycap>-</keycap> keys can be used to increment/decrement a
+  single day.  The <keycap>]</keycap> or <keycap>}</keycap> and <keycap>[</keycap> or
+  <keycap>{</keycap> keys can be used to increment/decrement a single month.
+  The <keycap>'</keycap> or <keycap>"</keycap> and <keycap>;</keycap> or <keycap>:</keycap>
+  keys can be used to increment/decrement a single year. Month and year boundaries
+  are considered and incremented/decremented if necessary, e.g. using <keycap>+</keycap>
+  to increment the date of January 31th will change it to February 1st.
+</para>
+
+<para>
+  The following additional shortcuts can also be used:
+</para>
+
+<para>
+  <itemizedlist>
+    <listitem>
+      <para><keycap>M</keycap> to set the date to the first day of the current month</para>
+    </listitem>
+    <listitem>
+      <para><keycap>H</keycap> to set the date to the last day of the current month</para>
+    </listitem>
+    <listitem>
+      <para><keycap>Y</keycap> to set the date to the first day of the current year</para>
+    </listitem>
+    <listitem>
+      <para><keycap>R</keycap> to set the date to the last day of the current year</para>
+    </listitem>
+    <listitem>
+      <para><keycap>T</keycap> to set the date to today's date</para>
+    </listitem>
+  </itemizedlist>
 </para>
 
 <para>
diff --git a/kmymoney/widgets/kmymoneydateedit.cpp b/kmymoney/widgets/kmymoneydateedit.cpp
index 63864e5bc..07cd346be 100644
--- a/kmymoney/widgets/kmymoneydateedit.cpp
+++ b/kmymoney/widgets/kmymoneydateedit.cpp
@@ -256,75 +256,37 @@ public:
 
     /**
      * Adjust the day of the @a date by the amount provided by @a delta
-     * in days. In case the resulting day is not within the bounds of
-     * the month of @a date an invalid date is returned.
+     * in days.
      */
     QDate adjustDay(QDate date, int delta)
     {
-        const auto minValue(1);
-        const auto maxValue(date.daysInMonth());
-        const auto newDay(date.day() + delta);
-        if ((newDay >= minValue) && (newDay <= maxValue)) {
-            return QDate(date.year(), date.month(), newDay);
-        }
-        return {};
+        return date.addDays(delta);
     }
 
     /**
      * Adjust the month of the @a date by the amount provided by @a delta
-     * in months. In case the resulting month is not within the bounds of
-     * valid months (1..12) an invalid date is returned. In case the
-     * original day is larger than the current day, it will be used
-     * instead. In case the day is not within the range of valid days
-     * for the resulting month the day will be adjusted to the last day
-     * of the month.
+     * in months. Uses the original day. In case the original day is not within
+     * the range of valid days for the resulting, post-adjustment month, the day
+     * will be adjusted to the last day of that month.
      */
     QDate adjustMonth(QDate date, int delta)
     {
-        const auto minValue(1);
-        const auto maxValue(12);
-        const auto newMonth(date.month() + delta);
-
-        if ((newMonth >= minValue) && (newMonth <= maxValue)) {
-            auto day = date.day();
-            if (m_originalDay > day)
-                day = m_originalDay;
-            auto newDate = QDate(date.year(), newMonth, day);
-            if (!newDate.isValid()) {
-                const auto maxDays(QDate(date.year(), newMonth, 1).daysInMonth());
-                newDate = QDate(date.year(), newMonth, maxDays);
-            }
-            return newDate;
-        }
-        return {};
+        QDate newDate = date.addMonths(delta);
+
+        return QDate(newDate.year(), newDate.month(), qMin(m_originalDay, newDate.daysInMonth()));
     }
 
     /**
      * Adjust the year of the @a date by the amount provided by @a delta
-     * in years. In case the resulting year is not within the bounds of
-     * valid years (1..4000) an invalid date is returned. In case the
-     * original day is larger than the current day, it will be used
-     * instead. In case the day is not within the range of valid days
-     * for the resulting month the day will be adjusted to the last day
-     * of the month.
+     * in year. Uses the original day. In case the original day is not within
+     * the range of valid days for the resulting, post-adjustment month, the day
+     * will be adjusted to the last day of that month.
      */
     QDate adjustYear(QDate date, int delta)
     {
-        const auto minValue(1);
-        const auto maxValue(4000);
-        const auto newYear(date.year() + delta);
-        if ((newYear >= minValue) && (newYear <= maxValue)) {
-            auto day = date.day();
-            if (m_originalDay > day)
-                day = m_originalDay;
-            auto newDate = QDate(newYear, date.month(), day);
-            if (!newDate.isValid()) {
-                const auto maxDays(QDate(newYear, date.month(), 1).daysInMonth());
-                newDate = QDate(newYear, date.month(), maxDays);
-            }
-            return newDate;
-        }
-        return {};
+        QDate newDate = date.addYears(delta);
+
+        return QDate(newDate.year(), newDate.month(), qMin(m_originalDay, newDate.daysInMonth()));
     }
 
     /**
@@ -387,21 +349,16 @@ public:
             auto date = fixupDate();
             if (date.isValid()) {
                 switch (section) {
-                case QDateEdit::DaySection:
-                    date = adjustDay(date, delta);
-                    if (date.isValid()) {
-                        m_originalDay = date.day();
-                    }
-                    break;
                 case QDateEdit::MonthSection:
                     date = adjustMonth(date, delta);
                     break;
                 case QDateEdit::YearSection:
                     date = adjustYear(date, delta);
                     break;
+                case QDateEdit::DaySection:
                 case QDateEdit::NoSection:
                 default:
-                    date = date.addDays(delta);
+                    date = adjustDay(date, delta);
                     m_originalDay = date.day();
                     break;
                 }
@@ -608,7 +565,35 @@ void KMyMoneyDateEdit::keyPressEvent(QKeyEvent* keyEvent)
     case Qt::Key_Minus:
     case Qt::Key_Equal:
         if (isValid()) {
-            d->adjustDate(key != Qt::Key_Minus ? 1 : -1, QDateEdit::NoSection);
+            d->adjustDate(key != Qt::Key_Minus ? 1 : -1, QDateEdit::DaySection);
+        }
+        break;
+
+    case Qt::Key_BracketLeft:
+    case Qt::Key_BraceLeft:
+        if (isValid()) {
+            d->adjustDate(-1, QDateEdit::MonthSection);
+        }
+        break;
+
+    case Qt::Key_BracketRight:
+    case Qt::Key_BraceRight:
+        if (isValid()) {
+            d->adjustDate(1, QDateEdit::MonthSection);
+        }
+        break;
+
+    case Qt::Key_Colon:
+    case Qt::Key_Semicolon:
+        if (isValid()) {
+            d->adjustDate(-1, QDateEdit::YearSection);
+        }
+        break;
+
+    case Qt::Key_QuoteDbl:
+    case Qt::Key_Apostrophe:
+        if (isValid()) {
+            d->adjustDate(1, QDateEdit::YearSection);
         }
         break;
 
@@ -652,6 +637,38 @@ void KMyMoneyDateEdit::keyPressEvent(QKeyEvent* keyEvent)
         QComboBox::keyPressEvent(keyEvent);
         break;
 
+    case Qt::Key_M:
+        date = d->fixupDate();
+        if (date.isValid()) {
+            setDate(QDate(date.year(), date.month(), 1));
+            d->selectSection(QDateEdit::MonthSection);
+        }
+        break;
+
+    case Qt::Key_H:
+        date = d->fixupDate();
+        if (date.isValid()) {
+            setDate(QDate(date.year(), date.month(), date.daysInMonth()));
+            d->selectSection(QDateEdit::MonthSection);
+        }
+        break;
+
+    case Qt::Key_Y:
+        date = d->fixupDate();
+        if (date.isValid()) {
+            setDate(QDate(date.year(), 1, 1));
+            d->selectSection(QDateEdit::YearSection);
+        }
+        break;
+
+    case Qt::Key_R:
+        date = d->fixupDate();
+        if (date.isValid()) {
+            setDate(QDate(date.year(), 12, 31));
+            d->selectSection(QDateEdit::YearSection);
+        }
+        break;
+
     case Qt::Key_T:
         d->setDate(QDate::currentDate());
         Q_EMIT dateValidityChanged(QDate::currentDate());


More information about the kde-doc-english mailing list