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.
tellico/src/gui/datewidget.cpp

280 lines
8.4 KiB

/***************************************************************************
copyright : (C) 2003-2006 by Robby Stephenson
email : robby@periapsis.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of version 2 of the GNU General Public License as *
* published by the Free Software Foundation; *
* *
***************************************************************************/
// this class borrows heavily from kdateedit.h in the tdepim module
// which is Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org>
// and published under the LGPL
#include "datewidget.h"
#include <kdebug.h>
#include <kcombobox.h>
#include <kpushbutton.h>
#include <kdatepicker.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdeglobalsettings.h>
#include <kcalendarsystem.h>
#include <tqvbox.h>
#include <tqlayout.h>
using Tellico::GUI::SpinBox;
using Tellico::GUI::DateWidget;
SpinBox::SpinBox(int min, int max, TQWidget *parent) : TQSpinBox(min, max, 1, parent)
{
editor()->setAlignment(AlignRight);
// I want to be able to omit the day
// an empty string just removes the special value, so set white space
setSpecialValueText(TQChar(' '));
}
DateWidget::DateWidget(TQWidget* parent_, const char* name_) : TQWidget(parent_, name_) {
TQHBoxLayout* l = new TQHBoxLayout(this, 0, 4);
TDELocale* locale = TDEGlobal::locale();
// 0 allows empty value
m_daySpin = new SpinBox(0, 31, this);
l->addWidget(m_daySpin, 1);
m_monthCombo = new KComboBox(false, this);
l->addWidget(m_monthCombo, 1);
// allow empty item
m_monthCombo->insertItem(TQString());
TQDate d;
for(int i = 1; ; ++i) {
TQString str = locale->calendar()->monthName(i, locale->calendar()->year(d));
if(str.isNull()) {
break;
}
m_monthCombo->insertItem(str);
}
m_yearSpin = new SpinBox(locale->calendar()->minValidYear(),
locale->calendar()->maxValidYear(), this);
l->addWidget(m_yearSpin, 1);
connect(m_daySpin, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(slotDateChanged()));
connect(m_monthCombo, TQ_SIGNAL(activated(int)), TQ_SLOT(slotDateChanged()));
connect(m_yearSpin, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(slotDateChanged()));
m_dateButton = new KPushButton(this);
m_dateButton->setIconSet(SmallIconSet(TQString::fromLatin1("date")));
connect(m_dateButton, TQ_SIGNAL(clicked()), TQ_SLOT(slotShowPicker()));
l->addWidget(m_dateButton, 0);
m_frame = new TQVBox(0, 0, WType_Popup);
m_frame->setFrameStyle(TQFrame::PopupPanel | TQFrame::Raised);
m_frame->setLineWidth(3);
m_frame->hide();
m_picker = new KDatePicker(m_frame, 0); // must include name to get correct constructor
connect(m_picker, TQ_SIGNAL(dateEntered(TQDate)), TQ_SLOT(slotDateEntered(TQDate)));
connect(m_picker, TQ_SIGNAL(dateSelected(TQDate)), TQ_SLOT(slotDateSelected(TQDate)));
}
void DateWidget::slotDateChanged() {
int day = m_daySpin->value();
day = TQMIN(TQMAX(day, m_daySpin->minValue()), m_daySpin->maxValue());
int m = m_monthCombo->currentItem();
m = TQMIN(TQMAX(m, 0), m_monthCombo->count()-1);
int y = m_yearSpin->value();
y = TQMIN(TQMAX(y, m_yearSpin->minValue()), m_yearSpin->maxValue());
// if all are valid, set this date
if(day > m_daySpin->minValue() && m > 0 && y > m_yearSpin->minValue()) {
TQDate d(y, m, day);
setDate(d);
}
emit signalModified();
}
TQDate DateWidget::date() const {
// possible for either day, month, or year to be empty
// in which case a null date is returned
int day = m_daySpin->value();
// min value is the empty one
if(day == m_daySpin->minValue()) {
return TQDate();
}
int month = m_monthCombo->currentItem();
if(month == 0) {
return TQDate();
}
int year = m_yearSpin->value();
if(year == m_yearSpin->minValue()) {
return TQDate();
}
return TQDate(year, month, day);
}
TQString DateWidget::text() const {
// possible for either day, month, or year to be empty
// but not all three
bool empty = true;
// format is "year-month-day"
TQString s;
if(m_yearSpin->value() > m_yearSpin->minValue()) {
s += TQString::number(m_yearSpin->value());
empty = false;
}
s += '-';
// first item is empty
if(m_monthCombo->currentItem() > 0) {
s += TQString::number(m_monthCombo->currentItem());
empty = false;
}
s += '-';
if(m_daySpin->value() > m_daySpin->minValue()) {
s += TQString::number(m_daySpin->value());
empty = false;
}
return empty ? TQString() : s;
}
void DateWidget::setDate(const TQDate& date_) {
m_daySpin->blockSignals(true);
m_monthCombo->blockSignals(true);
m_yearSpin->blockSignals(true);
const KCalendarSystem * calendar = TDEGlobal::locale()->calendar();
m_daySpin->setMaxValue(calendar->daysInMonth(date_));
m_daySpin->setValue(calendar->day(date_));
m_monthCombo->setCurrentItem(calendar->month(date_)); // don't subtract 1 since there's the blank first item
m_yearSpin->setValue(calendar->year(date_));
m_daySpin->blockSignals(false);
m_monthCombo->blockSignals(false);
m_yearSpin->blockSignals(false);
}
void DateWidget::setDate(const TQString& date_) {
m_daySpin->blockSignals(true);
m_monthCombo->blockSignals(true);
m_yearSpin->blockSignals(true);
TQStringList s = TQStringList::split('-', date_, true);
bool ok = true;
int y = s.count() > 0 ? s[0].toInt(&ok) : m_yearSpin->minValue();
if(!ok) {
y = m_yearSpin->minValue();
ok = true;
}
y = TQMIN(TQMAX(y, m_yearSpin->minValue()), m_yearSpin->maxValue());
m_yearSpin->setValue(y);
int m = s.count() > 1 ? s[1].toInt(&ok) : 0;
if(!ok) {
m = 0;
ok = true;
}
m = TQMIN(TQMAX(m, 0), m_monthCombo->count()-1);
m_monthCombo->setCurrentItem(m);
// need to update number of days in month
// for now set date to 1
TQDate date(y, (m == 0 ? 1 : m), 1);
m_daySpin->blockSignals(true);
m_daySpin->setMaxValue(TDEGlobal::locale()->calendar()->daysInMonth(date));
m_daySpin->blockSignals(false);
int day = s.count() > 2 ? s[2].toInt(&ok) : m_daySpin->minValue();
if(!ok) {
day = m_daySpin->minValue();
}
day = TQMIN(TQMAX(day, m_daySpin->minValue()), m_daySpin->maxValue());
m_daySpin->setValue(day);
m_daySpin->blockSignals(false);
m_monthCombo->blockSignals(false);
m_yearSpin->blockSignals(false);
// if all are valid, set this date
if(day > m_daySpin->minValue() && m > 0 && y > m_yearSpin->minValue()) {
TQDate d(y, m, day);
m_picker->blockSignals(true);
m_picker->setDate(d);
m_picker->blockSignals(false);
}
}
void DateWidget::clear() {
m_daySpin->blockSignals(true);
m_monthCombo->blockSignals(true);
m_yearSpin->blockSignals(true);
m_picker->blockSignals(true);
m_daySpin->setValue(m_daySpin->minValue());
m_monthCombo->setCurrentItem(0);
m_yearSpin->setValue(m_yearSpin->minValue());
m_picker->setDate(TQDate::currentDate());
m_daySpin->blockSignals(false);
m_monthCombo->blockSignals(false);
m_yearSpin->blockSignals(false);
m_picker->blockSignals(false);
}
void DateWidget::slotShowPicker() {
TQRect desk = TDEGlobalSettings::desktopGeometry(this);
TQPoint popupPoint = mapToGlobal(TQPoint(0, 0));
int dateFrameHeight = m_frame->sizeHint().height();
if(popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
popupPoint.setY(popupPoint.y() - dateFrameHeight);
} else {
popupPoint.setY(popupPoint.y() + height());
}
int dateFrameWidth = m_frame->sizeHint().width();
if(popupPoint.x() + dateFrameWidth > desk.right()) {
popupPoint.setX(desk.right() - dateFrameWidth);
}
if(popupPoint.x() < desk.left()) {
popupPoint.setX( desk.left());
}
if(popupPoint.y() < desk.top()) {
popupPoint.setY(desk.top());
}
m_frame->move(popupPoint);
TQDate d = date();
if(d.isValid()) {
m_picker->setDate(d);
}
m_frame->show();
}
void DateWidget::slotDateSelected(TQDate date_) {
if(date_.isValid()) {
setDate(date_);
emit signalModified();
m_frame->hide();
}
}
void DateWidget::slotDateEntered(TQDate date_) {
if(date_.isValid()) {
setDate(date_);
emit signalModified();
}
}
#include "datewidget.moc"