summaryrefslogtreecommitdiffstats
path: root/src/declarative/fx/qfxtextinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/fx/qfxtextinput.cpp')
-rw-r--r--src/declarative/fx/qfxtextinput.cpp626
1 files changed, 626 insertions, 0 deletions
diff --git a/src/declarative/fx/qfxtextinput.cpp b/src/declarative/fx/qfxtextinput.cpp
new file mode 100644
index 0000000..1407a78
--- /dev/null
+++ b/src/declarative/fx/qfxtextinput.cpp
@@ -0,0 +1,626 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfxtextinput.h"
+#include "qfxtextinput_p.h"
+#include <QValidator>
+#include <QApplication>
+#include <QFontMetrics>
+#include <QPainter>
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,TextInput,QFxTextInput);
+QML_DEFINE_NOCREATE_TYPE(QValidator);
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,QIntValidator,QIntValidator);
+
+/*!
+ \qmlclass LineEdit
+ The LineEdit item allows you to add an editable line of text to a scene.
+*/
+QFxTextInput::QFxTextInput(QFxItem* parent)
+ : QFxPaintedItem(*(new QFxTextInputPrivate), parent)
+{
+ Q_D(QFxTextInput);
+ d->init();
+}
+
+/*
+ \internal
+*/
+QFxTextInput::QFxTextInput(QFxTextInputPrivate &dd, QFxItem* parent)
+ : QFxPaintedItem(dd, parent)
+{
+ Q_D(QFxTextInput);
+ d->init();
+}
+
+QFxTextInput::~QFxTextInput()
+{
+}
+
+/*!
+ \qmlproperty string LineEdit::text
+
+ The text in the LineEdit.
+*/
+
+QString QFxTextInput::text() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->text();
+}
+
+void QFxTextInput::setText(const QString &s)
+{
+ Q_D(QFxTextInput);
+ if(s == text())
+ return;
+ d->control->setText(s);
+ //emit textChanged();
+}
+
+/*!
+ \qmlproperty font LineEdit::font
+
+ Set the LineEdit's font attributes. \c font.size sets the font's point size.
+*/
+QFont QFxTextInput::font() const
+{
+ Q_D(const QFxTextInput);
+ return d->font;
+}
+
+void QFxTextInput::setFont(const QFont &font)
+{
+ Q_D(QFxTextInput);
+ d->font = font;
+
+ d->control->setFont(d->font);
+ if(d->cursorItem){
+ d->cursorItem->setHeight(QFontMetrics(d->font).height());
+ moveCursor();
+ }
+ //updateSize();
+ updateAll();//TODO: Only necessary updates
+ update();
+}
+
+/*!
+ \qmlproperty color LineEdit::color
+
+ The text color.
+*/
+QColor QFxTextInput::color() const
+{
+ Q_D(const QFxTextInput);
+ return d->color;
+}
+
+void QFxTextInput::setColor(const QColor &c)
+{
+ Q_D(QFxTextInput);
+ d->color = c;
+}
+
+
+/*!
+ \qmlproperty color LineEdit::highlightColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QFxTextInput::highlightColor() const
+{
+ Q_D(const QFxTextInput);
+ return d->highlightColor;
+}
+
+void QFxTextInput::setHighlightColor(const QColor &color)
+{
+ Q_D(QFxTextInput);
+ if (d->highlightColor == color)
+ return;
+
+ d->highlightColor = color;
+ //TODO: implement
+}
+
+/*!
+ \qmlproperty color LineEdit::highlightedTextColor
+
+ The highlighted text color, used in selections.
+*/
+QColor QFxTextInput::highlightedTextColor() const
+{
+ Q_D(const QFxTextInput);
+ return d->highlightedTextColor;
+}
+
+void QFxTextInput::setHighlightedTextColor(const QColor &color)
+{
+ Q_D(QFxTextInput);
+ if (d->highlightedTextColor == color)
+ return;
+
+ d->highlightedTextColor = color;
+ //TODO: implement
+}
+
+QFxTextInput::HAlignment QFxTextInput::hAlign() const
+{
+ Q_D(const QFxTextInput);
+ return d->hAlign;
+}
+
+void QFxTextInput::setHAlign(HAlignment align)
+{
+ Q_D(QFxTextInput);
+ d->hAlign = align;
+}
+
+bool QFxTextInput::isReadOnly() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->isReadOnly();
+}
+
+void QFxTextInput::setReadOnly(bool ro)
+{
+ Q_D(QFxTextInput);
+ d->control->setReadOnly(ro);
+}
+
+int QFxTextInput::maxLength() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->maxLength();
+}
+
+void QFxTextInput::setMaxLength(int ml)
+{
+ Q_D(QFxTextInput);
+ d->control->setMaxLength(ml);
+}
+
+/*!
+ \qmlproperty bool LineEdit::cursorVisible
+ If true the text edit shows a cursor.
+
+ This property is set and unset when the line edit gets focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QFxTextInput::isCursorVisible() const
+{
+ Q_D(const QFxTextInput);
+ return d->cursorVisible;
+}
+
+void QFxTextInput::setCursorVisible(bool on)
+{
+ Q_D(QFxTextInput);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
+ updateAll();//TODO: Only update cursor rect
+}
+
+/*!
+ \qmlproperty int LineEdit::cursorPosition
+ The position of the cursor in the LineEdit.
+*/
+int QFxTextInput::cursorPosition() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->cursor();
+}
+void QFxTextInput::setCursorPosition(int cp)
+{
+ Q_D(QFxTextInput);
+ d->control->moveCursor(cp);
+}
+
+/*!
+ \qmlproperty int LineEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+ Setting this and selectionEnd allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionStart to a value outside of
+ the current text, selectionStart will not be changed.
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QFxTextInput::selectionStart() const
+{
+ Q_D(const QFxTextInput);
+ return d->lastSelectionStart;
+}
+
+void QFxTextInput::setSelectionStart(int s)
+{
+ Q_D(QFxTextInput);
+ if(d->lastSelectionStart == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionStart = s;
+ d->control->setSelection(s, d->lastSelectionEnd - s);
+}
+
+/*!
+ \qmlproperty int LineEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+ Setting this and selectionStart allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionEnd to a value outside of
+ the current text, selectionEnd will not be changed.
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QFxTextInput::selectionEnd() const
+{
+ Q_D(const QFxTextInput);
+ return d->lastSelectionEnd;
+}
+
+void QFxTextInput::setSelectionEnd(int s)
+{
+ Q_D(QFxTextInput);
+ if(d->lastSelectionEnd == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionEnd = s;
+ d->control->setSelection(d->lastSelectionStart, s - d->lastSelectionStart);
+}
+
+QString QFxTextInput::selectedText() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->selectedText();
+}
+
+QValidator* QFxTextInput::validator() const
+{
+ Q_D(const QFxTextInput);
+ //###const cast isn't good, but needed for property system?
+ return const_cast<QValidator*>(d->control->validator());
+}
+
+void QFxTextInput::setValidator(QValidator* v)
+{
+ Q_D(QFxTextInput);
+ d->control->setValidator(v);
+ if(!d->control->hasAcceptableInput()){
+ d->oldValidity = false;
+ emit acceptableInputChanged();
+ }
+}
+
+QString QFxTextInput::inputMask() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->inputMask();
+}
+
+void QFxTextInput::setInputMask(const QString &im)
+{
+ Q_D(QFxTextInput);
+ d->control->setInputMask(im);
+}
+
+bool QFxTextInput::hasAcceptableInput() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->hasAcceptableInput();
+}
+
+uint QFxTextInput::echoMode() const
+{
+ Q_D(const QFxTextInput);
+ return d->control->echoMode();
+}
+
+void QFxTextInput::setEchoMode(uint echo)
+{
+ Q_D(QFxTextInput);
+ d->control->setEchoMode(echo);
+}
+
+/*!
+ \qmlproperty Component LineEdit::cursorDelegate
+ The delegate for the cursor in the LineEdit.
+
+ If you set a cursorDelegate for a LineEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the LineEdit when a cursor is
+ needed, and the x property of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QFxItem or
+ QFxItem derived item.
+*/
+QmlComponent* QFxTextInput::cursorDelegate() const
+{
+ Q_D(const QFxTextInput);
+ return d->cursorComponent;
+}
+
+void QFxTextInput::setCursorDelegate(QmlComponent* c)
+{
+ Q_D(QFxTextInput);
+ if(d->cursorComponent)
+ delete d->cursorComponent;
+ d->cursorComponent = c;
+ d->startCreatingCursor();
+}
+
+void QFxTextInputPrivate::startCreatingCursor()
+{
+ Q_Q(QFxTextInput);
+ if(!cursorComponent){
+ q->disconnect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(moveCursor()));
+ return;
+ }
+ q->connect(control, SIGNAL(cursorPositionChanged(int, int)),
+ q, SLOT(moveCursor()));
+ if(cursorComponent->isReady()){
+ q->createCursor();
+ }else if(cursorComponent->isLoading()){
+ q->connect(cursorComponent, SIGNAL(statusChanged(int)),
+ q, SLOT(createCursor()));
+ }else{//isError
+ qWarning() << "You could really use the error checking for QFxTextInput. We'll implement it soon.";
+ }
+}
+
+void QFxTextInput::createCursor()
+{
+ Q_D(QFxTextInput);
+ //Handle isError too
+ if(!d->cursorComponent->isReady())
+ return;
+
+ if(d->cursorItem)
+ delete d->cursorItem;
+ d->cursorItem = qobject_cast<QFxItem*>(d->cursorComponent->create());
+ if(!d->cursorItem){
+ qWarning() << "You could really use the error reporting for QFxTextInput. We'll implement it soon.";
+ return;
+ }
+
+ d->cursorItem->setParentItem(this);
+ d->cursorItem->setX(d->control->cursorToX());
+ d->cursorItem->setHeight(d->control->height());
+}
+
+void QFxTextInput::moveCursor()
+{
+ Q_D(QFxTextInput);
+ if(!d->cursorItem)
+ return;
+ d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
+}
+
+int QFxTextInput::xToPos(int x)
+{
+ Q_D(const QFxTextInput);
+ return d->control->xToPos(x - d->hscroll);
+}
+
+void QFxTextInput::focusChanged(bool hasFocus)
+{
+ Q_D(QFxTextInput);
+ d->focused = hasFocus;
+ setCursorVisible(hasFocus);
+ QFxItem::focusChanged(hasFocus);
+}
+
+void QFxTextInput::keyPressEvent(QKeyEvent* ev)
+{
+ Q_D(QFxTextInput);
+ d->control->processKeyEvent(ev);
+ if (!ev->isAccepted())
+ QFxPaintedItem::keyPressEvent(ev);
+}
+
+void QFxTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QFxTextInput);
+ setFocus(true);//###Should we make 'focusOnPress' be optional like TextEdit?
+ setCursorVisible(true);
+ d->focused = true;
+ d->control->processEvent(event);
+ //event->accept();
+}
+
+bool QFxTextInput::event(QEvent* ev)
+{
+ Q_D(QFxTextInput);
+ //Anything we don't deal with ourselves, pass to the control
+ switch(ev->type()){
+ case QEvent::GraphicsSceneMousePress:
+ break;
+ default:
+ return d->control->processEvent(ev);
+ }
+ return false;
+}
+
+void QFxTextInput::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QFxPaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QFxTextInput::drawContents(QPainter *p, const QRect &r)
+{
+ Q_D(QFxTextInput);
+ p->setRenderHint(QPainter::TextAntialiasing, true);
+ p->save();
+ p->setPen(QPen(d->color));
+ int flags = QLineControl::DrawText;
+ if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
+ flags |= QLineControl::DrawCursor;
+ if (d->control->hasSelectedText())
+ flags |= QLineControl::DrawSelections;
+
+ d->control->draw(p, QPoint(0,0), r, flags);
+
+ p->restore();
+}
+
+/*!
+ \qmlproperty bool LineEdit::smooth
+
+ Set this property if you want the text to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+void QFxTextInputPrivate::init()
+{
+ Q_Q(QFxTextInput);
+ control->setCursorWidth(1);
+ control->setPasswordCharacter(QLatin1Char('*'));
+ control->setLayoutDirection(Qt::LeftToRight);
+ q->setSmoothTransform(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(cursorPosChanged()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(selectionChanged()));
+ q->connect(control, SIGNAL(textChanged(const QString &)),
+ q, SLOT(q_textChanged()));
+ q->connect(control, SIGNAL(accepted()),
+ q, SIGNAL(accepted()));
+ q->connect(control, SIGNAL(updateNeeded(const QRect &)),
+ // q, SLOT(dirtyCache(const QRect &)));
+ q, SLOT(updateAll()));
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(updateAll()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(updateAll()));
+ q->updateSize();
+ oldValidity = control->hasAcceptableInput();
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
+}
+
+void QFxTextInput::cursorPosChanged()
+{
+ Q_D(QFxTextInput);
+ emit cursorPositionChanged();
+
+ if(!d->control->hasSelectedText()){
+ if(d->lastSelectionStart != d->control->cursor()){
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->cursor()){
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+ }
+}
+
+void QFxTextInput::selectionChanged()
+{
+ Q_D(QFxTextInput);
+ emit selectedTextChanged();
+
+ if(d->lastSelectionStart != d->control->selectionStart()){
+ d->lastSelectionStart = d->control->selectionStart();
+ if(d->lastSelectionStart == -1)
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->selectionEnd()){
+ d->lastSelectionEnd = d->control->selectionEnd();
+ if(d->lastSelectionEnd == -1)
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+}
+
+void QFxTextInput::q_textChanged()
+{
+ Q_D(QFxTextInput);
+ updateAll();
+ emit textChanged();
+ if(hasAcceptableInput() != d->oldValidity){
+ d->oldValidity = hasAcceptableInput();
+ emit acceptableInputChanged();
+ }
+}
+
+//### Please replace this function with proper updating
+void QFxTextInput::updateAll()
+{
+ clearCache();
+ updateSize();
+ update();
+}
+
+void QFxTextInput::updateSize()
+{
+ Q_D(QFxTextInput);
+ setImplicitHeight(d->control->height());
+ //d->control->width() is max width, not current width
+ QFontMetrics fm = QFontMetrics(d->font);
+ setImplicitWidth(fm.boundingRect(d->control->text()).width()+1);
+ setContentsSize(QSize(width(), height()));
+}
+
+QT_END_NAMESPACE
+