You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
10 KiB
349 lines
10 KiB
/***************************************************************************
|
|
kmymoneydateinput.cpp
|
|
-------------------
|
|
copyright : (C) 2000 by Michael Edwardes
|
|
email : mte@users.sourceforge.net
|
|
ipwizard@users.sourceforge.net
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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 <tqpainter.h>
|
|
#include <tqdrawutil.h>
|
|
#include <tqpoint.h>
|
|
#include <tqvalidator.h>
|
|
#include <tqtimer.h>
|
|
#include <tqstyle.h>
|
|
#include <tqlayout.h>
|
|
#include <tqapplication.h>
|
|
#include <tqdesktopwidget.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqtimer.h>
|
|
#include <tqlabel.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(TQEvent* e)
|
|
{
|
|
// make sure that we keep the current date setting of a kMyMoneyDateInput object
|
|
// across the TQDateEdit::event(FocusOutEvent)
|
|
bool rc;
|
|
|
|
kMyMoneyDateInput* p = dynamic_cast<kMyMoneyDateInput*>(parentWidget());
|
|
if(e->type() == TQEvent::FocusOut && p) {
|
|
TQDate d = p->date();
|
|
rc = TQDateEdit::event(e);
|
|
if(d.isValid())
|
|
d = p->date();
|
|
p->loadDate(d);
|
|
} else {
|
|
rc = TQDateEdit::event(e);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
kMyMoneyDateInput::kMyMoneyDateInput(TQWidget *parent, const char *name, TQt::AlignmentFlags flags)
|
|
: TQHBox(parent,name)
|
|
{
|
|
m_qttqalignment = flags;
|
|
m_date = TQDate::tqcurrentDate();
|
|
|
|
dateEdit = new KMyMoneyDateEdit(m_date, this, "dateEdit");
|
|
setFocusProxy(dateEdit);
|
|
tqfocusWidget()->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 TQLabel(KGlobal::locale()->formatDate(m_date), m_datePopup, "datePopupLabel"));
|
|
|
|
m_dateFrame = new TQVBox(this, 0, WType_Popup);
|
|
m_dateFrame->setFrameStyle(TQFrame::PopupPanel | TQFrame::Raised);
|
|
m_dateFrame->setLineWidth(3);
|
|
m_dateFrame->hide();
|
|
|
|
TQString dateFormat = KGlobal::locale()->dateFormatShort().lower();
|
|
TQString 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(TQDateEdit::MDY);
|
|
m_focusDatePart = 1;
|
|
} else if(order == "dmy") {
|
|
dateEdit->setOrder(TQDateEdit::DMY);
|
|
m_focusDatePart = 0;
|
|
} else if(order == "ydm") {
|
|
dateEdit->setOrder(TQDateEdit::YDM);
|
|
m_focusDatePart = 1;
|
|
} else {
|
|
dateEdit->setOrder(TQDateEdit::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(TQIconSet(TQPixmap(KGlobal::iconLoader()->iconPath("date", -KIcon::SizeSmall))), TQString(""), this);
|
|
m_dateButton->setMinimumWidth(30);
|
|
|
|
connect(m_dateButton,TQT_SIGNAL(clicked()),TQT_SLOT(toggleDatePicker()));
|
|
connect(dateEdit, TQT_SIGNAL(valueChanged(const TQDate&)), this, TQT_SLOT(slotDateChosenRef(const TQDate&)));
|
|
connect(m_datePicker, TQT_SIGNAL(dateSelected(TQDate)), this, TQT_SLOT(slotDateChosen(TQDate)));
|
|
connect(m_datePicker, TQT_SIGNAL(dateEntered(TQDate)), this, TQT_SLOT(slotDateChosen(TQDate)));
|
|
connect(m_datePicker, TQT_SIGNAL(dateSelected(TQDate)), m_dateFrame, TQT_SLOT(hide()));
|
|
}
|
|
|
|
void kMyMoneyDateInput::markAsBadDate(bool bad, const TQColor& color)
|
|
{
|
|
if(dateEdit->focusProxy()) {
|
|
TQT_TQWIDGET(dateEdit->focusProxy())->setPaletteForegroundColor(paletteForegroundColor());
|
|
if(bad)
|
|
TQT_TQWIDGET(dateEdit->focusProxy())->setPaletteForegroundColor(color);
|
|
}
|
|
}
|
|
|
|
void kMyMoneyDateInput::show(void)
|
|
{
|
|
// don't forget the standard behaviour ;-)
|
|
TQHBox::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.
|
|
TQTimer::singleShot(50, this, TQT_SLOT(fixSize()));
|
|
}
|
|
|
|
void kMyMoneyDateInput::fixSize(void)
|
|
{
|
|
// According to a hint in the documentation of KDatePicker::tqsizeHint()
|
|
// 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->tqsizeHint() + TQSize(22, 14));
|
|
|
|
dateEdit->setMinimumWidth(dateEdit->tqminimumSizeHint().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
|
|
{
|
|
TQPoint tmpPoint = mapToGlobal(m_dateButton->tqgeometry().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 > TQApplication::desktop()->height()) {
|
|
tmpPoint.setY(tmpPoint.y() - h - m_dateButton->height());
|
|
}
|
|
|
|
if((m_qttqalignment == TQt::AlignRight && tmpPoint.x()+w <= TQApplication::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(TQDate::tqcurrentDate());
|
|
}
|
|
m_dateFrame->show();
|
|
}
|
|
}
|
|
|
|
|
|
void kMyMoneyDateInput::resizeEvent(TQResizeEvent* 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 TQWidget::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(TQKeyEvent * 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(TQDate::tqcurrentDate());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function receives all events that are sent to tqfocusWidget().
|
|
* Some KeyPress events are intercepted and passed to keyPressEvent.
|
|
* Otherwise they would be consumed by TQDateEdit.
|
|
*/
|
|
bool kMyMoneyDateInput::eventFilter(TQObject *, TQEvent *e)
|
|
{
|
|
if (e->type() == TQEvent::FocusIn) {
|
|
m_datePopup->show();
|
|
// The cast to the base class is needed since setFocusSection
|
|
// is protected in TQDateEdit. This causes some logic in
|
|
// TQDateEdit::setFocusSection not to be executed but this does
|
|
// not hurt here, because the widget just receives focus.
|
|
static_cast<TQDateTimeEditBase *>(dateEdit)->setFocusSection(m_focusDatePart);
|
|
}
|
|
else if (e->type() == TQEvent::FocusOut)
|
|
m_datePopup->hide();
|
|
else if (e->type() == TQEvent::KeyPress) {
|
|
if (TQKeyEvent *k = dynamic_cast<TQKeyEvent*>(e)) {
|
|
if (k->key() == Key_Minus) {
|
|
keyPressEvent(k);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false; // Don't filter the event
|
|
}
|
|
|
|
void kMyMoneyDateInput::slotDateChosenRef(const TQDate& date)
|
|
{
|
|
if(date.isValid()) {
|
|
emit dateChanged(date);
|
|
m_date = date;
|
|
|
|
TQLabel *lbl = static_cast<TQLabel*>(m_datePopup->view());
|
|
lbl->setText(KGlobal::locale()->formatDate(date));
|
|
lbl->adjustSize();
|
|
if(m_datePopup->isVisible() || hasFocus())
|
|
m_datePopup->show(); // Repaint
|
|
}
|
|
}
|
|
|
|
void kMyMoneyDateInput::slotDateChosen(TQDate date)
|
|
{
|
|
if(date.isValid()) {
|
|
// the next line implies a call to slotDateChosenRef() above
|
|
dateEdit->setDate(date);
|
|
}
|
|
}
|
|
|
|
TQDate kMyMoneyDateInput::date(void) const
|
|
{
|
|
return dateEdit->date();
|
|
}
|
|
|
|
void kMyMoneyDateInput::setDate(TQDate date)
|
|
{
|
|
slotDateChosen(date);
|
|
}
|
|
|
|
void kMyMoneyDateInput::loadDate(const TQDate& date)
|
|
{
|
|
m_date = m_prevDate = date;
|
|
|
|
blockSignals(true);
|
|
dateEdit->setDate(date);
|
|
m_date = date;
|
|
blockSignals(false);
|
|
}
|
|
|
|
void kMyMoneyDateInput::resetDate(void)
|
|
{
|
|
setDate(m_prevDate);
|
|
}
|
|
|
|
TQWidget* kMyMoneyDateInput::tqfocusWidget(void) const
|
|
{
|
|
TQWidget* w = dateEdit;
|
|
while(w->focusProxy())
|
|
w = TQT_TQWIDGET(w->focusProxy());
|
|
return w;
|
|
}
|
|
|
|
#include "kmymoneydateinput.moc"
|