libkdepim Library API Documentation

kdateedit.cpp

00001 /* 00002 This file is part of libkdepim. 00003 00004 Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #include <qevent.h> 00023 #include <qlineedit.h> 00024 #include <qapplication.h> 00025 #include <qlistbox.h> 00026 00027 #include <kdatepicker.h> 00028 #include <knotifyclient.h> 00029 #include <kglobalsettings.h> 00030 #include <kdebug.h> 00031 #include <kglobal.h> 00032 #include <klocale.h> 00033 #include <kcalendarsystem.h> 00034 00035 #include "kdateedit.h" 00036 #include "kdateedit.moc" 00037 00038 00039 KDateEdit::KDateEdit(QWidget *parent, const char *name) 00040 : QComboBox(true, parent, name), 00041 defaultValue(QDate::currentDate()), 00042 mReadOnly(false), 00043 mDiscardNextMousePress(false) 00044 { 00045 setMaxCount(1); // need at least one entry for popup to work 00046 value = defaultValue; 00047 QString today = KGlobal::locale()->formatDate(value, true); 00048 insertItem(today); 00049 setCurrentItem(0); 00050 changeItem(today, 0); 00051 setMinimumSize(sizeHint()); 00052 00053 mDateFrame = new QVBox(0,0,WType_Popup); 00054 mDateFrame->setFrameStyle(QFrame::PopupPanel | QFrame::Raised); 00055 mDateFrame->setLineWidth(3); 00056 mDateFrame->hide(); 00057 mDateFrame->installEventFilter(this); 00058 00059 mDatePicker = new KDatePicker(mDateFrame, value); 00060 00061 connect(lineEdit(),SIGNAL(returnPressed()),SLOT(lineEnterPressed())); 00062 connect(this,SIGNAL(textChanged(const QString &)), 00063 SLOT(slotTextChanged(const QString &))); 00064 00065 connect(mDatePicker,SIGNAL(dateEntered(QDate)),SLOT(dateEntered(QDate))); 00066 connect(mDatePicker,SIGNAL(dateSelected(QDate)),SLOT(dateSelected(QDate))); 00067 00068 // Create the keyword list. This will be used to match against when the user 00069 // enters information. 00070 mKeywordMap[i18n("tomorrow")] = 1; 00071 mKeywordMap[i18n("today")] = 0; 00072 mKeywordMap[i18n("yesterday")] = -1; 00073 00074 QString dayName; 00075 for (int i = 1; i <= 7; ++i) 00076 { 00077 dayName = KGlobal::locale()->calendar()->weekDayName(i).lower(); 00078 mKeywordMap[dayName] = i + 100; 00079 } 00080 lineEdit()->installEventFilter(this); // handle keyword entry 00081 00082 mTextChanged = false; 00083 mHandleInvalid = false; 00084 } 00085 00086 KDateEdit::~KDateEdit() 00087 { 00088 delete mDateFrame; 00089 } 00090 00091 void KDateEdit::setDate(const QDate& newDate) 00092 { 00093 if (!newDate.isValid() && !mHandleInvalid) 00094 return; 00095 00096 QString dateString = ""; 00097 if(newDate.isValid()) 00098 dateString = KGlobal::locale()->formatDate( newDate, true ); 00099 00100 mTextChanged = false; 00101 00102 // We do not want to generate a signal here, since we explicitly setting 00103 // the date 00104 bool b = signalsBlocked(); 00105 blockSignals(true); 00106 changeItem(dateString, 0); 00107 blockSignals(b); 00108 00109 value = newDate; 00110 } 00111 00112 void KDateEdit::setHandleInvalid(bool handleInvalid) 00113 { 00114 mHandleInvalid = handleInvalid; 00115 } 00116 00117 bool KDateEdit::handlesInvalid() const 00118 { 00119 return mHandleInvalid; 00120 } 00121 00122 void KDateEdit::setReadOnly(bool readOnly) 00123 { 00124 mReadOnly = readOnly; 00125 lineEdit()->setReadOnly(readOnly); 00126 } 00127 00128 bool KDateEdit::isReadOnly() const 00129 { 00130 return mReadOnly; 00131 } 00132 00133 bool KDateEdit::validate( const QDate & ) 00134 { 00135 return true; 00136 } 00137 00138 QDate KDateEdit::date() const 00139 { 00140 QDate dt; 00141 if (readDate(dt) && (mHandleInvalid || dt.isValid())) { 00142 return dt; 00143 } 00144 return defaultValue; 00145 } 00146 00147 QDate KDateEdit::defaultDate() const 00148 { 00149 return defaultValue; 00150 } 00151 00152 void KDateEdit::setDefaultDate(const QDate& date) 00153 { 00154 defaultValue = date; 00155 } 00156 00157 void KDateEdit::popup() 00158 { 00159 if (mReadOnly) 00160 return; 00161 00162 QRect desk = KGlobalSettings::desktopGeometry(this); 00163 00164 QPoint popupPoint = mapToGlobal( QPoint( 0,0 ) ); 00165 00166 int dateFrameHeight = mDateFrame->sizeHint().height(); 00167 if ( popupPoint.y() + height() + dateFrameHeight > desk.bottom() ) { 00168 popupPoint.setY( popupPoint.y() - dateFrameHeight ); 00169 } else { 00170 popupPoint.setY( popupPoint.y() + height() ); 00171 } 00172 int dateFrameWidth = mDateFrame->sizeHint().width(); 00173 if ( popupPoint.x() + dateFrameWidth > desk.right() ) { 00174 popupPoint.setX( desk.right() - dateFrameWidth ); 00175 } 00176 00177 if ( popupPoint.x() < desk.left() ) popupPoint.setX( desk.left() ); 00178 if ( popupPoint.y() < desk.top() ) popupPoint.setY( desk.top() ); 00179 00180 mDateFrame->move( popupPoint ); 00181 00182 QDate date; 00183 readDate(date); 00184 if (date.isValid()) { 00185 mDatePicker->setDate( date ); 00186 } else { 00187 mDatePicker->setDate( defaultValue ); 00188 } 00189 00190 mDateFrame->show(); 00191 00192 // The combo box is now shown pressed. Make it show not pressed again 00193 // by causing its (invisible) list box to emit a 'selected' signal. 00194 QListBox *lb = listBox(); 00195 if (lb) { 00196 lb->setCurrentItem(0); 00197 QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, 0, 0); 00198 QApplication::postEvent(lb, keyEvent); 00199 } 00200 } 00201 00202 void KDateEdit::dateSelected(QDate newDate) 00203 { 00204 if ((mHandleInvalid || newDate.isValid()) && validate(newDate)) { 00205 setDate(newDate); 00206 emit dateChanged(newDate); 00207 mDateFrame->hide(); 00208 } 00209 } 00210 00211 void KDateEdit::dateEntered(QDate newDate) 00212 { 00213 if ((mHandleInvalid || newDate.isValid()) && validate(newDate)) { 00214 setDate(newDate); 00215 emit dateChanged(newDate); 00216 } 00217 } 00218 00219 void KDateEdit::lineEnterPressed() 00220 { 00221 QDate date; 00222 if (readDate(date) && (mHandleInvalid || date.isValid()) && validate(date)) 00223 { 00224 // Update the edit. This is needed if the user has entered a 00225 // word rather than the actual date. 00226 setDate(date); 00227 emit(dateChanged(date)); 00228 } 00229 else { 00230 // Invalid or unacceptable date - revert to previous value 00231 KNotifyClient::beep(); 00232 setDate(value); 00233 emit invalidDateEntered(); 00234 } 00235 } 00236 00237 bool KDateEdit::inputIsValid() const 00238 { 00239 QDate date; 00240 return readDate(date) && date.isValid(); 00241 } 00242 00243 /* Reads the text from the line edit. If the text is a keyword, the 00244 * word will be translated to a date. If the text is not a keyword, the 00245 * text will be interpreted as a date. 00246 * Returns true if the date text is blank or valid, false otherwise. 00247 */ 00248 bool KDateEdit::readDate(QDate& result) const 00249 { 00250 QString text = currentText(); 00251 00252 if (text.isEmpty()) { 00253 result = QDate(); 00254 } 00255 else if (mKeywordMap.contains(text.lower())) 00256 { 00257 QDate today = QDate::currentDate(); 00258 int i = mKeywordMap[text.lower()]; 00259 if (i >= 100) 00260 { 00261 /* A day name has been entered. Convert to offset from today. 00262 * This uses some math tricks to figure out the offset in days 00263 * to the next date the given day of the week occurs. There 00264 * are two cases, that the new day is >= the current day, which means 00265 * the new day has not occurred yet or that the new day < the current day, 00266 * which means the new day is already passed (so we need to find the 00267 * day in the next week). 00268 */ 00269 i -= 100; 00270 int currentDay = today.dayOfWeek(); 00271 if (i >= currentDay) 00272 i -= currentDay; 00273 else 00274 i += 7 - currentDay; 00275 } 00276 result = today.addDays(i); 00277 } 00278 else 00279 { 00280 result = KGlobal::locale()->readDate(text); 00281 return result.isValid(); 00282 } 00283 00284 return true; 00285 } 00286 00287 /* Checks for a focus out event. The display of the date is updated 00288 * to display the proper date when the focus leaves. 00289 */ 00290 bool KDateEdit::eventFilter(QObject *obj, QEvent *e) 00291 { 00292 if (obj == lineEdit()) { 00293 // We only process the focus out event if the text has changed 00294 // since we got focus 00295 if ((e->type() == QEvent::FocusOut) && mTextChanged) 00296 { 00297 lineEnterPressed(); 00298 mTextChanged = false; 00299 } 00300 else if (e->type() == QEvent::KeyPress) 00301 { 00302 // Up and down arrow keys step the date 00303 QKeyEvent* ke = (QKeyEvent*)e; 00304 00305 if (ke->key() == Qt::Key_Return) 00306 { 00307 lineEnterPressed(); 00308 return true; 00309 } 00310 00311 int step = 0; 00312 if (ke->key() == Qt::Key_Up) 00313 step = 1; 00314 else if (ke->key() == Qt::Key_Down) 00315 step = -1; 00316 if (step && !mReadOnly) 00317 { 00318 QDate date; 00319 if (readDate(date) && date.isValid()) { 00320 date = date.addDays(step); 00321 if (validate(date)) { 00322 setDate(date); 00323 emit(dateChanged(date)); 00324 return true; 00325 } 00326 } 00327 } 00328 } 00329 } 00330 else { 00331 // It's a date picker event 00332 switch (e->type()) { 00333 case QEvent::MouseButtonDblClick: 00334 case QEvent::MouseButtonPress: { 00335 QMouseEvent *me = (QMouseEvent*)e; 00336 if (!mDateFrame->rect().contains(me->pos())) { 00337 QPoint globalPos = mDateFrame->mapToGlobal(me->pos()); 00338 if (QApplication::widgetAt(globalPos, true) == this) { 00339 // The date picker is being closed by a click on the 00340 // KDateEdit widget. Avoid popping it up again immediately. 00341 mDiscardNextMousePress = true; 00342 } 00343 } 00344 break; 00345 } 00346 default: 00347 break; 00348 } 00349 } 00350 00351 return false; 00352 } 00353 00354 void KDateEdit::mousePressEvent(QMouseEvent *e) 00355 { 00356 if (e->button() == Qt::LeftButton && mDiscardNextMousePress) { 00357 mDiscardNextMousePress = false; 00358 return; 00359 } 00360 QComboBox::mousePressEvent(e); 00361 } 00362 00363 void KDateEdit::slotTextChanged(const QString &) 00364 { 00365 mTextChanged = true; 00366 }
KDE Logo
This file is part of the documentation for libkdepim Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:29 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003