src/hbwidgets/editors/hbvalidator_p.cpp
changeset 0 16d8024aca5e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbwidgets/editors/hbvalidator_p.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#include "hbvalidator_p.h"
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QDebug>
+#include <QtAlgorithms>
+
+#ifdef HBVALIDATOR_DEBUG_ENABLE
+#define VALIDATORDEBUG(x) printFields(x)
+#else
+#define VALIDATORDEBUG(x)
+#endif
+
+HbValidatorPrivate::HbValidatorPrivate() :
+    separatorToAdd("/")
+{
+}
+
+void HbValidatorPrivate::init()
+{
+    // no implemantation needed
+}
+
+void HbValidatorPrivate::clear()
+{
+    deleteAllFields();
+}
+
+void HbValidatorPrivate::addField(const QString &separator, QValidator *validator, const QString &defaultValue)
+{
+    if(!fields.isEmpty()) {
+        // set separator between this and previous field
+        fields.back()->mNextSeparator = separator;
+    }
+
+    // creating new filed
+    HbValidatorField *newField = new HbValidatorField();
+    fields.append(newField);
+    
+    newField->mDefaultValue = defaultValue;
+    newField->mValidator = validator;
+}
+
+QValidator::State HbValidatorPrivate::validateText(const QTextDocument *doc)
+{
+    QValidator::State state = QValidator::Acceptable;
+    int lastSeparatorPos = 0;
+    QTextCursor suportCursor;
+
+    foreach(HbValidatorField* field, fields) {
+        int separatorPos;
+
+        if(!field->mNextSeparator.isEmpty()) {
+            suportCursor = doc->find(field->mNextSeparator, lastSeparatorPos, QTextDocument::FindCaseSensitively);
+            if(suportCursor.isNull()) {
+                // parsing failed
+                return QValidator::Invalid;
+            }
+            separatorPos = suportCursor.anchor();
+        } else {
+            // last posible cursor position
+            separatorPos = doc->characterCount()-1;
+            Q_ASSERT_X(separatorPos == doc->toPlainText().length(), 
+                "HbValidatorPrivate::validateText", 
+                "problems with QTextDocument::characterCount (to big value)");
+        }
+
+        // select field:
+        QTextCursor toValidate(const_cast<QTextDocument *>(doc));
+        toValidate.setPosition(lastSeparatorPos);
+        toValidate.setPosition(separatorPos, QTextCursor::KeepAnchor);
+
+        QString fieldText = toValidate.selectedText();
+        int cursorPos = fieldText.length();
+        QValidator::State fieldState = field->mValidator->validate(fieldText, cursorPos);
+
+        // maybe here changes done by field validator shold be copied to document using QTextCursor toValidate?
+        // in this case const from method argument should be removed
+
+        if(fieldState<state) {
+            state = fieldState;
+        }
+
+        if(state == QValidator::Invalid) {
+            break;
+        }
+
+        // position of cursor after separator
+        lastSeparatorPos = suportCursor.position();
+    }
+
+    return state;
+}
+
+int HbValidatorPrivate::findFieldIndexUnderCursorPos(const QTextCursor &cursor)
+{
+    const int cursorPosition(cursor.position());
+    const int lastFieldIndex(fields.count()-1);
+    int findFrom = 0;
+    int i;
+
+    QTextDocument *doc = cursor.document();
+    for(i = 0; i<lastFieldIndex; ++i) {
+        QTextCursor separatorFound = doc->find(fields.at(i)->mNextSeparator, findFrom, QTextDocument::FindCaseSensitively);
+        if(separatorFound.isNull()) {
+            return -1;
+        }
+        findFrom = separatorFound.position();
+        if(findFrom>cursorPosition) {
+            break;
+        }
+    }
+    return i;
+}
+
+bool HbValidatorPrivate::fieldHasSelection(int fieldIndex, const QTextCursor &cursor)
+{
+    if(!cursor.hasSelection()) {
+        return false;
+    }
+
+    const int lastFieldIndex = fields.count() - 1;
+
+    Q_ASSERT( fieldIndex >= 0 );
+    Q_ASSERT( fieldIndex <= lastFieldIndex );
+
+    const int cursorBegin = qMin(cursor.position(), cursor.anchor());
+    const int cursorEnd   = qMax(cursor.position(), cursor.anchor());
+
+    // cheching left side of cursor
+    if(fieldIndex==0) {// boundary condition (front):
+        if(cursorBegin != 0) {
+            return false;
+        }
+    } else { // normal check
+        QTextCursor supportCursor = cursor.document()->find( 
+                    fields.at(fieldIndex-1)->mNextSeparator,
+                    cursorBegin, 
+                    QTextDocument::FindCaseSensitively | QTextDocument::FindBackward);
+        Q_ASSERT(!supportCursor.isNull());
+        if( supportCursor.position() != cursorBegin) {
+            return false;
+        }
+    }
+
+    // checking right side of cursor
+    if(fieldIndex==lastFieldIndex) { // boundary condition (tail):
+        if( cursorEnd != cursor.document()->characterCount()-1 ) {
+            return false;
+        }
+    } else { // normal check
+        QTextCursor supportCursor = cursor.document()->find( 
+                    fields.at(fieldIndex)->mNextSeparator,
+                    cursorEnd, 
+                    QTextDocument::FindCaseSensitively);
+        Q_ASSERT(!supportCursor.isNull());
+        if( supportCursor.anchor() != cursorEnd) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void HbValidatorPrivate::highlightField(QTextCursor* cursor, int fieldIndex)
+{
+    const int lastFieldIndex = fields.count() - 1;
+
+    Q_ASSERT( fieldIndex >= 0 );
+    Q_ASSERT( fieldIndex <= lastFieldIndex );
+
+    QTextDocument *doc = cursor->document();
+    int lastFind = 0;
+    for(int i=0; i<fieldIndex; ++i) {
+        lastFind = doc->find(
+            fields.at(i)->mNextSeparator, 
+            lastFind, 
+            QTextDocument::FindCaseSensitively ).position();
+    }
+    cursor->setPosition(lastFind);
+
+    if(fieldIndex == lastFieldIndex) {
+        lastFind = doc->characterCount()-1;
+    } else {
+        lastFind = doc->find(
+                fields.at(fieldIndex)->mNextSeparator, 
+                lastFind, 
+                QTextDocument::FindCaseSensitively ).anchor();
+    }
+    cursor->setPosition(lastFind, QTextCursor::KeepAnchor);
+}
+
+void HbValidatorPrivate::deleteAllFields()
+{
+    Q_Q(HbValidator);
+
+    foreach(HbValidatorField *field, fields) {
+        if(field->mValidator) {
+            if( field->mValidator->parent() == q ) {
+                delete field->mValidator;
+            }
+        }
+        delete field;
+    }
+    fields.clear();
+}