diff -r 000000000000 -r 16d8024aca5e src/hbwidgets/editors/hbdatetimevalidator_p.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbwidgets/editors/hbdatetimevalidator_p.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,407 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (developer.feedback@nokia.com) +** +** This file is part of the HbWidgets module of the UI Extensions for Mobile. +** +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at developer.feedback@nokia.com. +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Hb API. It exists purely as an +// implementation detail. This file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include + +#include "hbdatetimevalidator_p_p.h" +#include "hbvalidator_p.h" + +#define DEFAULT_YEAR_VALUE "2009" + +const int KMinimumYear = -4713; +const int KMaximumYear = 11000000; // see more in QDate documentation + +HbDateTimeValidatorPrivate::HbDateTimeValidatorPrivate() : + HbValidatorPrivate() +{ + +} + +HbDateTimeValidatorPrivate::~HbDateTimeValidatorPrivate() +{ + +} + +class HbFixableIntQValidator : public QIntValidator +{ +public: + HbFixableIntQValidator( QObject * parent ) : + QIntValidator ( parent ), + mMaxLeght(10000) + { + } + + HbFixableIntQValidator ( int minimum, int maximum, QObject * parent ) : + QIntValidator ( minimum, maximum, parent ) + { + int topLenght = QString::number(top()).length(); + int bottomLenght = QString::number(bottom()).length(); + mMaxLeght = qMax(topLenght, bottomLenght); + } + + void fixup ( QString & input ) const + { + QString newTextValue=input; + newTextValue.remove(QRegExp((bottom()>=0)?"[^0-9]":"[^\\-0-9]")); + bool ok; + int value = newTextValue.toInt(&ok); + if(ok) { + value = qBound(bottom(), value, top()); + newTextValue.setNum(value); + if(newTextValue!=input) { + input = newTextValue; + } + } + } + + State validate ( QString & input, int & pos ) const + { + if(input.length()>mMaxLeght) { + return Invalid; + } + + return QIntValidator::validate(input, pos); + } + +private: + int mMaxLeght; +}; + +void HbDateTimeValidatorPrivate::addDateTimeField(const DataPositions& data) +{ + Q_Q(HbDateTimeValidator); + QValidator *fieldValidator = NULL; + QString defaultValue; + + switch(data.type) { + case Year: { + if(data.lenght() == 4) { + fieldValidator = new HbFixableIntQValidator(KMinimumYear, + KMaximumYear, + q); + defaultValue = "2009"; + } else { + fieldValidator = new HbFixableIntQValidator(0,99,q); + defaultValue = "09"; + } + } + break; + case Month: { + fieldValidator = new HbFixableIntQValidator(1,12,q); + defaultValue = (data.lenght() == 1)?"1":"01"; + } + break; + case Day: { + fieldValidator = new HbFixableIntQValidator(1,31,q); + defaultValue = (data.lenght() == 1)?"1":"01"; + } + break; + case AmPm: { + QRegExp regUxp("AM|PM", Qt::CaseInsensitive); + fieldValidator = new QRegExpValidator(regUxp,q); + defaultValue = "AM"; + } + break; + case Hour24: { + fieldValidator = new HbFixableIntQValidator(0,23,q); + defaultValue = (data.lenght() == 1)?"0":"00"; + } + break; + case Hour12: { + fieldValidator = new HbFixableIntQValidator(1,12,q); + defaultValue = "12"; + } + break; + case Minutes: { + fieldValidator = new HbFixableIntQValidator(0,59,q); + defaultValue = (data.lenght() == 1)?"0":"00"; + } + break; + case Seconds: { + fieldValidator = new HbFixableIntQValidator(0,59,q); + defaultValue = (data.lenght() == 1)?"0":"00"; + } + break; + case MilliSeconds: { + fieldValidator = new HbFixableIntQValidator(0,999,q); + defaultValue = (data.lenght() == 1)?"0":"000"; + } + break; + default: + Q_ASSERT(false); + } + fieldTypes.append(data.type); + addField(separatorToAdd,fieldValidator,defaultValue); +} + +bool HbDateTimeValidatorPrivate::fixDate(QTextCursor *cursor, bool updateCursor) +{ + Q_ASSERT(!fieldTypes.isEmpty()); + + QRegExp regExp = QRegExp(parseString,Qt::CaseInsensitive); + + Q_ASSERT(regExp.isValid()); + + bool result = false; + + if(regExp.exactMatch(cursor->document()->toPlainText())) { + QTextCursor fixingCursor(cursor->document()); + fixingCursor.beginEditBlock(); + + // step one: fixing each field separately + for(int i = fieldTypes.count()-1; i>=0; --i ) { + int pos = regExp.pos(i+1); + QString fieldTxt = regExp.cap(i+1); + fixingCursor.setPosition(pos); + fixingCursor.setPosition(pos + fieldTxt.length()); + + int x = fieldTxt.length(); + if( QValidator::Acceptable != fields.at(i)->mValidator->validate(fieldTxt, x) ) { + fields.at(i)->mValidator->fixup(fieldTxt); + if(QValidator::Acceptable == fields.at(i)->mValidator->validate(fieldTxt, x)) { + // successful fix + fixingCursor.insertText(fieldTxt); + result = true; + } + } + } + + // step two: fixing correlations between fields + // Note: this functionality is specific for HbDateTimeValidator + int yearCapture = fieldTypes.indexOf(Year)+1; + int monthCapture = fieldTypes.indexOf(Month)+1; + int dayCapture = fieldTypes.indexOf(Day)+1; + + if(dayCapture<=0 || monthCapture<=0) { + fixingCursor.endEditBlock(); + return result; // nothing to fix no date + } + + // match content again + if(regExp.exactMatch(cursor->document()->toPlainText())) { + int year=1900, month, day; + + if(yearCapture>0) { + year = regExp.cap(yearCapture).toInt(); + } + month = regExp.cap(monthCapture).toInt(); + + int daySize =0; + QString s = regExp.cap(dayCapture); + daySize = s.length(); + day = s.toInt(); + + if( !QDate::isValid(year, month, day) ) { + QDate dateFoFix(year,month,1); + if(dateFoFix.daysInMonth()q_ptr = this; +} + +HbDateTimeValidator::HbDateTimeValidator(HbDateTimeValidatorPrivate &dd, QObject *parent) : + HbValidator(dd, parent) +{ + Q_D(HbDateTimeValidator); + d->q_ptr = this; +} + +/*! + Destructor +*/ +HbDateTimeValidator::~HbDateTimeValidator() +{ +} + +inline void appendIfFound(DataType type, QList* where, QRegExp& what, const QString& from) +{ + int pos = from.indexOf(what); + if(pos>=0) { + int matchLenght = what.cap(0).length(); + Q_ASSERT( matchLenght>0 ); + Q_ASSERT( from.indexOf(what, pos+matchLenght)==-1 ); + + where->append( + DataPositions(type, pos, matchLenght) + ); + } +} + +void HbDateTimeValidator::setDisplayFormat(const QString &format) +{ + QList positions; + + QRegExp regExp; + QString newParseString = QRegExp::escape(format); + const QString captureNumber = "([0-9]+)"; + + regExp.setPattern("yy(yy)?"); + appendIfFound(Year, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("M{1,3}"); + appendIfFound(Month, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("d{1,3}"); + appendIfFound(Day, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + const QString captureAmPm("(AM|PM|am|pm)"); + regExp.setPattern("ap"); + appendIfFound(AmPm, &positions, regExp, format); + newParseString.replace(regExp, captureAmPm); + + regExp.setPattern("AP"); + appendIfFound(AmPm, &positions, regExp, format); + newParseString.replace(regExp, captureAmPm); + + DataType hourType = Hour24; + if(!positions.isEmpty()) { + if(positions.last().type==AmPm) { + hourType = Hour12; + } + } + + regExp.setPattern("hh?"); + appendIfFound(hourType, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("HH?"); + appendIfFound(hourType, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("mm?"); + appendIfFound(Minutes, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("ss?"); + appendIfFound(Seconds, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + regExp.setPattern("z(zz)?"); + appendIfFound(MilliSeconds, &positions, regExp, format); + newParseString.replace(regExp, captureNumber); + + if(positions.size()==0) { + qWarning() << "HbDateTimeValidator::setDisplayFormat: format: \"" + << format << "\" is invalid so it was ignored" ; + return; + } + + qSort(positions); + + Q_D(HbDateTimeValidator); + d->format = format; + // ignore trailing separators: + if(positions.back().stop < format.length()) { + newParseString.chop(QRegExp::escape(format.mid(positions.back().stop)).length()); + d->format.resize(positions.back().stop); + } + + // ignore front separators: + if(positions.front().start != 0) { + newParseString.remove(0,positions.front().start); + } + + d->parseString = newParseString; + d->fieldTypes.clear(); + d->deleteAllFields(); + + const int n=positions.size()-1; + for(int i=0; iaddDateTimeField(positions.at(i)); + int separatorBegin = positions.at(i).stop; + int separatorLenght = positions.at(i+1).start - separatorBegin; + if(separatorLenght>0) { + setDefaultSeparator(format.mid(separatorBegin,separatorLenght)); + } else { + setDefaultSeparator(" "); + } + } + d->addDateTimeField(positions.at(n)); +} + +const QString HbDateTimeValidator::displayFormat() const +{ + Q_D(const HbDateTimeValidator); + return d->format; +} + +bool HbDateTimeValidator::fixDate(QTextCursor *cursor, bool updateCursor) +{ + return d_func()->fixDate(cursor, updateCursor); +}