}
/*!
+ Sets the tentative commit string to \a tentativeCommitString.
+
+ The tentative commit string is what the preedit string is expected to be committed as.
+ The string can be used within the editor to trigger code that reacts on text changes such as validators.
+*/
+void QInputMethodEvent::setTentativeCommitString(const QString &tentativeCommitString)
+{
+ tentativeCommit = tentativeCommitString;
+}
+
+/*!
\fn const QList<Attribute> &QInputMethodEvent::attributes() const
Returns the list of attributes passed to the QInputMethodEvent
\sa replacementStart(), setCommitString()
*/
+/*!
+ \fn const QString &tentativeCommitString() const
+
+ Returns the text as which preedit string is expected to be committed as.
+ The string can be used within the editor to trigger code that reacts on text changes such as validators.
+
+ \sa setTentativeCommitString()
+*/
/*! \class QInputMethodQueryEvent
QInputMethodEvent();
QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes);
void setCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
+ void setTentativeCommitString(const QString &tentativeCommitString);
inline const QList<Attribute> &attributes() const { return attrs; }
inline const QString &preeditString() const { return preedit; }
inline const QString &commitString() const { return commit; }
inline int replacementStart() const { return replace_from; }
inline int replacementLength() const { return replace_length; }
+ inline const QString &tentativeCommitString() const { return tentativeCommit; }
QInputMethodEvent(const QInputMethodEvent &other);
QString commit;
int replace_from;
int replace_length;
+ QString tentativeCommit;
};
class Q_GUI_EXPORT QInputMethodQueryEvent : public QEvent
case Qt::ImCursorPosition:
return QVariant(d->control->cursor());
case Qt::ImSurroundingText:
- return QVariant(text());
+ return QVariant(d->control->realText());
case Qt::ImCurrentSelection:
return QVariant(selectedText());
case Qt::ImMaximumTextLength:
*/
void QWidgetLineControl::processInputMethodEvent(QInputMethodEvent *event)
{
- int priorState = 0;
+ int priorState = -1;
bool isGettingInput = !event->commitString().isEmpty()
|| event->preeditString() != preeditAreaText()
|| event->replacementLength() > 0;
emitCursorPositionChanged();
else if (m_preeditCursor != oldPreeditCursor)
emit updateMicroFocus();
- if (isGettingInput)
+
+ bool tentativeCommitChanged = (m_tentativeCommit != event->tentativeCommitString());
+ if (tentativeCommitChanged) {
+ m_textDirty = true;
+ m_tentativeCommit = event->tentativeCommitString();
+ }
+
+ if (isGettingInput || tentativeCommitChanged)
finishChange(priorState);
+
if (selectionChange)
emit selectionChanged();
}
m_validInput = true;
#ifndef QT_NO_VALIDATOR
if (m_validator) {
- m_validInput = false;
QString textCopy = m_text;
int cursorCopy = m_cursor;
m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
return true;
}
m_cursor = cursorCopy;
+
+ if (!m_tentativeCommit.isEmpty()) {
+ textCopy.insert(m_cursor, m_tentativeCommit);
+ bool validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
+ if (!validInput)
+ m_tentativeCommit.clear();
+ }
+ } else {
+ m_tentativeCommit.clear();
}
}
#endif
QString text() const
{
+ QString content = m_text;
+ if (!m_tentativeCommit.isEmpty())
+ content.insert(m_cursor, m_tentativeCommit);
+ QString res = m_maskData ? stripString(content) : content;
+ return (res.isNull() ? QString::fromLatin1("") : res);
+ }
+ // like text() but doesn't include preedit
+ QString realText() const
+ {
QString res = m_maskData ? stripString(m_text) : m_text;
return (res.isNull() ? QString::fromLatin1("") : res);
}
- void setText(const QString &txt) { internalSetText(txt, -1, false); }
+ void setText(const QString &txt)
+ {
+ if (composeMode())
+ qApp->inputPanel()->reset();
+ m_tentativeCommit.clear();
+ internalSetText(txt, -1, false);
+ }
+
QString displayText() const { return m_textLayout.text(); }
void backspace();
int m_cursor;
int m_preeditCursor;
int m_cursorWidth;
+ QString m_tentativeCommit;
Qt::LayoutDirection m_layoutDirection;
uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
uint m_separator : 1;
void selectAndCursorPosition();
void inputMethodSelection();
+ void inputMethodTentativeCommit();
protected slots:
void editingFinished();
QCOMPARE(testWidget->selectionStart(), 12);
}
+void tst_QLineEdit::inputMethodTentativeCommit()
+{
+ // test that basic tentative commit gets to text property on preedit state
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("test", attributes);
+ event.setTentativeCommitString("test");
+ QApplication::sendEvent(testWidget, &event);
+ QCOMPARE(testWidget->text(), QString("test"));
+
+ // tentative commit not allowed present in surrounding text
+ QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
+ QApplication::sendEvent(testWidget, &queryEvent);
+ QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
+
+ // if text with tentative commit does not validate, not allowed to be part of text property
+ testWidget->setText(""); // ensure input state is reset
+ QValidator *validator = new QIntValidator(0, 100);
+ testWidget->setValidator(validator);
+ QApplication::sendEvent(testWidget, &event);
+ QCOMPARE(testWidget->text(), QString(""));
+ testWidget->setValidator(0);
+ delete validator;
+}
+
+
QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc"