diff --git a/kmymoney/dialogs/settings/ksettingsregister.ui b/kmymoney/dialogs/settings/ksettingsregister.ui index 358c81d4b..da3a1cea4 100644 --- a/kmymoney/dialogs/settings/ksettingsregister.ui +++ b/kmymoney/dialogs/settings/ksettingsregister.ui @@ -1,554 +1,596 @@ KSettingsRegister 0 0 632 - 500 + 512 Register settings - 2 + 0 Display Show a grid in the register Show all register entries in full detail Using the ledger lens shows the details for the transaction that has focus in the ledger. Usually, when using the transaction form, only a one line summary is displayed for each transaction as the details are shown in the form. Use the ledger lens Show transaction form Always show a No. field Draws a larger header above each group of transactions. The grouping depends on the current sort order. Show group header between transactions Show header for the previous and current fiscal year If a planned transaction is overdue, today's date is used by default as the posting date. With this option, the originally planned date is used instead. Display overdue schedules with planned date Qt::Vertical QSizePolicy::Expanding 20 40 Sorting Normal view Reconciliation view Search view Use the <i>left</i> and <i>right</i> buttons to add and remove sort options. Use the <i>up</i> and <i>down</i> buttons to modify the sort order. Double-Click a selected entry to toggle the sort order between <i>ascending</i> and <i>descending</i>. true Data entry Insert transaction type into No. field for new transactions Auto increment check number Keep changes when selecting a different transaction/split Use Enter to move between fields Mark this option, if you always want to match names e.g. for payees from the start. If unset, any substring is matched. Match names from start After entering the reconciliation data automatically detect the transactions that match that data (in some cases it might be not possible to do that). Automatic reconciliation - - + + + + + Initial cursor position within the date field + + + + + + + + Day + + + + + Month + + + + + Year + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 31 + 20 + + + + + Default reconciliation state false - + Default reconciliation state for transactions entered during reconciliation of an account Not reconciled Cleared Reconciled - + Qt::Horizontal QSizePolicy::Expanding 31 20 Autofill -1 Do not auto-fill transaction data at all. No Autofill Collect all transactions for the given payee. Treat all transactions that refer to the same category and have an amount with +/- X % as identical. If more than one transaction is found, a list of them is presented to the user. Selecting 0% will list all transactions. Same transaction if amount differs less than percentage set below true The data of the last transaction assigned to the category used most often for this payee is autofilled into the transaction editor. With previously most often used transaction for the payee 0 0 Same transaction if amount differs less than Two transactions are usually treated identical for autofill, if they refer the same accounts. They are treated as different transactions though, when their amount varies by more than the percentage given here. % 100 10 Qt::Horizontal 40 20 If this option is checked the memos from the previous transaction will be used otherwise the memos will not be considered when the transaction is autofilled. Use memos from previous transaction Qt::Vertical QSizePolicy::Expanding 20 20 Import Match transactions within days false Search for matching transactions within the range of the posting date of the imported transaction +/- the number of given days. QAbstractSpinBox::UpDownArrows 0 99 4 Qt::Horizontal QSizePolicy::Expanding 61 20 Whenever a new payee is detected during import of a statement, the user will be asked to assign a default category for this user when this option is selected. Ask for a new payee's default category Qt::Vertical QSizePolicy::Expanding 20 60 KComboBox QComboBox
kcombobox.h
KLineEdit QLineEdit
klineedit.h
TransactionSortOption QWidget
transactionsortoption.h
radioButton2 toggled(bool) percentageWidget setEnabled(bool) 147 323 171 378
diff --git a/kmymoney/settings/kmymoney.kcfg b/kmymoney/settings/kmymoney.kcfg index dddb670b3..3662c5add 100644 --- a/kmymoney/settings/kmymoney.kcfg +++ b/kmymoney/settings/kmymoney.kcfg @@ -1,455 +1,464 @@ false 1 10 true true false false 10 0 20 10 0 60 false false 0 0 999 (None) 0 0 999 false false false false true true 0 0 false false false true true 0 true true false account,cashflow,payee,category,tag,memo,number,date,amount,state number,date,payee,category,tag,memo,payment,deposit,state 8,1,2,3,4,5,6,7,-9,10 1.00 true true false false false false false false false 255,255,0 152,251,152 255,0,0 0,0,255 255,242,155 255,255,221 false false false false false false false false false true true true 0 0 11 1 1 28 QDateTime::fromString("1900-01-01T00:00:00", Qt::ISODate) false system 1,-9,-4 1,-4 1,-9,-4 + + + Day + + + + + + 0 4 false Bar Banca,Banque Kreditkarte And. Kto. Eröffnungssaldo Rechnung false 10 0 100 2 0 256 2 0 2 0 90 1 999 30 1 999 3 1 999 0 0 31 1 true true true diff --git a/kmymoney/settings/kmymoneysettings.kcfgc b/kmymoney/settings/kmymoneysettings.kcfgc index ffcf13884..ea5eef567 100644 --- a/kmymoney/settings/kmymoneysettings.kcfgc +++ b/kmymoney/settings/kmymoneysettings.kcfgc @@ -1,9 +1,10 @@ File=kmymoney.kcfg ClassName=KMyMoneySettings Singleton=true Mutators=true MemberVariables=private IncludeFiles=\"kmm_settings_export.h\",\"kmymoneysettings_addon.h\" SourceIncludeFiles=\"kmymoneysettings_addons.cpp\" Visibility=KMM_SETTINGS_EXPORT CustomAdditions=true +UseEnumTypes=true diff --git a/kmymoney/widgets/kmymoneydateinput.cpp b/kmymoney/widgets/kmymoneydateinput.cpp index 6ecd2679d..d34e926e5 100644 --- a/kmymoney/widgets/kmymoneydateinput.cpp +++ b/kmymoney/widgets/kmymoneydateinput.cpp @@ -1,389 +1,402 @@ /* * Copyright 2000-2003 Michael Edwardes * Copyright 2001 Felix Rodriguez * 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 "kmymoneydateinput.h" +#include "kmymoneysettings.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "icons/icons.h" using namespace Icons; namespace { const int DATE_POPUP_TIMEOUT = 1500; const QDate INVALID_DATE = QDate(1800, 1, 1); } -KMyMoney::OldDateEdit::OldDateEdit(const QDate& date, QWidget* parent) : - QDateEdit(date, parent) +KMyMoney::OldDateEdit::OldDateEdit(const QDate& date, QWidget* parent) + : QDateEdit(date, parent) + , m_initialSection(QDateTimeEdit::DaySection) { } void KMyMoney::OldDateEdit::keyPressEvent(QKeyEvent* k) { if ((lineEdit()->text().isEmpty() || lineEdit()->selectedText() == lineEdit()->text()) && QChar(k->key()).isDigit()) { // the line edit is empty which means that the date was cleared // or the whole text is selected and a digit character was entered // (the same meaning as clearing the date) - in this case set the date // to the current date and let the editor do the actual work setDate(QDate::currentDate()); - setSelectedSection(QDateTimeEdit::DaySection); // start as when focused in if the date was cleared + setSelectedSection(m_initialSection); // start as when focused in if the date was cleared } QDateEdit::keyPressEvent(k); } void KMyMoney::OldDateEdit::focusInEvent(QFocusEvent * event) { QDateEdit::focusInEvent(event); - setSelectedSection(QDateTimeEdit::DaySection); + setSelectedSection(m_initialSection); } bool KMyMoney::OldDateEdit::event(QEvent* e) { // make sure that we keep the current date setting of a KMyMoneyDateInput object // across the QDateEdit::event(FocusOutEvent) bool rc; KMyMoneyDateInput* p = dynamic_cast(parentWidget()); if (e->type() == QEvent::FocusOut && p) { QDate d = p->date(); rc = QDateEdit::event(e); if (d.isValid()) d = p->date(); p->loadDate(d); } else { rc = QDateEdit::event(e); } return rc; } bool KMyMoney::OldDateEdit::focusNextPrevChild(bool next) { Q_UNUSED(next) return true; } struct KMyMoneyDateInput::Private { - QDateEdit *m_dateEdit; + KMyMoney::OldDateEdit *m_dateEdit; KDatePicker *m_datePicker; QDate m_date; QDate m_prevDate; Qt::AlignmentFlag m_qtalignment; QWidget *m_dateFrame; QPushButton *m_dateButton; KPassivePopup *m_datePopup; }; KMyMoneyDateInput::KMyMoneyDateInput(QWidget *parent, Qt::AlignmentFlag flags) : QWidget(parent), d(new Private) { d->m_qtalignment = flags; d->m_date = QDate::currentDate(); QHBoxLayout *dateInputLayout = new QHBoxLayout(this); dateInputLayout->setSpacing(0); dateInputLayout->setContentsMargins(0, 0, 0, 0); d->m_dateEdit = new KMyMoney::OldDateEdit(d->m_date, this); dateInputLayout->addWidget(d->m_dateEdit, 3); setFocusProxy(d->m_dateEdit); d->m_dateEdit->installEventFilter(this); // To get d->m_dateEdit's FocusIn/Out and some KeyPress events // we use INVALID_DATE as a special value for multi transaction editing d->m_dateEdit->setMinimumDate(INVALID_DATE); d->m_dateEdit->setSpecialValueText(QLatin1String(" ")); d->m_datePopup = new KPassivePopup(d->m_dateEdit); d->m_datePopup->setObjectName("datePopup"); d->m_datePopup->setTimeout(DATE_POPUP_TIMEOUT); d->m_datePopup->setView(new QLabel(QLocale().toString(d->m_date), d->m_datePopup)); d->m_dateFrame = new QWidget(this); dateInputLayout->addWidget(d->m_dateFrame); QVBoxLayout *dateFrameVBoxLayout = new QVBoxLayout(d->m_dateFrame); dateFrameVBoxLayout->setMargin(0); dateFrameVBoxLayout->setContentsMargins(0, 0, 0, 0); d->m_dateFrame->setWindowFlags(Qt::Popup); d->m_dateFrame->hide(); d->m_dateEdit->setDisplayFormat(QLocale().dateFormat(QLocale::ShortFormat)); + switch(KMyMoneySettings::initialDateFieldCursorPosition()) { + case KMyMoneySettings::Day: + d->m_dateEdit->setInitialSection(QDateTimeEdit::DaySection); + break; + case KMyMoneySettings::Month: + d->m_dateEdit->setInitialSection(QDateTimeEdit::MonthSection); + break; + case KMyMoneySettings::Year: + d->m_dateEdit->setInitialSection(QDateTimeEdit::YearSection); + break; + } d->m_datePicker = new KDatePicker(d->m_date, d->m_dateFrame); dateFrameVBoxLayout->addWidget(d->m_datePicker); // Let the date picker have a close button (Added in 3.1) d->m_datePicker->setCloseButton(true); // the next line is a try to add an icon to the button d->m_dateButton = new QPushButton(Icons::get(Icon::ViewCalendarDay), QString(), this); dateInputLayout->addWidget(d->m_dateButton); connect(d->m_dateButton, &QAbstractButton::clicked, this, &KMyMoneyDateInput::toggleDatePicker); connect(d->m_dateEdit, &QDateTimeEdit::dateChanged, this, &KMyMoneyDateInput::slotDateChosenRef); connect(d->m_datePicker, &KDatePicker::dateSelected, this, &KMyMoneyDateInput::slotDateChosen); connect(d->m_datePicker, &KDatePicker::dateEntered, this, &KMyMoneyDateInput::slotDateChosen); connect(d->m_datePicker, &KDatePicker::dateSelected, d->m_dateFrame, &QWidget::hide); } void KMyMoneyDateInput::markAsBadDate(bool bad, const QColor& color) { // the next line knows a bit about the internals of QAbstractSpinBox QLineEdit* le = d->m_dateEdit->findChild(); //krazy:exclude=qclasses if (le) { QPalette palette = this->palette(); le->setPalette(palette); if (bad) { palette.setColor(foregroundRole(), color); le->setPalette(palette); } } } void KMyMoneyDateInput::showEvent(QShowEvent* event) { // don't forget the standard behaviour ;-) QWidget::showEvent(event); // If the widget is shown, the size must be fixed a little later // to be appropriate. I saw this in some other places and the only // way to solve this problem is to postpone the setup of the size // to the time when the widget is on the screen. QTimer::singleShot(50, this, SLOT(fixSize())); } void KMyMoneyDateInput::fixSize() { // According to a hint in the documentation of KDatePicker::sizeHint() // 28 pixels should be added in each direction to obtain a better // display of the month button. I decided, (22,14) is good // enough and save some space on the screen (ipwizard) d->m_dateFrame->setFixedSize(d->m_datePicker->sizeHint() + QSize(22, 14)); } KMyMoneyDateInput::~KMyMoneyDateInput() { delete d->m_dateFrame; delete d->m_datePopup; delete d; } void KMyMoneyDateInput::toggleDatePicker() { int w = d->m_dateFrame->width(); int h = d->m_dateFrame->height(); if (d->m_dateFrame->isVisible()) { d->m_dateFrame->hide(); } else { QPoint tmpPoint = mapToGlobal(d->m_dateButton->geometry().bottomRight()); // usually, the datepicker widget is shown underneath the d->m_dateEdit widget // if it does not fit on the screen, we show it above this widget if (tmpPoint.y() + h > QApplication::desktop()->height()) { tmpPoint.setY(tmpPoint.y() - h - d->m_dateButton->height()); } if ((d->m_qtalignment == Qt::AlignRight && tmpPoint.x() + w <= QApplication::desktop()->width()) || (tmpPoint.x() - w < 0)) { d->m_dateFrame->setGeometry(tmpPoint.x() - width(), tmpPoint.y(), w, h); } else { tmpPoint.setX(tmpPoint.x() - w); d->m_dateFrame->setGeometry(tmpPoint.x(), tmpPoint.y(), w, h); } if (d->m_date.isValid() && d->m_date != INVALID_DATE) { d->m_datePicker->setDate(d->m_date); } else { d->m_datePicker->setDate(QDate::currentDate()); } d->m_dateFrame->show(); } } /** Overriding QWidget::keyPressEvent * * increments/decrements the date upon +/- or Up/Down key input * sets the date to current date when the 'T' key is pressed */ void KMyMoneyDateInput::keyPressEvent(QKeyEvent * k) { QKeySequence today(i18nc("Enter todays date into date input widget", "T")); auto adjustDateSection = [&](int offset) { switch(d->m_dateEdit->currentSection()) { case QDateTimeEdit::DaySection: slotDateChosen(d->m_date.addDays(offset)); break; case QDateTimeEdit::MonthSection: slotDateChosen(d->m_date.addMonths(offset)); break; case QDateTimeEdit::YearSection: slotDateChosen(d->m_date.addYears(offset)); break; default: break; } }; switch (k->key()) { case Qt::Key_Equal: case Qt::Key_Plus: adjustDateSection(1); k->accept(); break; case Qt::Key_Minus: adjustDateSection(-1); k->accept(); break; default: if (today == QKeySequence(k->key()) || k->key() == Qt::Key_T) { slotDateChosen(QDate::currentDate()); k->accept(); } break; } k->ignore(); // signal that the key event was not handled } /** * This function receives all events that are sent to focusWidget(). * Some KeyPress events are intercepted and passed to keyPressEvent. * Otherwise they would be consumed by QDateEdit. */ bool KMyMoneyDateInput::eventFilter(QObject *, QEvent *e) { if (e->type() == QEvent::FocusIn) { #ifndef Q_OS_MAC d->m_datePopup->show(mapToGlobal(QPoint(0, height()))); #endif // select the date section, but we need to delay it a bit } else if (e->type() == QEvent::FocusOut) { #ifndef Q_OS_MAC d->m_datePopup->hide(); #endif } else if (e->type() == QEvent::KeyPress) { if (QKeyEvent *k = dynamic_cast(e)) { keyPressEvent(k); if (k->isAccepted()) return true; // signal that the key event was handled } } return false; // Don't filter the event } void KMyMoneyDateInput::slotDateChosenRef(const QDate& date) { if (date.isValid()) { emit dateChanged(date); d->m_date = date; #ifndef Q_OS_MAC QLabel *lbl = static_cast(d->m_datePopup->view()); lbl->setText(QLocale().toString(date)); lbl->adjustSize(); if (d->m_datePopup->isVisible() || hasFocus()) d->m_datePopup->show(mapToGlobal(QPoint(0, height()))); // Repaint #endif } } void KMyMoneyDateInput::slotDateChosen(QDate date) { if (date.isValid()) { // the next line implies a call to slotDateChosenRef() above d->m_dateEdit->setDate(date); } else { d->m_dateEdit->setDate(INVALID_DATE); } } QDate KMyMoneyDateInput::date() const { QDate rc = d->m_dateEdit->date(); if (rc == INVALID_DATE) rc = QDate(); return rc; } void KMyMoneyDateInput::setDate(QDate date) { slotDateChosen(date); } void KMyMoneyDateInput::loadDate(const QDate& date) { d->m_date = d->m_prevDate = date; blockSignals(true); slotDateChosen(date); blockSignals(false); } void KMyMoneyDateInput::resetDate() { setDate(d->m_prevDate); } void KMyMoneyDateInput::setMaximumDate(const QDate& max) { d->m_dateEdit->setMaximumDate(max); } QWidget* KMyMoneyDateInput::focusWidget() const { QWidget* w = d->m_dateEdit; while (w->focusProxy()) w = w->focusProxy(); return w; } /* void KMyMoneyDateInput::setRange(const QDate & min, const QDate & max) { d->m_dateEdit->setDateRange(min, max); } */ diff --git a/kmymoney/widgets/kmymoneydateinput.h b/kmymoney/widgets/kmymoneydateinput.h index 5f5fd751d..e1bfa37e6 100644 --- a/kmymoney/widgets/kmymoneydateinput.h +++ b/kmymoney/widgets/kmymoneydateinput.h @@ -1,153 +1,156 @@ /* * Copyright 2000-2003 Michael Edwardes * Copyright 2001 Felix Rodriguez * 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 . */ #ifndef KMYMONEYDATEINPUT_H #define KMYMONEYDATEINPUT_H // ---------------------------------------------------------------------------- // QT Includes #include #include #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "kmm_widgets_export.h" // Ideas neatly taken from korganizer // Respective authors are credited. // Some ideas/code have been borrowed from Calendar-0.13 (phoenix.bmedesign.com/~qt) namespace KMyMoney { /** * Provided to be able to catch the focusOut events before the contents gets changed */ class OldDateEdit : public QDateEdit { Q_OBJECT public: explicit OldDateEdit(const QDate& date, QWidget* parent = nullptr); + void setInitialSection(Section section) { m_initialSection = section; } protected: /** if the date was cleared (a state which is not supported by QDateEdit) * make sure that a date can be entered again */ void keyPressEvent(QKeyEvent* k) final override; /** reimplemented for internal reasons */ bool event(QEvent* e) final override; /** reimplemented for internal reasons */ bool focusNextPrevChild(bool next) final override; /** reimplemented for internal reasons */ void focusInEvent(QFocusEvent *event) final override; + private: + QDateEdit::Section m_initialSection; }; }; // namespace /** * This class provides the general widget used for date selection * throughout the KMyMoney project. It provides an QDateEdit widget * which is based on an edit field with spin boxes and adds a QPushButton * to open a KDatePicker. */ class KMM_WIDGETS_EXPORT KMyMoneyDateInput : public QWidget { Q_OBJECT Q_PROPERTY(QDate date READ date WRITE setDate STORED false) public: explicit KMyMoneyDateInput(QWidget* parent = nullptr, Qt::AlignmentFlag flags = Qt::AlignLeft); ~KMyMoneyDateInput(); /** * Returns the selected date in the widget. If the widget is not * showing a date, a QDate() object is returned which has an invalid date. */ QDate date() const; /** * Set the date shown in the widget to @a date. If @a date is invalid, * no text will be shown. The internal widget will use 1.1.1800 for this * special case, as the standard QDateEdit widget does not support an * invalid date as of Qt4 anymore, but we need it anyway for multi transaction * edit. */ void setDate(QDate date); void setMaximumDate(const QDate& max); /** * Setup the widget with @a date. This date is stored internally and * can be reloaded using resetDate(). * * @sa setDate, resetDate */ void loadDate(const QDate& date); /** * Setup the widget with the date loaded using loadDate(). * * @sa loadDate */ void resetDate(); QWidget* focusWidget() const; void setRange(const QDate & min, const QDate & max); void markAsBadDate(bool bad = false, const QColor& = QColor()); Q_SIGNALS: void dateChanged(const QDate& date); protected: /** * - increments/decrements the date upon +/- key input * - increments/decrements the date upon Up/Down key input * - sets the date to current date when the 'T' key is pressed. * The actual key for this to happen might be overridden through * an i18n package. The 'T'-key is always possible. */ void keyPressEvent(QKeyEvent* k) override; void showEvent(QShowEvent* event) override; /** To intercept events sent to focusWidget() */ bool eventFilter(QObject *o, QEvent *e) override; protected Q_SLOTS: void slotDateChosen(QDate date); void toggleDatePicker(); private Q_SLOTS: void slotDateChosenRef(const QDate& date); void fixSize(); private: struct Private; Private * const d; }; #endif