TextEdit:
- the default value of the textFormat property is now PlainText instead of AutoText.
+TextInput has new wrapMode and verticalAlignment properties, and the positionAt function now takes
+a y parameter.
+
PathView now has a \c currentItem property
ListView and GridView:
{
}
+void QQuickTextInput::componentComplete()
+{
+ Q_D(QQuickTextInput);
+
+ QQuickImplicitSizeItem::componentComplete();
+
+ d->updateLayout();
+ updateCursorRectangle();
+ if (d->cursorComponent && d->cursorComponent->isReady())
+ createCursor();
+}
+
/*!
\qmlproperty string QtQuick2::TextInput::text
d->font.setPointSizeF(size/2.0);
}
if (oldFont != d->font) {
- d->updateDisplayText();
- updateSize();
+ d->updateLayout();
updateCursorRectangle();
- if (d->cursorItem) {
- d->cursorItem->setHeight(QFontMetrics(d->font).height());
- }
}
emit fontChanged(d->sourceFont);
}
/*!
\qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
\qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
+ \qmlproperty enumeration QtQuick2::TextInput::verticalAlignment
Sets the horizontal alignment of the text within the TextInput item's
width and height. By default, the text alignment follows the natural alignment
The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
\c TextInput.AlignHCenter.
+ Valid values for \c verticalAlignment are \c TextEdit.AlignTop (default),
+ \c TextEdit.AlignBottom \c TextEdit.AlignVCenter.
+
When using the attached property LayoutMirroring::enabled to mirror application
layouts, the horizontal alignment of text will also be mirrored. However, the property
\c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
d->hAlignImplicit = false;
if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
+ d->updateLayout();
updateCursorRectangle();
}
}
Q_D(QQuickTextInput);
d->hAlignImplicit = true;
if (d->determineHorizontalAlignment() && isComponentComplete()) {
+ d->updateLayout();
updateCursorRectangle();
}
}
return false;
}
+QQuickTextInput::VAlignment QQuickTextInput::vAlign() const
+{
+ Q_D(const QQuickTextInput);
+ return d->vAlign;
+}
+
+void QQuickTextInput::setVAlign(QQuickTextInput::VAlignment alignment)
+{
+ Q_D(QQuickTextInput);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ emit verticalAlignmentChanged(d->vAlign);
+ if (isComponentComplete()) {
+ updateCursorRectangle();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuick2::TextInput::wrapMode
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ \list
+ \o TextInput.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
+ \o TextInput.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
+ \o TextInput.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o TextInput.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+
+ The default is TextInput.NoWrap. If you set a width, consider using TextInput.Wrap.
+*/
+QQuickTextInput::WrapMode QQuickTextInput::wrapMode() const
+{
+ Q_D(const QQuickTextInput);
+ return d->wrapMode;
+}
+
+void QQuickTextInput::setWrapMode(WrapMode mode)
+{
+ Q_D(QQuickTextInput);
+ if (mode == d->wrapMode)
+ return;
+ d->wrapMode = mode;
+ d->updateLayout();
+ updateCursorRectangle();
+ emit wrapModeChanged();
+}
+
void QQuickTextInputPrivate::mirrorChange()
{
Q_Q(QQuickTextInput);
QRect QQuickTextInput::cursorRectangle() const
{
Q_D(const QQuickTextInput);
- QTextLine l = d->m_textLayout.lineAt(0);
+
int c = d->m_cursor;
if (d->m_preeditCursor != -1)
c += d->m_preeditCursor;
- return QRect(qRound(l.cursorToX(c)) - d->hscroll, 0, d->m_cursorWidth, l.height());
+ if (d->m_echoMode == NoEcho || !isComponentComplete())
+ c = 0;
+ QTextLine l = d->m_textLayout.lineForTextPosition(c);
+ return QRect(
+ qRound(l.cursorToX(c) - d->hscroll),
+ qRound(l.y() - d->vscroll),
+ d->m_cursorWidth,
+ qCeil(l.height()));
}
+
/*!
\qmlproperty int QtQuick2::TextInput::selectionStart
d->autoScroll = b;
//We need to repaint so that the scrolling is taking into account.
- updateSize(true);
updateCursorRectangle();
emit autoScrollChanged(d->autoScroll);
}
d->m_echoMode = echo;
d->m_passwordEchoEditing = false;
d->updateInputMethodHints();
-
d->updateDisplayText();
- q_textChanged();
+ updateCursorRectangle();
emit echoModeChanged(echoMode());
}
void QQuickTextInput::createCursor()
{
Q_D(QQuickTextInput);
+ if (!isComponentComplete())
+ return;
+
if (d->cursorComponent->isError()) {
qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
return;
return;
}
+ QRectF r = cursorRectangle();
+
QDeclarative_setParent_noEvent(d->cursorItem, this);
d->cursorItem->setParentItem(this);
- d->cursorItem->setX(d->cursorToX());
- d->cursorItem->setHeight(d->calculateTextHeight());
+ d->cursorItem->setPos(r.topLeft());
+ d->cursorItem->setHeight(r.height());
}
/*!
if (pos > d->m_cursor)
pos += d->preeditAreaText().length();
QTextLine l = d->m_textLayout.lineAt(0);
- return QRectF( l.cursorToX(pos) - d->hscroll, 0.0, d->m_cursorWidth, l.height());
+ return QRectF(l.cursorToX(pos) - d->hscroll, 0.0, d->m_cursorWidth, l.height());
}
/*!
- \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
+ \qmlmethod int QtQuick2::TextInput::positionAt(real x, real y, CursorPosition position = CursorBetweenCharacters)
This function returns the character position at
- x pixels from the left of the textInput. Position 0 is before the
+ x and y pixels from the top left of the textInput. Position 0 is before the
first character, position 1 is after the first character but before the second,
and so on until position text.length, which is after all characters.
This means that for all x values before the first character this function returns 0,
- and for all x values after the last character this function returns text.length.
+ and for all x values after the last character this function returns text.length. If
+ the y value is above the text the position will be that of the nearest character on
+ the first line line and if it is below the text the position of the nearest character
+ on the last line will be returned.
The cursor position type specifies how the cursor position should be resolved.
\o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
\endlist
*/
-int QQuickTextInput::positionAt(int x) const
-{
- return positionAt(x, CursorBetweenCharacters);
-}
-int QQuickTextInput::positionAt(int x, CursorPosition position) const
+void QQuickTextInput::positionAt(QDeclarativeV8Function *args) const
{
Q_D(const QQuickTextInput);
- int pos = d->m_textLayout.lineAt(0).xToCursor(x + d->hscroll, QTextLine::CursorPosition(position));
+
+ qreal x = 0;
+ qreal y = 0;
+ QTextLine::CursorPosition position = QTextLine::CursorBetweenCharacters;
+
+ if (args->Length() < 1)
+ return;
+
+ int i = 0;
+ v8::Local<v8::Value> arg = (*args)[i];
+ x = arg->NumberValue();
+
+ if (++i < args->Length()) {
+ arg = (*args)[i];
+ y = arg->NumberValue();
+ }
+
+ if (++i < args->Length()) {
+ arg = (*args)[i];
+ position = QTextLine::CursorPosition(arg->Int32Value());
+ }
+
+ int pos = d->positionAt(x, y, position);
const int cursor = d->m_cursor;
if (pos > cursor) {
const int preeditLength = d->preeditAreaText().length();
? pos - preeditLength
: cursor;
}
- return pos;
+ args->returnValue(v8::Int32::New(pos));
+}
+
+int QQuickTextInputPrivate::positionAt(int x, int y, QTextLine::CursorPosition position) const
+{
+ x += hscroll;
+ y += vscroll;
+ QTextLine line = m_textLayout.lineAt(0);
+ for (int i = 1; i < m_textLayout.lineCount(); ++i) {
+ QTextLine nextLine = m_textLayout.lineAt(i);
+
+ if (y < (line.rect().bottom() + nextLine.y()) / 2)
+ break;
+ line = nextLine;
+ }
+ return line.xToCursor(x, position);
}
void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
if (d->selectByMouse && event->button() == Qt::LeftButton) {
d->commitPreedit();
- int cursor = d->xToPos(event->localPos().x());
+ int cursor = d->positionAt(event->localPos());
d->selectWordAtPos(cursor);
event->setAccepted(true);
if (!d->hasPendingTripleClick()) {
return;
bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
- int cursor = d->xToPos(event->localPos().x());
+ int cursor = d->positionAt(event->localPos());
d->moveCursor(cursor, mark);
event->setAccepted(true);
}
if (d->composeMode()) {
// start selection
- int startPos = d->xToPos(d->pressPos.x());
- int currentPos = d->xToPos(event->localPos().x());
+ int startPos = d->positionAt(d->pressPos);
+ int currentPos = d->positionAt(event->localPos());
if (startPos != currentPos)
d->setSelection(startPos, currentPos - startPos);
} else {
- moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
+ moveCursorSelection(d->positionAt(event->localPos()), d->mouseSelectionMode);
}
event->setAccepted(true);
} else {
{
#if !defined QT_NO_IM
if (composeMode()) {
- int tmp_cursor = xToPos(event->localPos().x());
+ int tmp_cursor = positionAt(event->localPos());
int mousePos = tmp_cursor - m_cursor;
if (mousePos >= 0 && mousePos <= m_textLayout.preeditAreaText().length()) {
if (event->type() == QEvent::MouseButtonRelease) {
void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
- if (newGeometry.width() != oldGeometry.width()) {
- updateSize();
- updateCursorRectangle();
- }
+ Q_D(QQuickTextInput);
+ if (newGeometry.width() != oldGeometry.width())
+ d->updateLayout();
+ updateCursorRectangle();
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
void QQuickTextInputPrivate::updateHorizontalScroll()
{
Q_Q(QQuickTextInput);
+ QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
const int preeditLength = m_textLayout.preeditAreaText().length();
const int width = q->width();
- int widthUsed = calculateTextWidth();
+ int widthUsed = currentLine.isValid() ? qRound(currentLine.naturalTextWidth()) : 0;
+ int previousScroll = hscroll;
- if (!autoScroll || widthUsed <= width) {
- QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
- // text fits in br; use hscroll for alignment
- switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
- case Qt::AlignRight:
- hscroll = widthUsed - width;
- break;
- case Qt::AlignHCenter:
- hscroll = (widthUsed - width) / 2;
- break;
- default:
- // Left
- hscroll = 0;
- break;
- }
+ if (!autoScroll || widthUsed <= width || m_echoMode == QQuickTextInput::NoEcho) {
+ hscroll = 0;
} else {
- int cix = qRound(cursorToX(m_cursor + preeditLength));
+ int cix = qRound(currentLine.cursorToX(m_cursor + preeditLength));
if (cix - hscroll >= width) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - width;
if (preeditLength > 0) {
// check to ensure long pre-edit text doesn't push the cursor
// off to the left
- cix = qRound(cursorToX(
- m_cursor + qMax(0, m_preeditCursor - 1)));
+ cix = qRound(currentLine.cursorToX(m_cursor + qMax(0, m_preeditCursor - 1)));
if (cix < hscroll)
hscroll = cix;
}
}
+ if (previousScroll != hscroll)
+ textLayoutDirty = true;
+}
+
+void QQuickTextInputPrivate::updateVerticalScroll()
+{
+ Q_Q(QQuickTextInput);
+ const int preeditLength = m_textLayout.preeditAreaText().length();
+ const int height = q->height();
+ int heightUsed = boundingRect.height();
+ int previousScroll = vscroll;
+
+ if (!autoScroll || heightUsed <= height) {
+ // text fits in br; use vscroll for alignment
+ switch (vAlign & ~(Qt::AlignAbsolute|Qt::AlignHorizontal_Mask)) {
+ case Qt::AlignBottom:
+ vscroll = heightUsed - height;
+ break;
+ case Qt::AlignVCenter:
+ vscroll = (heightUsed - height) / 2;
+ break;
+ default:
+ // Top
+ vscroll = 0;
+ break;
+ }
+ } else {
+ QRectF r = m_textLayout.lineForTextPosition(m_cursor + preeditLength).rect();
+ int top = qFloor(r.top());
+ int bottom = qCeil(r.bottom());
+
+ if (bottom - vscroll >= height) {
+ // text doesn't fit, cursor is to the below the br (scroll down)
+ vscroll = bottom - height;
+ } else if (top - vscroll < 0 && vscroll < heightUsed) {
+ // text doesn't fit, cursor is above br (scroll up)
+ vscroll = top;
+ } else if (heightUsed - vscroll < height) {
+ // text doesn't fit, text document is to the left of br; align
+ // right
+ vscroll = heightUsed - height;
+ }
+ if (preeditLength > 0) {
+ // check to ensure long pre-edit text doesn't push the cursor
+ // off the top
+ top = qRound(m_textLayout.lineForTextPosition(
+ m_cursor + qMax(0, m_preeditCursor - 1)).rect().top());
+ if (top < vscroll)
+ vscroll = top;
+ }
+ }
+ if (previousScroll != vscroll)
+ textLayoutDirty = true;
}
QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
QPoint offset = QPoint(0,0);
QFontMetrics fm = QFontMetrics(d->font);
- QRect br(boundingRect().toRect());
if (d->autoScroll) {
// the y offset is there to keep the baseline constant in case we have script changes in the text.
- offset = br.topLeft() - QPoint(d->hscroll, d->ascent() - fm.ascent());
+ offset = -QPoint(d->hscroll, d->vscroll + d->m_ascent - fm.ascent());
} else {
- offset = QPoint(d->hscroll, 0);
+ offset = -QPoint(d->hscroll, d->vscroll);
}
if (!d->m_textLayout.text().isEmpty()) {
if (str.length() < 1)
return;
d->m_passwordCharacter = str.constData()[0];
- d->updateDisplayText();
- if (d->m_echoMode == Password || d->m_echoMode == PasswordEchoOnEdit) {
- updateSize();
- }
+ if (d->m_echoMode == Password || d->m_echoMode == PasswordEchoOnEdit)
+ d->updateDisplayText();
emit passwordCharacterChanged();
}
q, SLOT(q_canPasteChanged()));
canPaste = !m_readOnly && QGuiApplication::clipboard()->text().length() != 0;
#endif // QT_NO_CLIPBOARD
- updateDisplayText();
- q->updateSize();
+ m_textLayout.beginLayout();
+ m_textLayout.createLine();
+ m_textLayout.endLayout();
+
imHints &= ~Qt::ImhMultiLine;
oldValidity = hasAcceptableInput(m_text);
lastSelectionStart = 0;
void QQuickTextInput::updateCursorRectangle()
{
Q_D(QQuickTextInput);
- d->determineHorizontalAlignment();
+ if (!isComponentComplete())
+ return;
+
d->updateHorizontalScroll();
- updateRect();//TODO: Only update rect between pos's
+ d->updateVerticalScroll();
+ update();
updateMicroFocus();
emit cursorRectangleChanged();
- if (d->cursorItem)
- d->cursorItem->setX(d->cursorToX() - d->hscroll);
+ if (d->cursorItem) {
+ QRectF r = cursorRectangle();
+ d->cursorItem->setPos(r.topLeft());
+ d->cursorItem->setHeight(r.height());
+ }
}
void QQuickTextInput::selectionChanged()
}
}
-void QQuickTextInput::q_textChanged()
-{
- Q_D(QQuickTextInput);
- emit textChanged();
- emit displayTextChanged();
- updateSize();
- d->determineHorizontalAlignment();
- d->updateHorizontalScroll();
- updateMicroFocus();
- if (hasAcceptableInput() != d->oldValidity) {
- d->oldValidity = hasAcceptableInput();
- emit acceptableInputChanged();
- }
-}
-
void QQuickTextInputPrivate::showCursor()
{
if (textNode != 0 && textNode->cursorNode() != 0)
QRectF QQuickTextInput::boundingRect() const
{
Q_D(const QQuickTextInput);
- QRectF r = QQuickImplicitSizeItem::boundingRect();
+ QRectF r = d->boundingRect;
int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->m_cursorWidth;
// Could include font max left/right bearings to either side of rectangle.
r.setRight(r.right() + cursorWidth);
+ r.translate(-d->hscroll, -d->vscroll);
return r;
}
-void QQuickTextInput::updateSize(bool needsRedraw)
-{
- Q_D(QQuickTextInput);
- int w = width();
- int h = height();
- setImplicitSize(d->calculateTextWidth(), d->calculateTextHeight());
- if (w==width() && h==height() && needsRedraw)
- update();
-}
-
void QQuickTextInput::q_canPasteChanged()
{
Q_D(QQuickTextInput);
uc[i] = QChar(0x0020);
}
- m_textLayout.setText(str);
+ if (str != orig || forceUpdate) {
+ m_textLayout.setText(str);
+ updateLayout(); // polish?
+ emit q_func()->displayTextChanged();
+ }
+}
+
+void QQuickTextInputPrivate::updateLayout()
+{
+ Q_Q(QQuickTextInput);
+
+ if (!q->isComponentComplete())
+ return;
QTextOption option = m_textLayout.textOption();
option.setTextDirection(m_layoutDirection);
option.setFlags(QTextOption::IncludeTrailingSpaces);
+ option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
m_textLayout.setTextOption(option);
+ m_textLayout.setFont(font);
+ boundingRect = QRectF();
m_textLayout.beginLayout();
- QTextLine l = m_textLayout.createLine();
+ QTextLine line = m_textLayout.createLine();
+ qreal lineWidth = q->widthValid() ? q->width() : INT_MAX;
+ qreal height = 0;
+ QTextLine firstLine = line;
+ do {
+ line.setLineWidth(lineWidth);
+ line.setPosition(QPointF(line.position().x(), height));
+ boundingRect = boundingRect.united(line.naturalTextRect());
+
+ height += line.height();
+ line = m_textLayout.createLine();
+ } while (line.isValid());
m_textLayout.endLayout();
- m_ascent = qRound(l.ascent());
- if (str != orig || forceUpdate)
- emit q_func()->displayTextChanged();
+ option.setWrapMode(QTextOption::NoWrap);
+ m_textLayout.setTextOption(option);
+
+ m_ascent = qRound(firstLine.ascent());
+ textLayoutDirty = true;
+
+ q->update();
+ q->setImplicitSize(qCeil(boundingRect.width()), qCeil(boundingRect.height()));
+
}
#ifndef QT_NO_CLIPBOARD
m_preeditCursor = 0;
m_textLayout.setPreeditArea(-1, QString());
m_textLayout.clearAdditionalFormats();
- updateDisplayText(/*force*/ true);
+ updateLayout();
}
/*!
/*!
\internal
- Returns the cursor position of the given \a x pixel value in relation
- to the displayed text. The given \a betweenOrOn specified what kind
- of cursor position is requested.
-*/
-int QQuickTextInputPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
-{
- Q_Q(const QQuickTextInput);
- QRect cr = q->boundingRect().toRect();
- x-= cr.x() - hscroll;
- return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
-}
-
-/*!
- \internal
-
Fixes the current text so that it is valid given any set validators.
Returns true if the text was changed. Otherwise returns false.
anchor = m_cursor;
m_selstart = qMin(anchor, pos);
m_selend = qMax(anchor, pos);
- updateDisplayText();
} else {
internalDeselect();
}
|| event->replacementLength() > 0;
bool cursorPositionChanged = false;
bool selectionChange = false;
+ m_preeditDirty = event->preeditString() != preeditAreaText();
if (isGettingInput) {
// If any text is being input, remove selected text.
}
}
m_textLayout.setAdditionalFormats(formats);
+
updateDisplayText(/*force*/ true);
if (cursorPositionChanged)
emitCursorPositionChanged();
if (m_textDirty) {
m_textDirty = false;
- q_func()->q_textChanged();
+ m_preeditDirty = false;
+ determineHorizontalAlignment();
+ emit q->textChanged();
}
+
+ if (m_validInput != wasValidInput)
+ emit q->acceptableInputChanged();
+ }
+ if (m_preeditDirty) {
+ m_preeditDirty = false;
+ determineHorizontalAlignment();
}
if (m_selDirty) {
m_selDirty = false;
#define QQUICKTEXTINPUT_P_H
#include "qquickimplicitsizeitem_p.h"
+#include <QtGui/qtextoption.h>
#include <QtGui/qvalidator.h>
QT_BEGIN_HEADER
{
Q_OBJECT
Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(WrapMode)
Q_ENUMS(EchoMode)
Q_ENUMS(SelectionMode)
+ Q_ENUMS(CursorPosition)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
QQuickTextInput(QQuickItem * parent=0);
~QQuickTextInput();
+ void componentComplete();
+
enum EchoMode {//To match QLineEdit::EchoMode
Normal,
NoEcho,
AlignHCenter = Qt::AlignHCenter
};
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum WrapMode {
+ NoWrap = QTextOption::NoWrap,
+ WordWrap = QTextOption::WordWrap,
+ WrapAnywhere = QTextOption::WrapAnywhere,
+ WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
+ Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
+ };
+
enum SelectionMode {
SelectCharacters,
SelectWords
CursorOnCharacter
};
+
//Auxilliary functions needed to control the TextInput from QML
- Q_INVOKABLE int positionAt(int x) const;
- Q_INVOKABLE int positionAt(int x, CursorPosition position) const;
+ Q_INVOKABLE void positionAt(QDeclarativeV8Function *args) const;
Q_INVOKABLE QRectF positionToRectangle(int pos) const;
Q_INVOKABLE void moveCursorSelection(int pos);
Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
void resetHAlign();
HAlignment effectiveHAlign() const;
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode w);
+
bool isReadOnly() const;
void setReadOnly(bool);
void selectedTextColorChanged(const QColor &color);
void fontChanged(const QFont &font);
void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapModeChanged();
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
void cursorDelegateChanged();
#endif
private Q_SLOTS:
- void updateSize(bool needsRedraw = true);
- void q_textChanged();
void selectionChanged();
void createCursor();
void updateCursorRectangle();
, textNode(0)
, m_maskData(0)
, hscroll(0)
- , oldScroll(0)
+ , vscroll(0)
, m_cursor(0)
, m_preeditCursor(0)
, m_cursorWidth(1)
, m_selend(0)
, style(QQuickText::Normal)
, hAlign(QQuickTextInput::AlignLeft)
+ , vAlign(QQuickTextInput::AlignTop)
+ , wrapMode(QQuickTextInput::NoWrap)
, mouseSelectionMode(QQuickTextInput::SelectCharacters)
, inputMethodHints(Qt::ImhNone)
, m_layoutDirection(Qt::LayoutDirectionAuto)
, m_readOnly(0)
, m_echoMode(QQuickTextInput::Normal)
, m_textDirty(0)
+ , m_preeditDirty(0)
, m_selDirty(0)
, m_validInput(1)
, m_blinkStatus(0)
void init();
void startCreatingCursor();
void updateHorizontalScroll();
+ void updateVerticalScroll();
bool determineHorizontalAlignment();
bool setHAlign(QQuickTextInput::HAlignment, bool forceAlign = false);
void mirrorChange();
QPoint tripleClickStartPoint;
QList<int> m_transactions;
QVector<Command> m_history;
+ QRectF boundingRect;
int lastSelectionStart;
int lastSelectionEnd;
int oldHeight;
int oldWidth;
int hscroll;
- int oldScroll;
+ int vscroll;
int m_cursor;
int m_preeditCursor;
int m_cursorWidth;
QQuickText::TextStyle style;
QQuickTextInput::HAlignment hAlign;
+ QQuickTextInput::VAlignment vAlign;
+ QQuickTextInput::WrapMode wrapMode;
QQuickTextInput::SelectionMode mouseSelectionMode;
Qt::InputMethodHints inputMethodHints;
Qt::LayoutDirection m_layoutDirection;
uint m_readOnly : 1;
uint m_echoMode : 2;
uint m_textDirty : 1;
+ uint m_preeditDirty : 1;
uint m_selDirty : 1;
uint m_validInput : 1;
uint m_blinkStatus : 1;
bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
- int calculateTextHeight() const { return qRound(m_textLayout.lineAt(0).height()); }
- int calculateTextWidth() const { return qRound(m_textLayout.lineAt(0).naturalTextWidth()); }
- int ascent() const { return m_ascent; }
-
void setSelection(int start, int length);
inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); }
int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
- bool inSelection(int x) const
- {
- if (m_selstart >= m_selend)
- return false;
- int pos = xToPos(x, QTextLine::CursorOnCharacter);
- return pos >= m_selstart && pos < m_selend;
+
+ int positionAt(int x, int y, QTextLine::CursorPosition position) const;
+ int positionAt(const QPointF &point, QTextLine::CursorPosition position = QTextLine::CursorBetweenCharacters) const {
+ return positionAt(point.x(), point.y(), position);
}
void removeSelection()
void home(bool mark) { moveCursor(0, mark); }
void end(bool mark) { moveCursor(q_func()->text().length(), mark); }
- int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
-
- qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); }
- qreal cursorToX() const
- {
- int cursor = m_cursor;
- if (m_preeditCursor != -1)
- cursor += m_preeditCursor;
- return cursorToX(cursor);
- }
-
void backspace();
void del();
void deselect() { internalDeselect(); finishChange(); }
void setCursorBlinkPeriod(int msec);
void resetCursorBlinkTimer();
+ void updateLayout();
+
private:
void init(const QString &txt);
void removeSelectedText();
inline void separate() { m_separator = true; }
-
// masking
void parseInputMask(const QString &maskFields);
bool isValidInput(QChar key, QChar mask) const;
Rectangle {
anchors.centerIn: parent
width: 60
- height: 20
+ height: 60
color: "green"
TextInput {
+ objectName: "text"
id: text
anchors.fill: parent
text: top.text
focus: true
objectName: "myInput"
width: 50
+ height: 100
text: "AAAAAAAAAAAAAAAAAAAAAAAAAAAA"
}
#include "../../shared/util.h"
#include <private/qinputpanel_p.h>
#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
#include <QFile>
#include <QtQuick/qquickview.h>
#include <QtGui/qguiapplication.h>
return expectfile;
}
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ T result = expr.evaluate().value<T>();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result;
+}
+
typedef QPair<int, QChar> Key;
class tst_qquicktextinput : public QObject
void width();
void font();
void color();
+ void wrap();
void selection();
void isRightToLeft_data();
void isRightToLeft();
void horizontalAlignment_data();
void horizontalAlignment();
void horizontalAlignment_RightToLeft();
+ void verticalAlignment();
void positionAt();
}
}
+void tst_qquicktextinput::wrap()
+{
+ int textHeight = 0;
+ // for specified width and wrap set true
+ {
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData("import QtQuick 2.0\nTextInput { text: \"Hello\"; wrapMode: Text.WrapAnywhere; width: 300 }", QUrl::fromLocalFile(""));
+ QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
+ textHeight = textObject->height();
+
+ QVERIFY(textObject != 0);
+ QVERIFY(textObject->wrapMode() == QQuickTextInput::WrapAnywhere);
+ QCOMPARE(textObject->width(), 300.);
+
+ delete textObject;
+ }
+
+ for (int i = 0; i < standard.count(); i++) {
+ QString componentStr = "import QtQuick 2.0\nTextInput { wrapMode: Text.WrapAnywhere; width: 30; text: \"" + standard.at(i) + "\" }";
+ QDeclarativeComponent textComponent(&engine);
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->width(), 30.);
+ QVERIFY(textObject->height() > textHeight);
+
+ int oldHeight = textObject->height();
+ textObject->setWidth(100);
+ QVERIFY(textObject->height() < oldHeight);
+
+ delete textObject;
+ }
+}
+
void tst_qquicktextinput::selection()
{
QString testStr = standard[0];
QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
QVERIFY(textInputPrivate != 0);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// implicit alignment should follow the reading direction of RTL text
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// explicitly left aligned
textInput->setHAlign(QQuickTextInput::AlignLeft);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() < canvas.width()/2);
// explicitly right aligned
textInput->setHAlign(QQuickTextInput::AlignRight);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// explicitly center aligned
textInput->setHAlign(QQuickTextInput::AlignHCenter);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignHCenter);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
- QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() < canvas.width()/2);
+ QVERIFY(textInput->boundingRect().right() > canvas.width()/2);
// reseted alignment should go back to following the text reading direction
textInput->resetHAlign();
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// mirror the text item
QQuickItemPrivate::get(textInput)->setLayoutMirror(true);
// mirrored implicit alignment should continue to follow the reading direction of the text
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// explicitly right aligned behaves as left aligned
textInput->setHAlign(QQuickTextInput::AlignRight);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignLeft);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() < canvas.width()/2);
// mirrored explicitly left aligned behaves as right aligned
textInput->setHAlign(QQuickTextInput::AlignLeft);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
// disable mirroring
QQuickItemPrivate::get(textInput)->setLayoutMirror(false);
// English text should be implicitly left aligned
textInput->setText("Hello world!");
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() < canvas.width()/2);
canvas.requestActivateWindow();
QTest::qWaitForWindowShown(&canvas);
QCOMPARE(textInput->hAlign(), QGuiApplication::keyboardInputDirection() == Qt::LeftToRight ?
QQuickTextInput::AlignLeft : QQuickTextInput::AlignRight);
if (QGuiApplication::keyboardInputDirection() == Qt::LeftToRight)
- QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() < canvas.width()/2);
else
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
textInput->setHAlign(QQuickTextInput::AlignRight);
QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
- QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
+ QVERIFY(textInput->boundingRect().left() > canvas.width()/2);
QString componentStr = "import QtQuick 2.0\nTextInput {}";
QDeclarativeComponent textComponent(&engine);
delete textObject;
}
+void tst_qquicktextinput::verticalAlignment()
+{
+ QQuickView canvas(QUrl::fromLocalFile(TESTDATA("horizontalAlignment.qml")));
+ QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
+ QVERIFY(textInput != 0);
+ canvas.show();
+
+ QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
+ QVERIFY(textInputPrivate != 0);
+
+ QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignTop);
+ QVERIFY(textInput->boundingRect().bottom() < canvas.height() / 2);
+
+ // bottom aligned
+ textInput->setVAlign(QQuickTextInput::AlignBottom);
+ QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignBottom);
+ QVERIFY(textInput->boundingRect().top () > canvas.height() / 2);
+
+ // explicitly center aligned
+ textInput->setVAlign(QQuickTextInput::AlignVCenter);
+ QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignVCenter);
+ QVERIFY(textInput->boundingRect().top() < canvas.height() / 2);
+ QVERIFY(textInput->boundingRect().bottom() > canvas.height() / 2);
+}
+
void tst_qquicktextinput::positionAt()
{
QQuickView canvas(QUrl::fromLocalFile(TESTDATA("positionAt.qml")));
// Check autoscrolled...
- int pos = textinputObject->positionAt(textinputObject->width()/2);
+ int pos = evaluate<int>(textinputObject, QString("positionAt(%1)").arg(textinputObject->width()/2));
QTextLayout layout(textinputObject->text());
layout.setFont(textinputObject->font());
QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorBetweenCharacters)").arg(x)), pos + 1);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorOnCharacter)").arg(x)), pos);
// Check without autoscroll...
textinputObject->setAutoScroll(false);
- pos = textinputObject->positionAt(textinputObject->width()/2);
+ pos = evaluate<int>(textinputObject, QString("positionAt(%1)").arg(textinputObject->width() / 2));
textLeftWidthBegin = floor(line.cursorToX(pos - 1));
textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
x = textinputObject->positionToRectangle(pos + 1).x() - 1;
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorBetweenCharacters), pos + 1);
- QCOMPARE(textinputObject->positionAt(x, QQuickTextInput::CursorOnCharacter), pos);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorBetweenCharacters)").arg(x)), pos + 1);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorOnCharacter)").arg(x)), pos);
const qreal x0 = textinputObject->positionToRectangle(pos).x();
const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
textinputObject->setText(textinputObject->text().mid(pos));
textinputObject->setCursorPosition(0);
- QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
- QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent);
+ { QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent); }
// Check all points within the preedit text return the same position.
- QCOMPARE(textinputObject->positionAt(0), 0);
- QCOMPARE(textinputObject->positionAt(x0 / 2), 0);
- QCOMPARE(textinputObject->positionAt(x0), 0);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(0)), 0);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x0 / 2)), 0);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x0)), 0);
// Verify positioning returns to normal after the preedit text.
- QCOMPARE(textinputObject->positionAt(x1), 1);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x1)), 1);
QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
+
+ { QInputMethodEvent inputEvent;
+ QGuiApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &inputEvent); }
+
+ // With wrapping.
+ textinputObject->setWrapMode(QQuickTextInput::WrapAnywhere);
+
+ const qreal y0 = line.height() / 2;
+ const qreal y1 = line.height() * 3 / 2;
+
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x0).arg(y0)), pos);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x1).arg(y0)), pos + 1);
+
+ int newLinePos = evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x0).arg(y1));
+ QVERIFY(newLinePos > pos);
+ QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x1).arg(y1)), newLinePos + 1);
}
void tst_qquicktextinput::maxLength()
layout.endLayout();
input.setWidth(line.cursorToX(5, QTextLine::Leading));
+ input.setHeight(qCeil(line.height() * 3 / 2));
QRect r;
}
// Check the cursor rectangle remains within the input bounding rect when auto scrolling.
- QVERIFY(r.left() < input.boundingRect().width());
+ QVERIFY(r.left() < input.width());
QVERIFY(r.right() >= input.width() - error);
for (int i = 6; i < text.length(); ++i) {
for (int i = text.length() - 2; i >= 0; --i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
+ QCOMPARE(r.top(), 0);
QVERIFY(r.right() >= 0);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
}
+ // Check vertical scrolling with word wrap.
+ input.setWrapMode(QQuickTextInput::WordWrap);
+ for (int i = 0; i <= 5; ++i) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+
+ QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
+ QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ QCOMPARE(r.top(), 0);
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
+ }
+
+ input.setCursorPosition(6);
+ r = input.cursorRectangle();
+ QCOMPARE(r.left(), 0);
+ QVERIFY(r.bottom() >= input.height() - error);
+
+ for (int i = 7; i < text.length(); ++i) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+ QVERIFY(r.bottom() >= input.height() - error);
+ }
+
+ for (int i = text.length() - 2; i >= 6; --i) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+ QVERIFY(r.bottom() >= input.height() - error);
+ }
+
+ for (int i = 5; i >= 0; --i) {
+ input.setCursorPosition(i);
+ r = input.cursorRectangle();
+ QCOMPARE(r.top(), 0);
+ }
+
input.setText("Hi!");
input.setHAlign(QQuickTextInput::AlignRight);
r = input.cursorRectangle();
- QVERIFY(r.left() < input.boundingRect().width());
+ QVERIFY(r.left() < input.width() + error);
QVERIFY(r.right() >= input.width() - error);
}
// check default values
QVERIFY(input->focusOnPress());
QVERIFY(!input->hasActiveFocus());
- qDebug() << &input << qApp->inputPanel()->inputItem();
QCOMPARE(qApp->inputPanel()->inputItem(), static_cast<QObject*>(0));
QCOMPARE(qApp->inputPanel()->visible(), false);
// test the text is scrolled so the preedit is visible.
sendPreeditText(preeditText.mid(0, 3), 1);
- QVERIFY(input->positionAt(0) != 0);
+ QVERIFY(evaluate<int>(input, QString("positionAt(0)")) != 0);
QVERIFY(input->cursorRectangle().left() < input->boundingRect().width());
QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
// test the text is scrolled back when the preedit is removed.
QInputMethodEvent imEvent;
QCoreApplication::sendEvent(qGuiApp->inputPanel()->inputItem(), &imEvent);
- QCOMPARE(input->positionAt(0), 0);
- QCOMPARE(input->positionAt(input->width()), 5);
+ QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(0)), 0);
+ QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(input->width())), 5);
QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
QTextLayout layout(preeditText);
input->setAutoScroll(false);
sendPreeditText(preeditText.mid(0, 3), 1);
- QCOMPARE(input->positionAt(0), 0);
- QCOMPARE(input->positionAt(input->width()), 5);
+ QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(0)), 0);
+ QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(input->width())), 5);
}
void tst_qquicktextinput::preeditCursorRectangle()
font.pointSize: { pointvalue.model.get(pointvalue.currentIndex).value }
font.pixelSize: { pixelvalue.model.get(pixelvalue.currentIndex).value }
horizontalAlignment: { halignvalue.model.get(halignvalue.currentIndex).value }
+ verticalAlignment: { valignvalue.model.get(valignvalue.currentIndex).value }
+ wrapMode: { wrapvalue.model.get(wrapvalue.currentIndex).value }
smooth: { smoothvalue.model.get(smoothvalue.currentIndex).value }
selectByMouse: { mousevalue.model.get(mousevalue.currentIndex).value }
echoMode: { echovalue.model.get(echovalue.currentIndex).value }