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 if ( popupPoint.x() < desk.left() ) popupPoint.setX( desk.x() ); 00166 00167 int dateFrameHeight = mDateFrame->sizeHint().height(); 00168 00169 if ( popupPoint.y() + height() + dateFrameHeight > desk.bottom() ) { 00170 popupPoint.setY( popupPoint.y() - dateFrameHeight ); 00171 } else { 00172 popupPoint.setY( popupPoint.y() + height() ); 00173 } 00174 00175 mDateFrame->move( popupPoint ); 00176 00177 QDate date; 00178 readDate(date); 00179 if (date.isValid()) { 00180 mDatePicker->setDate( date ); 00181 } else { 00182 mDatePicker->setDate( defaultValue ); 00183 } 00184 00185 mDateFrame->show(); 00186 00187 // The combo box is now shown pressed. Make it show not pressed again 00188 // by causing its (invisible) list box to emit a 'selected' signal. 00189 QListBox *lb = listBox(); 00190 if (lb) { 00191 lb->setCurrentItem(0); 00192 QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, 0, 0); 00193 QApplication::postEvent(lb, keyEvent); 00194 } 00195 } 00196 00197 void KDateEdit::dateSelected(QDate newDate) 00198 { 00199 if ((mHandleInvalid || newDate.isValid()) && validate(newDate)) { 00200 setDate(newDate); 00201 emit dateChanged(newDate); 00202 mDateFrame->hide(); 00203 } 00204 } 00205 00206 void KDateEdit::dateEntered(QDate newDate) 00207 { 00208 if ((mHandleInvalid || newDate.isValid()) && validate(newDate)) { 00209 setDate(newDate); 00210 emit dateChanged(newDate); 00211 } 00212 } 00213 00214 void KDateEdit::lineEnterPressed() 00215 { 00216 QDate date; 00217 if (readDate(date) && (mHandleInvalid || date.isValid()) && validate(date)) 00218 { 00219 // Update the edit. This is needed if the user has entered a 00220 // word rather than the actual date. 00221 setDate(date); 00222 emit(dateChanged(date)); 00223 } 00224 else { 00225 // Invalid or unacceptable date - revert to previous value 00226 KNotifyClient::beep(); 00227 setDate(value); 00228 emit invalidDateEntered(); 00229 } 00230 } 00231 00232 bool KDateEdit::inputIsValid() const 00233 { 00234 QDate date; 00235 return readDate(date) && date.isValid(); 00236 } 00237 00238 /* Reads the text from the line edit. If the text is a keyword, the 00239 * word will be translated to a date. If the text is not a keyword, the 00240 * text will be interpreted as a date. 00241 * Returns true if the date text is blank or valid, false otherwise. 00242 */ 00243 bool KDateEdit::readDate(QDate& result) const 00244 { 00245 QString text = currentText(); 00246 00247 if (text.isEmpty()) { 00248 result = QDate(); 00249 } 00250 else if (mKeywordMap.contains(text.lower())) 00251 { 00252 QDate today = QDate::currentDate(); 00253 int i = mKeywordMap[text.lower()]; 00254 if (i >= 100) 00255 { 00256 /* A day name has been entered. Convert to offset from today. 00257 * This uses some math tricks to figure out the offset in days 00258 * to the next date the given day of the week occurs. There 00259 * are two cases, that the new day is >= the current day, which means 00260 * the new day has not occurred yet or that the new day < the current day, 00261 * which means the new day is already passed (so we need to find the 00262 * day in the next week). 00263 */ 00264 i -= 100; 00265 int currentDay = today.dayOfWeek(); 00266 if (i >= currentDay) 00267 i -= currentDay; 00268 else 00269 i += 7 - currentDay; 00270 } 00271 result = today.addDays(i); 00272 } 00273 else 00274 { 00275 result = KGlobal::locale()->readDate(text); 00276 return result.isValid(); 00277 } 00278 00279 return true; 00280 } 00281 00282 /* Checks for a focus out event. The display of the date is updated 00283 * to display the proper date when the focus leaves. 00284 */ 00285 bool KDateEdit::eventFilter(QObject *obj, QEvent *e) 00286 { 00287 if (obj == lineEdit()) { 00288 // We only process the focus out event if the text has changed 00289 // since we got focus 00290 if ((e->type() == QEvent::FocusOut) && mTextChanged) 00291 { 00292 lineEnterPressed(); 00293 mTextChanged = false; 00294 } 00295 else if (e->type() == QEvent::KeyPress) 00296 { 00297 // Up and down arrow keys step the date 00298 QKeyEvent* ke = (QKeyEvent*)e; 00299 00300 if (ke->key() == Qt::Key_Return) 00301 { 00302 lineEnterPressed(); 00303 return true; 00304 } 00305 00306 int step = 0; 00307 if (ke->key() == Qt::Key_Up) 00308 step = 1; 00309 else if (ke->key() == Qt::Key_Down) 00310 step = -1; 00311 if (step && !mReadOnly) 00312 { 00313 QDate date; 00314 if (readDate(date) && date.isValid()) { 00315 date = date.addDays(step); 00316 if (validate(date)) { 00317 setDate(date); 00318 emit(dateChanged(date)); 00319 return true; 00320 } 00321 } 00322 } 00323 } 00324 } 00325 else { 00326 // It's a date picker event 00327 switch (e->type()) { 00328 case QEvent::MouseButtonDblClick: 00329 case QEvent::MouseButtonPress: { 00330 QMouseEvent *me = (QMouseEvent*)e; 00331 if (!mDateFrame->rect().contains(me->pos())) { 00332 QPoint globalPos = mDateFrame->mapToGlobal(me->pos()); 00333 if (QApplication::widgetAt(globalPos, true) == this) { 00334 // The date picker is being closed by a click on the 00335 // KDateEdit widget. Avoid popping it up again immediately. 00336 mDiscardNextMousePress = true; 00337 } 00338 } 00339 break; 00340 } 00341 default: 00342 break; 00343 } 00344 } 00345 00346 return false; 00347 } 00348 00349 void KDateEdit::mousePressEvent(QMouseEvent *e) 00350 { 00351 if (e->button() == Qt::LeftButton && mDiscardNextMousePress) { 00352 mDiscardNextMousePress = false; 00353 return; 00354 } 00355 QComboBox::mousePressEvent(e); 00356 } 00357 00358 void KDateEdit::slotTextChanged(const QString &) 00359 { 00360 mTextChanged = true; 00361 }
KDE Logo
This file is part of the documentation for libkdepim Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:57:46 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003