summaryrefslogtreecommitdiffstats
path: root/kmymoney2/widgets/kmymoneydateinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmymoney2/widgets/kmymoneydateinput.cpp')
-rw-r--r--kmymoney2/widgets/kmymoneydateinput.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/kmymoney2/widgets/kmymoneydateinput.cpp b/kmymoney2/widgets/kmymoneydateinput.cpp
new file mode 100644
index 0000000..e1b4be8
--- /dev/null
+++ b/kmymoney2/widgets/kmymoneydateinput.cpp
@@ -0,0 +1,348 @@
+/***************************************************************************
+ kmymoneydateinput.cpp
+ -------------------
+ copyright : (C) 2000 by Michael Edwardes
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// ----------------------------------------------------------------------------
+// QT Includes
+
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qpoint.h>
+#include <qvalidator.h>
+#include <qtimer.h>
+#include <qstyle.h>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qlabel.h>
+
+// ----------------------------------------------------------------------------
+// KDE Includes
+#include "kdecompat.h"
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kshortcut.h>
+#include <kpassivepopup.h>
+
+// ----------------------------------------------------------------------------
+// Project Includes
+
+#include "kmymoneydateinput.h"
+
+namespace {
+ const int DATE_POPUP_TIMEOUT = 1500;
+}
+
+bool KMyMoneyDateEdit::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<kMyMoneyDateInput*>(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;
+}
+
+kMyMoneyDateInput::kMyMoneyDateInput(QWidget *parent, const char *name, Qt::AlignmentFlags flags)
+ : QHBox(parent,name)
+{
+ m_qtalignment = flags;
+ m_date = QDate::currentDate();
+
+ dateEdit = new KMyMoneyDateEdit(m_date, this, "dateEdit");
+ setFocusProxy(dateEdit);
+ focusWidget()->installEventFilter(this); // To get dateEdit's FocusIn/Out and some KeyPress events
+ dateEdit->installEventFilter(this); // To get dateEdit's FocusIn/Out and some KeyPress events
+
+ m_datePopup = new KPassivePopup(dateEdit, "datePopup");
+ m_datePopup->setTimeout(DATE_POPUP_TIMEOUT);
+ m_datePopup->setView(new QLabel(KGlobal::locale()->formatDate(m_date), m_datePopup, "datePopupLabel"));
+
+ m_dateFrame = new QVBox(this, 0, WType_Popup);
+ m_dateFrame->setFrameStyle(QFrame::PopupPanel | QFrame::Raised);
+ m_dateFrame->setLineWidth(3);
+ m_dateFrame->hide();
+
+ QString dateFormat = KGlobal::locale()->dateFormatShort().lower();
+ QString order, separator;
+ for(unsigned i = 0; i < dateFormat.length(); ++i) {
+ // DD.MM.YYYY is %d.%m.%y
+ // dD.mM.YYYY is %e.%n.%y
+ // SHORTWEEKDAY, dD SHORTMONTH YYYY is %a, %e %b %Y
+ if(dateFormat[i] == 'y' || dateFormat[i] == 'm' || dateFormat[i] == 'n' || dateFormat[i] == 'd' || dateFormat[i] == 'e') {
+ if(dateFormat[i] == 'n')
+ dateFormat[i] = 'm';
+ if(dateFormat[i] == 'e')
+ dateFormat[i] = 'd';
+ order += dateFormat[i];
+ } else if(dateFormat[i] != '%' && separator.isEmpty())
+ separator = dateFormat[i];
+ if(order.length() == 3)
+ break;
+ }
+
+ // see if we find a known format. If it's unknown, then we use YMD (international)
+ // set m_focusDatePart to the day position (0-2)
+ if(order == "mdy") {
+ dateEdit->setOrder(QDateEdit::MDY);
+ m_focusDatePart = 1;
+ } else if(order == "dmy") {
+ dateEdit->setOrder(QDateEdit::DMY);
+ m_focusDatePart = 0;
+ } else if(order == "ydm") {
+ dateEdit->setOrder(QDateEdit::YDM);
+ m_focusDatePart = 1;
+ } else {
+ dateEdit->setOrder(QDateEdit::YMD);
+ m_focusDatePart = 2;
+ separator = '-';
+ }
+ dateEdit->setSeparator(separator);
+
+ m_datePicker = new KDatePicker(m_dateFrame, m_date);
+#if KDE_IS_VERSION(3,1,0)
+ // Let the date picker have a close button (Added in 3.1)
+ m_datePicker->setCloseButton(true);
+#endif
+
+ // the next line is a try to add an icon to the button
+ m_dateButton = new KPushButton(QIconSet(QPixmap(KGlobal::iconLoader()->iconPath("date", -KIcon::SizeSmall))), QString(""), this);
+ m_dateButton->setMinimumWidth(30);
+
+ connect(m_dateButton,SIGNAL(clicked()),SLOT(toggleDatePicker()));
+ connect(dateEdit, SIGNAL(valueChanged(const QDate&)), this, SLOT(slotDateChosenRef(const QDate&)));
+ connect(m_datePicker, SIGNAL(dateSelected(QDate)), this, SLOT(slotDateChosen(QDate)));
+ connect(m_datePicker, SIGNAL(dateEntered(QDate)), this, SLOT(slotDateChosen(QDate)));
+ connect(m_datePicker, SIGNAL(dateSelected(QDate)), m_dateFrame, SLOT(hide()));
+}
+
+void kMyMoneyDateInput::markAsBadDate(bool bad, const QColor& color)
+{
+ if(dateEdit->focusProxy()) {
+ dateEdit->focusProxy()->setPaletteForegroundColor(paletteForegroundColor());
+ if(bad)
+ dateEdit->focusProxy()->setPaletteForegroundColor(color);
+ }
+}
+
+void kMyMoneyDateInput::show(void)
+{
+ // don't forget the standard behaviour ;-)
+ QHBox::show();
+
+ // 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(void)
+{
+ // 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)
+ m_dateFrame->setFixedSize(m_datePicker->sizeHint() + QSize(22, 14));
+
+ dateEdit->setMinimumWidth(dateEdit->minimumSizeHint().width() + 6);
+}
+
+kMyMoneyDateInput::~kMyMoneyDateInput()
+{
+ delete m_dateFrame;
+ delete m_datePopup;
+}
+
+void kMyMoneyDateInput::toggleDatePicker()
+{
+ int w = m_dateFrame->width();
+ int h = m_dateFrame->height();
+
+ if(m_dateFrame->isVisible())
+ {
+ m_dateFrame->hide();
+ }
+ else
+ {
+ QPoint tmpPoint = mapToGlobal(m_dateButton->geometry().bottomRight());
+
+ // usually, the datepicker widget is shown underneath the 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 - m_dateButton->height());
+ }
+
+ if((m_qtalignment == Qt::AlignRight && tmpPoint.x()+w <= QApplication::desktop()->width())
+ || (tmpPoint.x()-w < 0) )
+ {
+ m_dateFrame->setGeometry(tmpPoint.x()-width(), tmpPoint.y(), w, h);
+ }
+ else
+ {
+ tmpPoint.setX(tmpPoint.x() - w);
+ m_dateFrame->setGeometry(tmpPoint.x(), tmpPoint.y(), w, h);
+ }
+
+ if(m_date.isValid())
+ {
+ m_datePicker->setDate(m_date);
+ }
+ else
+ {
+ m_datePicker->setDate(QDate::currentDate());
+ }
+ m_dateFrame->show();
+ }
+}
+
+
+void kMyMoneyDateInput::resizeEvent(QResizeEvent* ev)
+{
+ m_dateButton->setMaximumHeight(ev->size().height());
+ m_dateButton->setMaximumWidth(ev->size().height());
+ dateEdit->setMaximumHeight(ev->size().height());
+
+ // qDebug("Received resize-event %d,%d", ev->size().width(), ev->size().height());
+}
+
+
+/** 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)
+{
+ KShortcut today(i18n("Enter todays date into date input widget", "T"));
+
+ switch(k->key()) {
+ case Key_Equal:
+ case Key_Plus:
+ slotDateChosen(m_date.addDays(1));
+ break;
+
+ case Key_Minus:
+ slotDateChosen(m_date.addDays(-1));
+ break;
+
+ default:
+ if(today.contains(KKey(k)) || k->key() == Key_T) {
+ slotDateChosen(QDate::currentDate());
+ }
+ break;
+ }
+}
+
+/**
+ * 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) {
+ m_datePopup->show();
+ // The cast to the base class is needed since setFocusSection
+ // is protected in QDateEdit. This causes some logic in
+ // QDateEdit::setFocusSection not to be executed but this does
+ // not hurt here, because the widget just receives focus.
+ static_cast<QDateTimeEditBase *>(dateEdit)->setFocusSection(m_focusDatePart);
+ }
+ else if (e->type() == QEvent::FocusOut)
+ m_datePopup->hide();
+ else if (e->type() == QEvent::KeyPress) {
+ if (QKeyEvent *k = dynamic_cast<QKeyEvent*>(e)) {
+ if (k->key() == Key_Minus) {
+ keyPressEvent(k);
+ return true;
+ }
+ }
+ }
+
+ return false; // Don't filter the event
+}
+
+void kMyMoneyDateInput::slotDateChosenRef(const QDate& date)
+{
+ if(date.isValid()) {
+ emit dateChanged(date);
+ m_date = date;
+
+ QLabel *lbl = static_cast<QLabel*>(m_datePopup->view());
+ lbl->setText(KGlobal::locale()->formatDate(date));
+ lbl->adjustSize();
+ if(m_datePopup->isVisible() || hasFocus())
+ m_datePopup->show(); // Repaint
+ }
+}
+
+void kMyMoneyDateInput::slotDateChosen(QDate date)
+{
+ if(date.isValid()) {
+ // the next line implies a call to slotDateChosenRef() above
+ dateEdit->setDate(date);
+ }
+}
+
+QDate kMyMoneyDateInput::date(void) const
+{
+ return dateEdit->date();
+}
+
+void kMyMoneyDateInput::setDate(QDate date)
+{
+ slotDateChosen(date);
+}
+
+void kMyMoneyDateInput::loadDate(const QDate& date)
+{
+ m_date = m_prevDate = date;
+
+ blockSignals(true);
+ dateEdit->setDate(date);
+ m_date = date;
+ blockSignals(false);
+}
+
+void kMyMoneyDateInput::resetDate(void)
+{
+ setDate(m_prevDate);
+}
+
+QWidget* kMyMoneyDateInput::focusWidget(void) const
+{
+ QWidget* w = dateEdit;
+ while(w->focusProxy())
+ w = w->focusProxy();
+ return w;
+}
+
+#include "kmymoneydateinput.moc"