qt5base-lts/tests/auto/qlineedit/tst_qlineedit.cpp
Andrew den Exter 06e2ce51d1 Fix delayed password masking mid-string.
Unmask the last character typed, not the last character in the string.

Change-Id: I9c70d2347bf878c18ab0a7f4ea76f755ca19a85c
Task-number: QTBUG-17003
Reviewed-by: Alan Alpert
(cherry picked from commit b98e9e69dd8ba33d5f01b9518d95b63b86c4b443)
Reviewed-on: http://codereview.qt.nokia.com/4165
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
2011-09-05 04:07:49 +02:00

3919 lines
120 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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.
**
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include "../../shared/util.h"
#include "qlineedit.h"
#include "qapplication.h"
#include "qstringlist.h"
#include "qstyle.h"
#include "qvalidator.h"
#include "qcompleter.h"
#include "qstandarditemmodel.h"
#ifndef QT_NO_CLIPBOARD
#include "qclipboard.h"
#endif
#ifdef Q_WS_MAC
#include <Carbon/Carbon.h> // For the random function.
#include <cstdlib> // For the random function.
#endif
#include <qlineedit.h>
#include <qmenu.h>
#include <qlayout.h>
#include <qspinbox.h>
#include <qdebug.h>
//TESTED_CLASS=
//TESTED_FILES=
#include "qcommonstyle.h"
#include "qstyleoption.h"
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE
class StyleOptionTestStyle : public QCommonStyle
{
private:
bool readOnly;
public:
inline StyleOptionTestStyle() : QCommonStyle(), readOnly(false)
{
}
inline void setReadOnly(bool readOnly)
{
this->readOnly = readOnly;
}
inline void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *,
const QWidget *) const
{
switch (pe) {
case PE_PanelLineEdit:
if (readOnly)
QVERIFY(opt->state & QStyle::State_ReadOnly);
else
QVERIFY(!(opt->state & QStyle::State_ReadOnly));
break;
default:
break;
}
}
};
class tst_QLineEdit : public QObject
{
Q_OBJECT
public:
enum EventStates { Press, Release, Click };
tst_QLineEdit();
virtual ~tst_QLineEdit();
public slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
private slots:
void getSetCheck();
void experimental();
void upperAndLowercase();
void setInputMask_data();
void setInputMask();
void inputMask_data();
void inputMask();
void clearInputMask();
void keypress_inputMask_data();
void keypress_inputMask();
void inputMaskAndValidator_data();
void inputMaskAndValidator();
void hasAcceptableInputMask_data();
void hasAcceptableInputMask();
void hasAcceptableInputValidator();
void redo_data();
void redo();
void isRedoAvailable();
void undo_data();
void undo();
void isUndoAvailable();
void undo_keypressevents_data();
void undo_keypressevents();
#ifndef QT_NO_CLIPBOARD
void QTBUG5786_undoPaste();
#endif
void clear();
void text_data();
void text();
void textMask_data();
void textMask();
void maskCharacter();
void maskCharacter_data();
void setText();
void displayText_data();
void displayText();
void setEchoMode();
void echoMode();
void passwordEchoOnEdit();
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void passwordEchoDelay();
#endif
void maxLength_mask_data();
void maxLength_mask();
void maxLength_data();
void maxLength();
void setMaxLength();
void isReadOnly();
void setReadOnly();
void cursorPosition();
void cursorPositionChanged_data();
void cursorPositionChanged();
void selectedText();
void hasSelectedText();
void deleteSelectedText();
void textChangedAndTextEdited();
void returnPressed();
void returnPressed_maskvalidator_data();
void returnPressed_maskvalidator();
void setValidator();
void validator();
void clearValidator();
void setValidator_QIntValidator_data();
void setValidator_QIntValidator();
void frame_data();
void frame();
void leftKeyOnSelectedText();
void setAlignment_data();
void setAlignment();
void alignment();
void isModified();
void edited();
void setEdited();
void insert();
void setSelection_data();
void setSelection();
#ifndef QT_NO_CLIPBOARD
void cut();
void copy();
void paste();
#endif
void maxLengthAndInputMask();
void returnPressedKeyEvent();
void keepSelectionOnTabFocusIn();
void readOnlyStyleOption();
void validateOnFocusOut();
void editInvalidText();
void charWithAltOrCtrlModifier();
void inlineCompletion();
void noTextEditedOnClear();
void cursor();
void textMargin_data();
void textMargin();
// task-specific tests:
void task180999_focus();
void task174640_editingFinished();
#ifndef QT_NO_COMPLETER
void task198789_currentCompletion();
void task210502_caseInsensitiveInlineCompletion();
#endif
void task229938_dontEmitChangedWhenTextIsNotChanged();
void task233101_cursorPosAfterInputMethod_data();
void task233101_cursorPosAfterInputMethod();
void task241436_passwordEchoOnEditRestoreEchoMode();
void task248948_redoRemovedSelection();
void taskQTBUG_4401_enterKeyClearsPassword();
void taskQTBUG_4679_moveToStartEndOfBlock();
void taskQTBUG_4679_selectToStartEndOfBlock();
#ifndef QT_NO_CONTEXTMENU
void taskQTBUG_7902_contextMenuCrash();
#endif
void taskQTBUG_7395_readOnlyShortcut();
void QTBUG697_paletteCurrentColorGroup();
void QTBUG13520_textNotVisible();
void bidiVisualMovement_data();
void bidiVisualMovement();
void bidiLogicalMovement_data();
void bidiLogicalMovement();
void selectAndCursorPosition();
void inputMethodSelection();
protected slots:
void editingFinished();
void onTextChanged( const QString &newString );
void onTextEdited( const QString &newString );
void onReturnPressed();
void onSelectionChanged();
void onCursorPositionChanged(int oldpos, int newpos);
private:
// keyClicks(..) is moved to QtTestCase
void psKeyClick(QWidget *target, Qt::Key key, Qt::KeyboardModifiers pressState = 0);
void psKeyClick(QTestEventList &keys, Qt::Key key, Qt::KeyboardModifiers pressState = 0);
bool validInput;
QString changed_string;
int changed_count;
int edited_count;
int return_count;
int selection_count;
int lastCursorPos;
int newCursorPos;
QLineEdit *testWidget;
};
typedef QList<int> IntList;
Q_DECLARE_METATYPE(IntList)
Q_DECLARE_METATYPE(QLineEdit::EchoMode)
// Testing get/set functions
void tst_QLineEdit::getSetCheck()
{
QLineEdit obj1;
// const QValidator * QLineEdit::validator()
// void QLineEdit::setValidator(const QValidator *)
QIntValidator *var1 = new QIntValidator(0);
obj1.setValidator(var1);
QCOMPARE((const QValidator *)var1, obj1.validator());
obj1.setValidator((QValidator *)0);
QCOMPARE((const QValidator *)0, obj1.validator());
delete var1;
// bool QLineEdit::dragEnabled()
// void QLineEdit::setDragEnabled(bool)
obj1.setDragEnabled(false);
QCOMPARE(false, obj1.dragEnabled());
obj1.setDragEnabled(true);
QCOMPARE(true, obj1.dragEnabled());
}
tst_QLineEdit::tst_QLineEdit()
{
validInput = false;
}
tst_QLineEdit::~tst_QLineEdit()
{
}
void tst_QLineEdit::initTestCase()
{
testWidget = new QLineEdit(0);
testWidget->setObjectName("testWidget");
connect(testWidget, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorPositionChanged(int, int)));
connect(testWidget, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged(const QString&)));
connect(testWidget, SIGNAL(textEdited(const QString&)), this, SLOT(onTextEdited(const QString&)));
connect(testWidget, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
connect(testWidget, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
connect(testWidget, SIGNAL(editingFinished()), this, SLOT(editingFinished()));
testWidget->resize(200,50);
testWidget->show();
QApplication::setActiveWindow(testWidget);
#ifdef Q_WS_X11
// to be safe and avoid failing setFocus with window managers
qt_x11_wait_for_window_manager(testWidget);
#endif
QTRY_VERIFY(testWidget->hasFocus());
changed_count = 0;
edited_count = 0;
selection_count = 0;
}
void tst_QLineEdit::cleanupTestCase()
{
delete testWidget;
}
void tst_QLineEdit::init()
{
return_count = 0;
testWidget->clear();
testWidget->setEchoMode(QLineEdit::Normal);
testWidget->setMaxLength(32767);
testWidget->setReadOnly(false);
testWidget->setText("");
testWidget->setInputMask("");
testWidget->setFrame(true);
testWidget->setValidator(0);
testWidget->setDragEnabled(true);
}
void tst_QLineEdit::cleanup()
{
}
void tst_QLineEdit::experimental()
{
QIntValidator intValidator(3, 7, 0);
testWidget->setValidator(&intValidator);
testWidget->setText("");
// test the order of setting these
testWidget->setInputMask("");
testWidget->setText("abc123");
testWidget->setInputMask("000.000.000.000");
QCOMPARE(testWidget->text(), QString("123..."));
testWidget->setText("");
}
void tst_QLineEdit::upperAndLowercase()
{
testWidget->setInputMask("");
testWidget->setText("");
QTest::keyClicks(testWidget, "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?");
qApp->processEvents();
QCOMPARE(testWidget->text(), QString("aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"));
}
void tst_QLineEdit::setInputMask_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<QString>("input");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("expectedDisplay");
QTest::addColumn<bool>("insert_text");
// both keyboard and insert()
for (int i=0; i<2; i++) {
bool insert_text = i==0 ? false : true;
QString insert_mode = "keys ";
if (insert_text)
insert_mode = "insert ";
QTest::newRow(QString(insert_mode + "ip_localhost").toLatin1())
<< QString("000.000.000.000")
<< QString("127.0.0.1")
<< QString("127.0.0.1")
<< QString("127.0 .0 .1 ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "mac").toLatin1())
<< QString("HH:HH:HH:HH:HH:HH;#")
<< QString("00:E0:81:21:9E:8E")
<< QString("00:E0:81:21:9E:8E")
<< QString("00:E0:81:21:9E:8E")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "mac2").toLatin1())
<< QString("<HH:>HH:!HH:HH:HH:HH;#")
<< QString("AAe081219E8E")
<< QString("aa:E0:81:21:9E:8E")
<< QString("aa:E0:81:21:9E:8E")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "byte").toLatin1())
<< QString("BBBBBBBB;0")
<< QString("11011001")
<< QString("11111")
<< QString("11011001")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "halfbytes").toLatin1())
<< QString("bbbb.bbbb;-")
<< QString("110. 0001")
<< QString("110.0001")
<< QString("110-.0001")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "blank char same type as content").toLatin1())
<< QString("000.000.000.000;0")
<< QString("127.0.0.1")
<< QString("127...1")
<< QString("127.000.000.100")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "parts of ip_localhost").toLatin1())
<< QString("000.000.000.000")
<< QString(".0.0.1")
<< QString(".0.0.1")
<< QString(" .0 .0 .1 ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "ip_null").toLatin1())
<< QString("000.000.000.000")
<< QString()
<< QString("...")
<< QString(" . . . ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "ip_null_hash").toLatin1())
<< QString("000.000.000.000;#")
<< QString()
<< QString("...")
<< QString("###.###.###.###")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "ip_overflow").toLatin1())
<< QString("000.000.000.000")
<< QString("1234123412341234")
<< QString("123.412.341.234")
<< QString("123.412.341.234")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "uppercase").toLatin1())
<< QString(">AAAA")
<< QString("AbCd")
<< QString("ABCD")
<< QString("ABCD")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "lowercase").toLatin1())
<< QString("<AAAA")
<< QString("AbCd")
<< QString("abcd")
<< QString("abcd")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "nocase").toLatin1())
<< QString("!AAAA")
<< QString("AbCd")
<< QString("AbCd")
<< QString("AbCd")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "nocase1").toLatin1())
<< QString("!A!A!A!A")
<< QString("AbCd")
<< QString("AbCd")
<< QString("AbCd")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "nocase2").toLatin1())
<< QString("AAAA")
<< QString("AbCd")
<< QString("AbCd")
<< QString("AbCd")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "reserved").toLatin1())
<< QString("{n}[0]")
<< QString("A9")
<< QString("A9")
<< QString("A9")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "escape01").toLatin1())
<< QString("\\N\\n00")
<< QString("9")
<< QString("Nn9")
<< QString("Nn9 ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "escape02").toLatin1())
<< QString("\\\\00")
<< QString("0")
<< QString("\\0")
<< QString("\\0 ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "escape03").toLatin1())
<< QString("\\(00\\)")
<< QString("0")
<< QString("(0)")
<< QString("(0 )")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "upper_lower_nocase1").toLatin1())
<< QString(">AAAA<AAAA!AAAA")
<< QString("AbCdEfGhIjKl")
<< QString("ABCDefghIjKl")
<< QString("ABCDefghIjKl")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "upper_lower_nocase2").toLatin1())
<< QString(">aaaa<aaaa!aaaa")
<< QString("AbCdEfGhIjKl")
<< QString("ABCDefghIjKl")
<< QString("ABCDefghIjKl")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case1").toLatin1())
<< QString(">A<A<A>A>A<A!A!A")
<< QString("AbCdEFGH")
<< QString("AbcDEfGH")
<< QString("AbcDEfGH")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case2").toLatin1())
<< QString(">A<A<A>A>A<A!A!A")
<< QString("aBcDefgh")
<< QString("AbcDEfgh")
<< QString("AbcDEfgh")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case3").toLatin1())
<< QString(">a<a<a>a>a<a!a!a")
<< QString("AbCdEFGH")
<< QString("AbcDEfGH")
<< QString("AbcDEfGH")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case4").toLatin1())
<< QString(">a<a<a>a>a<a!a!a")
<< QString("aBcDefgh")
<< QString("AbcDEfgh")
<< QString("AbcDEfgh")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case5").toLatin1())
<< QString(">H<H<H>H>H<H!H!H")
<< QString("aBcDef01")
<< QString("AbcDEf01")
<< QString("AbcDEf01")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "exact_case6").toLatin1())
<< QString(">h<h<h>h>h<h!h!h")
<< QString("aBcDef92")
<< QString("AbcDEf92")
<< QString("AbcDEf92")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "illegal_keys1").toLatin1())
<< QString("AAAAAAAA")
<< QString("A2#a;.0!")
<< QString("Aa")
<< QString("Aa ")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "illegal_keys2").toLatin1())
<< QString("AAAA")
<< QString("f4f4f4f4")
<< QString("ffff")
<< QString("ffff")
<< bool(insert_text);
QTest::newRow(QString(insert_mode + "blank=input").toLatin1())
<< QString("9999;0")
<< QString("2004")
<< QString("2004")
<< QString("2004")
<< bool(insert_text);
}
}
void tst_QLineEdit::setInputMask()
{
QFETCH(QString, mask);
QFETCH(QString, input);
QFETCH(QString, expectedText);
QFETCH(QString, expectedDisplay);
QFETCH(bool, insert_text);
QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
// First set the input mask
testWidget->setInputMask(mask);
// then either insert using insert() or keyboard
if (insert_text) {
testWidget->insert(input);
} else {
psKeyClick(testWidget, Qt::Key_Home);
for (int i=0; i<input.length(); i++)
QTest::keyClick(testWidget, input.at(i).toLatin1());
}
QCOMPARE(testWidget->text(), expectedText);
QCOMPARE(testWidget->displayText(), expectedDisplay);
}
void tst_QLineEdit::inputMask_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<QString>("expectedMask");
// if no mask is set a nul string should be returned
QTest::newRow("") << QString("") << QString();
QTest::newRow("") << QString() << QString();
// try different masks
QTest::newRow("") << QString("000.000.000.000") << QString("000.000.000.000; ");
QTest::newRow("") << QString("000.000.000.000;#") << QString("000.000.000.000;#");
QTest::newRow("") << QString("AAA.aa.999.###;") << QString("AAA.aa.999.###; ");
QTest::newRow("") << QString(">abcdef<GHIJK") << QString(">abcdef<GHIJK; ");
// QTest::newRow("") << QString() << QString();
// set an invalid input mask...
// the current behaviour is that this exact (faulty) string is returned.
QTest::newRow("") << QString("ABCDEFGHIKLMNOP;") << QString("ABCDEFGHIKLMNOP; ");
// verify that we can unset the mask again
QTest::newRow("") << QString("") << QString();
}
void tst_QLineEdit::inputMask()
{
QFETCH(QString, mask);
QFETCH(QString, expectedMask);
testWidget->setInputMask(mask);
QCOMPARE(testWidget->inputMask(), expectedMask);
}
void tst_QLineEdit::clearInputMask()
{
testWidget->setInputMask("000.000.000.000");
QVERIFY(testWidget->inputMask() != QString::null);
testWidget->setInputMask(QString::null);
QCOMPARE(testWidget->inputMask(), QString());
}
void tst_QLineEdit::keypress_inputMask_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("expectedDisplayText");
{
QTestEventList keys;
// inserting 'A1.2B'
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_Period);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_B);
QTest::newRow("jumping on period(separator)") << QString("000.000;_") << keys << QString("1.2") << QString("1__.2__");
}
{
QTestEventList keys;
// inserting 'A1.2B'
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_0);
keys.addKeyClick(Qt::Key_Exclam);
keys.addKeyClick('P');
keys.addKeyClick(Qt::Key_3);
QTest::newRow("jumping on input") << QString("D0.AA.XX.AA.00;_") << keys << QString("0..!P..3") << QString("_0.__.!P.__.3_");
}
{
QTestEventList keys;
// pressing delete
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_Delete);
QTest::newRow("delete") << QString("000.000;_") << keys << QString(".") << QString("___.___");
}
{
QTestEventList keys;
// selecting all and delete
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_End, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Delete);
QTest::newRow("deleting all") << QString("000.000;_") << keys << QString(".") << QString("___.___");
}
{
QTestEventList keys;
// inserting '12.12' then two backspaces
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_Period);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_Backspace);
keys.addKeyClick(Qt::Key_Backspace);
QTest::newRow("backspace") << QString("000.000;_") << keys << QString("12.") << QString("12_.___");
}
{
QTestEventList keys;
// inserting '12ab'
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB");
}
}
void tst_QLineEdit::keypress_inputMask()
{
QFETCH(QString, mask);
QFETCH(QTestEventList, keys);
QFETCH(QString, expectedText);
QFETCH(QString, expectedDisplayText);
testWidget->setInputMask(mask);
keys.simulate(testWidget);
QCOMPARE(testWidget->text(), expectedText);
QCOMPARE(testWidget->displayText(), expectedDisplayText);
}
void tst_QLineEdit::hasAcceptableInputMask_data()
{
QTest::addColumn<QString>("optionalMask");
QTest::addColumn<QString>("requiredMask");
QTest::addColumn<QString>("invalid");
QTest::addColumn<QString>("valid");
QTest::newRow("Alphabetic optional and required")
<< QString("aaaa") << QString("AAAA") << QString("ab") << QString("abcd");
QTest::newRow("Alphanumeric optional and require")
<< QString("nnnn") << QString("NNNN") << QString("R2") << QString("R2D2");
QTest::newRow("Any optional and required")
<< QString("xxxx") << QString("XXXX") << QString("+-") << QString("+-*/");
QTest::newRow("Numeric (0-9) required")
<< QString("0000") << QString("9999") << QString("11") << QString("1138");
QTest::newRow("Numeric (1-9) optional and required")
<< QString("dddd") << QString("DDDD") << QString("12") << QString("1234");
}
void tst_QLineEdit::hasAcceptableInputMask()
{
QFocusEvent lostFocus(QEvent::FocusOut);
QFETCH(QString, optionalMask);
QFETCH(QString, requiredMask);
QFETCH(QString, invalid);
QFETCH(QString, valid);
// test that invalid input (for required) work for optionalMask
testWidget->setInputMask(optionalMask);
validInput = false;
testWidget->setText(invalid);
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(validInput);
// at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
// test requiredMask
testWidget->setInputMask(requiredMask);
validInput = true;
testWidget->setText(invalid);
validInput = testWidget->hasAcceptableInput();
QVERIFY(!validInput);
validInput = false;
testWidget->setText(valid);
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(validInput);
}
static const int chars = 8;
class ValidatorWithFixup : public QValidator
{
public:
ValidatorWithFixup(QWidget *parent = 0)
: QValidator(parent)
{}
QValidator::State validate(QString &str, int &) const
{
const int s = str.size();
if (s < chars) {
return Intermediate;
} else if (s > chars) {
return Invalid;
}
return Acceptable;
}
void fixup(QString &str) const
{
str = str.leftJustified(chars, 'X', true);
}
};
void tst_QLineEdit::hasAcceptableInputValidator()
{
QFocusEvent lostFocus(QEvent::FocusOut);
ValidatorWithFixup val;
testWidget->setValidator(&val);
testWidget->setText("foobar");
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(testWidget->hasAcceptableInput());
}
void tst_QLineEdit::maskCharacter_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<QString>("input");
QTest::addColumn<bool>("expectedValid");
QTest::newRow("Hex") << QString("H")
<< QString("0123456789abcdefABCDEF") << true;
QTest::newRow("hex") << QString("h")
<< QString("0123456789abcdefABCDEF") << true;
QTest::newRow("HexInvalid") << QString("H")
<< QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
<< false;
QTest::newRow("hexInvalid") << QString("h")
<< QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ")
<< false;
QTest::newRow("Bin") << QString("B")
<< QString("01") << true;
QTest::newRow("bin") << QString("b")
<< QString("01") << true;
QTest::newRow("BinInvalid") << QString("B")
<< QString("23456789qwertyuiopasdfghjklzxcvbnm")
<< false;
QTest::newRow("binInvalid") << QString("b")
<< QString("23456789qwertyuiopasdfghjklzxcvbnm")
<< false;
}
void tst_QLineEdit::maskCharacter()
{
QFETCH(QString, mask);
QFETCH(QString, input);
QFETCH(bool, expectedValid);
QFocusEvent lostFocus(QEvent::FocusOut);
testWidget->setInputMask(mask);
for (int i = 0; i < input.size(); ++i) {
QString in = QString(input.at(i));
QString expected = expectedValid ? in : QString();
testWidget->setText(QString(input.at(i)));
qApp->sendEvent(testWidget, &lostFocus);
QCOMPARE(testWidget->text(), expected);
}
}
#define NORMAL 0
#define REPLACE_UNTIL_END 1
void tst_QLineEdit::undo_data()
{
QTest::addColumn<QStringList>("insertString");
QTest::addColumn<IntList>("insertIndex");
QTest::addColumn<IntList>("insertMode");
QTest::addColumn<QStringList>("expectedString");
QTest::addColumn<bool>("use_keys");
for (int i=0; i<2; i++) {
QString keys_str = "keyboard";
bool use_keys = true;
if (i==0) {
keys_str = "insert";
use_keys = false;
}
{
IntList insertIndex;
IntList insertMode;
QStringList insertString;
QStringList expectedString;
insertIndex << -1;
insertMode << NORMAL;
insertString << "1";
insertIndex << -1;
insertMode << NORMAL;
insertString << "5";
insertIndex << 1;
insertMode << NORMAL;
insertString << "3";
insertIndex << 1;
insertMode << NORMAL;
insertString << "2";
insertIndex << 3;
insertMode << NORMAL;
insertString << "4";
expectedString << "12345";
expectedString << "1235";
expectedString << "135";
expectedString << "15";
expectedString << "";
QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
insertString <<
insertIndex <<
insertMode <<
expectedString <<
bool(use_keys);
}
{
IntList insertIndex;
IntList insertMode;
QStringList insertString;
QStringList expectedString;
insertIndex << -1;
insertMode << NORMAL;
insertString << "World"; // World
insertIndex << 0;
insertMode << NORMAL;
insertString << "Hello"; // HelloWorld
insertIndex << 0;
insertMode << NORMAL;
insertString << "Well"; // WellHelloWorld
insertIndex << 9;
insertMode << NORMAL;
insertString << "There"; // WellHelloThereWorld;
expectedString << "WellHelloThereWorld";
expectedString << "WellHelloWorld";
expectedString << "HelloWorld";
expectedString << "World";
expectedString << "";
QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
insertString <<
insertIndex <<
insertMode <<
expectedString <<
bool(use_keys);
}
{
IntList insertIndex;
IntList insertMode;
QStringList insertString;
QStringList expectedString;
insertIndex << -1;
insertMode << NORMAL;
insertString << "Ensuring";
insertIndex << -1;
insertMode << NORMAL;
insertString << " instan";
insertIndex << 9;
insertMode << NORMAL;
insertString << "an ";
insertIndex << 10;
insertMode << REPLACE_UNTIL_END;
insertString << " unique instance.";
expectedString << "Ensuring a unique instance.";
expectedString << "Ensuring an instan";
expectedString << "Ensuring instan";
expectedString << "";
QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
insertString <<
insertIndex <<
insertMode <<
expectedString <<
bool(use_keys);
}
}
}
void tst_QLineEdit::undo()
{
QFETCH(QStringList, insertString);
QFETCH(IntList, insertIndex);
QFETCH(IntList, insertMode);
QFETCH(QStringList, expectedString);
QFETCH(bool, use_keys);
QVERIFY(!testWidget->isUndoAvailable());
int i;
// STEP 1: First build up an undo history by inserting or typing some strings...
for (i=0; i<insertString.size(); ++i) {
if (insertIndex[i] > -1)
testWidget->setCursorPosition(insertIndex[i]);
// experimental stuff
if (insertMode[i] == REPLACE_UNTIL_END) {
testWidget->setSelection(insertIndex[i], 8);
// This is what I actually want...
// QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
}
if (use_keys)
QTest::keyClicks(testWidget, insertString[i]);
else
testWidget->insert(insertString[i]);
}
// STEP 2: Next call undo several times and see if we can restore to the previous state
for (i=0; i<expectedString.size()-1; ++i) {
QCOMPARE(testWidget->text(), expectedString[i]);
QVERIFY(testWidget->isUndoAvailable());
testWidget->undo();
}
// STEP 3: Verify that we have undone everything
QVERIFY(!testWidget->isUndoAvailable());
QVERIFY(testWidget->text().isEmpty());
#ifdef Q_WS_WIN
// Repeat the test using shortcut instead of undo()
for (i=0; i<insertString.size(); ++i) {
if (insertIndex[i] > -1)
testWidget->setCursorPosition(insertIndex[i]);
if (insertMode[i] == REPLACE_UNTIL_END) {
testWidget->setSelection(insertIndex[i], 8);
}
if (use_keys)
QTest::keyClicks(testWidget, insertString[i]);
else
testWidget->insert(insertString[i]);
}
for (i=0; i<expectedString.size()-1; ++i) {
QCOMPARE(testWidget->text(), expectedString[i]);
QVERIFY(testWidget->isUndoAvailable());
QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier);
}
#endif
}
void tst_QLineEdit::isUndoAvailable()
{
DEPENDS_ON("undo");
}
void tst_QLineEdit::redo_data()
{
QTest::addColumn<QStringList>("insertString");
QTest::addColumn<IntList>("insertIndex");
QTest::addColumn<QStringList>("expectedString");
{
IntList insertIndex;
QStringList insertString;
QStringList expectedString;
insertIndex << -1;
insertString << "World"; // World
insertIndex << 0;
insertString << "Hello"; // HelloWorld
insertIndex << 0;
insertString << "Well"; // WellHelloWorld
insertIndex << 9;
insertString << "There"; // WellHelloThereWorld;
expectedString << "World";
expectedString << "HelloWorld";
expectedString << "WellHelloWorld";
expectedString << "WellHelloThereWorld";
QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
}
}
void tst_QLineEdit::redo()
{
QFETCH(QStringList, insertString);
QFETCH(IntList, insertIndex);
QFETCH(QStringList, expectedString);
QVERIFY(!testWidget->isUndoAvailable());
QVERIFY(!testWidget->isRedoAvailable());
int i;
// inserts the diff strings at diff positions
for (i=0; i<insertString.size(); ++i) {
if (insertIndex[i] > -1)
testWidget->setCursorPosition(insertIndex[i]);
testWidget->insert(insertString[i]);
}
QVERIFY(!testWidget->isRedoAvailable());
// undo everything
while (!testWidget->text().isEmpty())
testWidget->undo();
for (i=0; i<expectedString.size(); ++i) {
QVERIFY(testWidget->isRedoAvailable());
testWidget->redo();
QCOMPARE(testWidget->text() , expectedString[i]);
}
QVERIFY(!testWidget->isRedoAvailable());
#ifdef Q_WS_WIN
// repeat test, this time using shortcuts instead of undo()/redo()
while (!testWidget->text().isEmpty())
QTest::keyClick(testWidget, Qt::Key_Backspace, Qt::AltModifier);
for (i = 0; i < expectedString.size(); ++i) {
QVERIFY(testWidget->isRedoAvailable());
QTest::keyClick(testWidget, Qt::Key_Backspace,
Qt::ShiftModifier | Qt::AltModifier);
QCOMPARE(testWidget->text() , expectedString[i]);
}
QVERIFY(!testWidget->isRedoAvailable());
#endif
}
void tst_QLineEdit::isRedoAvailable()
{
DEPENDS_ON("redo");
}
void tst_QLineEdit::undo_keypressevents_data()
{
QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<QStringList>("expectedString");
{
QTestEventList keys;
QStringList expectedString;
keys.addKeyClick('A');
keys.addKeyClick('F');
keys.addKeyClick('R');
keys.addKeyClick('A');
keys.addKeyClick('I');
keys.addKeyClick('D');
psKeyClick(keys, Qt::Key_Home);
keys.addKeyClick('V');
keys.addKeyClick('E');
keys.addKeyClick('R');
keys.addKeyClick('Y');
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick('B');
keys.addKeyClick('E');
psKeyClick(keys, Qt::Key_End);
keys.addKeyClick(Qt::Key_Exclam);
expectedString << "BEVERYAFRAID!";
expectedString << "BEVERYAFRAID";
expectedString << "VERYAFRAID";
expectedString << "AFRAID";
QTest::newRow("Inserts and moving cursor") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting '1234'
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
keys.addKeyClick(Qt::Key_4);
psKeyClick(keys, Qt::Key_Home);
// skipping '12'
keys.addKeyClick(Qt::Key_Right);
keys.addKeyClick(Qt::Key_Right);
// selecting '34'
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
// deleting '34'
keys.addKeyClick(Qt::Key_Delete);
expectedString << "12";
expectedString << "1234";
QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting 'AB12'
keys.addKeyClick('A');
keys.addKeyClick('B');
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
psKeyClick(keys, Qt::Key_Home);
// selecting 'AB'
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
// deleting 'AB'
keys.addKeyClick(Qt::Key_Delete);
// undoing deletion of 'AB'
keys.addKeyClick(Qt::Key_Z, Qt::ControlModifier);
// unselect any current selection
keys.addKeyClick(Qt::Key_Right);
#ifdef Q_WS_WIN //Mac has a specialcase to handle jumping to the end of a selection
keys.addKeyClick(Qt::Key_Left);
#endif
// selecting '12'
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Right, Qt::ShiftModifier);
// deleting '12'
keys.addKeyClick(Qt::Key_Delete);
expectedString << "AB";
expectedString << "AB12";
QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting 'ABCD'
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_D);
//move left two
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick(Qt::Key_Left);
// inserting '1234'
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
keys.addKeyClick(Qt::Key_4);
// selecting '1234'
keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
keys.addKeyClick(Qt::Key_Left, Qt::ShiftModifier);
// overwriting '1234' with '5'
keys.addKeyClick(Qt::Key_5);
// undoing deletion of 'AB'
keys.addKeyClick(Qt::Key_Z, Qt::ControlModifier);
// overwriting '1234' with '6'
keys.addKeyClick(Qt::Key_6);
expectedString << "ab6cd";
// for versions previous to 3.2 we overwrite needed two undo operations
expectedString << "ab1234cd";
expectedString << "abcd";
QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting 'ABC'
keys.addKeyClick('A');
keys.addKeyClick('B');
keys.addKeyClick('C');
// removes 'C'
keys.addKeyClick(Qt::Key_Backspace);
expectedString << "AB";
expectedString << "ABC";
QTest::newRow("Inserts,backspace") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting 'ABC'
keys.addKeyClick('A');
keys.addKeyClick('B');
keys.addKeyClick('C');
// removes 'C'
keys.addKeyClick(Qt::Key_Backspace);
// inserting 'Z'
keys.addKeyClick('Z');
expectedString << "ABZ";
expectedString << "AB";
expectedString << "ABC";
QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
}
{
QTestEventList keys;
QStringList expectedString;
// inserting '123'
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
psKeyClick(keys, Qt::Key_Home);
// selecting '123'
psKeyClick(keys, Qt::Key_End, Qt::ShiftModifier);
// overwriting '123' with 'ABC'
keys.addKeyClick('A');
keys.addKeyClick('B');
keys.addKeyClick('C');
expectedString << "ABC";
// for versions previous to 3.2 we overwrite needed two undo operations
expectedString << "123";
QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
}
}
void tst_QLineEdit::undo_keypressevents()
{
QFETCH(QTestEventList, keys);
QFETCH(QStringList, expectedString);
keys.simulate(testWidget);
for (int i=0; i<expectedString.size(); ++i) {
QCOMPARE(testWidget->text() , expectedString[i]);
testWidget->undo();
}
QVERIFY(testWidget->text().isEmpty());
}
#ifndef QT_NO_CLIPBOARD
static bool nativeClipboardWorking()
{
#ifdef Q_WS_MAC
PasteboardRef pasteboard;
OSStatus status = PasteboardCreate(0, &pasteboard);
if (status == noErr)
CFRelease(pasteboard);
return status == noErr;
#endif
return true;
}
void tst_QLineEdit::QTBUG5786_undoPaste()
{
if (!nativeClipboardWorking())
QSKIP("this machine doesn't support the clipboard", SkipAll);
QString initial("initial");
QString string("test");
QString additional("add");
QApplication::clipboard()->setText(string);
QLineEdit edit(initial);
QCOMPARE(edit.text(), initial);
edit.paste();
QCOMPARE(edit.text(), initial + string);
edit.paste();
QCOMPARE(edit.text(), initial + string + string);
edit.insert(additional);
QCOMPARE(edit.text(), initial + string + string + additional);
edit.undo();
QCOMPARE(edit.text(), initial + string + string);
edit.undo();
QCOMPARE(edit.text(), initial + string);
edit.undo();
QCOMPARE(edit.text(), initial);
edit.selectAll();
QApplication::clipboard()->setText(QString());
edit.paste();
QVERIFY(edit.text().isEmpty());
}
#endif
void tst_QLineEdit::clear()
{
// checking that clear of empty/nullstring doesn't add to undo history
int max = 5000;
while (max > 0 && testWidget->isUndoAvailable()) {
max--;
testWidget->undo();
}
testWidget->clear();
// QVERIFY(!testWidget->isUndoAvailable());
// checks that clear actually clears
testWidget->insert("I am Legend");
testWidget->clear();
QVERIFY(testWidget->text().isEmpty());
// checks that clears can be undone
testWidget->undo();
QCOMPARE(testWidget->text(), QString("I am Legend"));
}
void tst_QLineEdit::editingFinished()
{
if (testWidget->hasAcceptableInput())
validInput = true;
else
validInput = false;
}
void tst_QLineEdit::text_data()
{
QTest::addColumn<QString>("insertString");
QTest::newRow("Plain text0") << QString("Hello World");
QTest::newRow("Plain text1") << QString("");
QTest::newRow("Plain text2") << QString("A");
QTest::newRow("Plain text3") << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry");
QTest::newRow("Plain text4") << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"");
QTest::newRow("Newlines") << QString("A\nB\nC\n");
QTest::newRow("Text with nbsp") << QString("Hello") + QChar(0xa0) + "World";
}
void tst_QLineEdit::text()
{
QFETCH(QString, insertString);
testWidget->setText(insertString);
QCOMPARE(testWidget->text(), insertString);
}
void tst_QLineEdit::textMask_data()
{
QTest::addColumn<QString>("insertString");
QTest::newRow( "Plain text1" ) << QString( "" );
}
void tst_QLineEdit::textMask()
{
QFETCH( QString, insertString );
testWidget->setInputMask( "#" );
testWidget->setText( insertString );
QCOMPARE( testWidget->text(), insertString );
}
void tst_QLineEdit::setText()
{
QSignalSpy editedSpy(testWidget, SIGNAL(textEdited(QString)));
QSignalSpy changedSpy(testWidget, SIGNAL(textChanged(QString)));
testWidget->setText("hello");
QCOMPARE(editedSpy.count(), 0);
QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello"));
}
void tst_QLineEdit::displayText_data()
{
QTest::addColumn<QString>("insertString");
QTest::addColumn<QString>("expectedString");
QTest::addColumn<QLineEdit::EchoMode>("mode");
QTest::addColumn<bool>("use_setText");
QString s;
QLineEdit::EchoMode m;
for (int i=0; i<2; i++) {
QString key_mode_str;
bool use_setText;
if (i==0) {
key_mode_str = "setText_";
use_setText = true;
} else {
key_mode_str = "useKeys_";
use_setText = false;
}
s = key_mode_str + "Normal";
m = QLineEdit::Normal;
QTest::newRow(QString(s + " text0").toLatin1()) << QString("Hello World") <<
QString("Hello World") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") <<
QString("A") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text3").toLatin1()) << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text4").toLatin1()) << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text with nbsp").toLatin1()) << QString("Hello") + QChar(0xa0) + "World" <<
QString("Hello") + QChar(0xa0) + "World" <<
m << bool(use_setText);
s = key_mode_str + "NoEcho";
m = QLineEdit::NoEcho;
QTest::newRow(QString(s + " text0").toLatin1()) << QString("Hello World") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text3").toLatin1()) << QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text4").toLatin1()) << QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text with nbsp").toLatin1()) << QString("Hello") + QChar(0xa0) + "World" <<
QString("") <<
m << bool(use_setText);
s = key_mode_str + "Password";
m = QLineEdit::Password;
QChar passChar = qApp->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, 0, testWidget);
QString input;
QString pass;
input = "Hello World";
pass.resize(input.length());
pass.fill(passChar);
QTest::newRow(QString(s + " text0").toLatin1()) << input << pass << m << bool(use_setText);
QTest::newRow(QString(s + " text1").toLatin1()) << QString("") <<
QString("") <<
m << bool(use_setText);
QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") << QString(passChar) << m << bool(use_setText);
input = QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry");
pass.resize(input.length());
pass.fill(passChar);
QTest::newRow(QString(s + " text3").toLatin1()) << input << pass << m << bool(use_setText);
input = QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\"");
pass.fill(passChar, input.length());
QTest::newRow(QString(s + " text4").toLatin1()) << input << pass << m << bool(use_setText);
input = QString("Hello") + QChar(0xa0) + "World";
pass.resize(input.length());
pass.fill(passChar);
QTest::newRow(QString(s + " text with nbsp").toLatin1()) << input << pass << m << bool(use_setText);
}
}
void tst_QLineEdit::displayText()
{
QFETCH(QString, insertString);
QFETCH(QString, expectedString);
QFETCH(QLineEdit::EchoMode, mode);
//QFETCH(bool, use_setText); Currently unused.
testWidget->setEchoMode(mode);
testWidget->setText(insertString);
QCOMPARE(testWidget->displayText(), expectedString);
QVERIFY(testWidget->echoMode() == mode);
}
void tst_QLineEdit::setEchoMode()
{
DEPENDS_ON("displayText");
}
void tst_QLineEdit::echoMode()
{
DEPENDS_ON("displayText");
}
void tst_QLineEdit::passwordEchoOnEdit()
{
QStyleOptionFrameV2 opt;
QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
testWidget->setFocus();
testWidget->raise();
QTRY_VERIFY(testWidget->hasFocus());
QTest::keyPress(testWidget, '0');
QTest::keyPress(testWidget, '1');
QTest::keyPress(testWidget, '2');
QTest::keyPress(testWidget, '3');
QTest::keyPress(testWidget, '4');
QCOMPARE(testWidget->displayText(), QString("01234"));
testWidget->clearFocus();
QVERIFY(!testWidget->hasFocus());
QCOMPARE(testWidget->displayText(), QString(5, fillChar));
testWidget->setFocus();
QTRY_VERIFY(testWidget->hasFocus());
QCOMPARE(testWidget->displayText(), QString(5, fillChar));
QTest::keyPress(testWidget, '0');
QCOMPARE(testWidget->displayText(), QString("0"));
// restore clean state
testWidget->setEchoMode(QLineEdit::Normal);
}
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void tst_QLineEdit::passwordEchoDelay()
{
QStyleOptionFrameV2 opt;
QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
testWidget->setEchoMode(QLineEdit::Password);
testWidget->setFocus();
testWidget->raise();
QTRY_VERIFY(testWidget->hasFocus());
QTest::keyPress(testWidget, '0');
QTest::keyPress(testWidget, '1');
QTest::keyPress(testWidget, '2');
QCOMPARE(testWidget->displayText(), QString(2, fillChar) + QLatin1Char('2'));
QTest::keyPress(testWidget, '3');
QTest::keyPress(testWidget, '4');
QCOMPARE(testWidget->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::keyPress(testWidget, Qt::Key_Backspace);
QCOMPARE(testWidget->displayText(), QString(4, fillChar));
QTest::keyPress(testWidget, '4');
QCOMPARE(testWidget->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
QTRY_COMPARE(testWidget->displayText(), QString(5, fillChar));
QTest::keyPress(testWidget, '5');
QCOMPARE(testWidget->displayText(), QString(5, fillChar) + QLatin1Char('5'));
testWidget->clearFocus();
QVERIFY(!testWidget->hasFocus());
QCOMPARE(testWidget->displayText(), QString(6, fillChar));
testWidget->setFocus();
QTRY_VERIFY(testWidget->hasFocus());
QCOMPARE(testWidget->displayText(), QString(6, fillChar));
QTest::keyPress(testWidget, '6');
QCOMPARE(testWidget->displayText(), QString(6, fillChar) + QLatin1Char('6'));
QInputMethodEvent ev;
ev.setCommitString(QLatin1String("7"));
QApplication::sendEvent(testWidget, &ev);
QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7'));
testWidget->setCursorPosition(3);
QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7'));
QTest::keyPress(testWidget, 'a');
QCOMPARE(testWidget->displayText(), QString(3, fillChar) + QLatin1Char('a') + QString(5, fillChar));
QTest::keyPress(testWidget, Qt::Key_Backspace);
QCOMPARE(testWidget->displayText(), QString(8, fillChar));
// restore clean state
testWidget->setEchoMode(QLineEdit::Normal);
}
#endif
void tst_QLineEdit::maxLength_mask_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<int>("expectedLength");
QTest::newRow("mask_case") << QString(">000<>00<000") << 8;
QTest::newRow("mask_nocase") << QString("00000000") << 8;
QTest::newRow("mask_null") << QString() << 32767;
QTest::newRow("mask_escape") << QString("\\A\\aAA") << 4;
}
void tst_QLineEdit::maxLength_mask()
{
QFETCH(QString, mask);
QFETCH(int, expectedLength);
testWidget->setInputMask(mask);
QCOMPARE(testWidget->maxLength(), expectedLength);
}
void tst_QLineEdit::maxLength_data()
{
QTest::addColumn<QString>("insertString");
QTest::addColumn<QString>("expectedString");
QTest::addColumn<int>("length");
QTest::addColumn<bool>("insertBeforeSettingMaxLength");
QTest::addColumn<bool>("use_setText");
QTest::newRow("keyclick before0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(true) << bool(false);
QTest::newRow("keyclick before1") << QString("this is a test.") << QString("this is a ") << 10 << bool(true) << bool(false);
QTest::newRow("keyclick after0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(false) << bool(false);
QTest::newRow("keyclick after1") << QString("this is a test.") << QString("this is a ") << 10 << bool(false) << bool(false);
QTest::newRow("settext before0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(true) << bool(true);
QTest::newRow("settext before1") << QString("this is a test.") << QString("this is a ") << 10 << bool(true) << bool(true);
QTest::newRow("settext after0") << QString("this is a test.") << QString("this is a test.") << 20 << bool(false) << bool(true);
QTest::newRow("settext after1") << QString("this is a test.") << QString("this is a ") << 10 << bool(false) << bool(true);
}
void tst_QLineEdit::maxLength()
{
QFETCH(QString, insertString);
QFETCH(QString, expectedString);
QFETCH(int, length);
QFETCH(bool, insertBeforeSettingMaxLength);
QFETCH(bool, use_setText);
// in some cases we set the maxLength _before_ entering the text.
if (!insertBeforeSettingMaxLength)
testWidget->setMaxLength(length);
// I expect MaxLength to work BOTH with entering live characters AND with setting the text.
if (use_setText) {
// Enter insertString using setText.
testWidget->setText(insertString);
} else {
// Enter insertString as a sequence of keyClicks
QTest::keyClicks(testWidget, insertString);
}
// in all other cases we set the maxLength _after_ entering the text.
if (insertBeforeSettingMaxLength) {
changed_count = 0;
testWidget->setMaxLength(length);
// Make sure that the textChanged is not emitted unless the text is actually changed
if (insertString == expectedString) {
QVERIFY(changed_count == 0);
} else {
QVERIFY(changed_count == 1);
}
}
// and check if we get the expected string back
QCOMPARE(testWidget->text(), expectedString);
}
void tst_QLineEdit::setMaxLength()
{
DEPENDS_ON("maxLength");
}
void tst_QLineEdit::isReadOnly()
{
QVERIFY(!testWidget->isReadOnly());
// start with a basic text
QTest::keyClicks(testWidget, "the quick brown fox");
QCOMPARE(testWidget->text(), QString("the quick brown fox"));
// do a quick check to verify that we can indeed edit the text
testWidget->home(false);
testWidget->cursorForward(false, 10);
QTest::keyClicks(testWidget, "dark ");
QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
testWidget->setReadOnly(true);
QVERIFY(testWidget->isReadOnly());
// verify that we cannot edit the text anymore
testWidget->home(false);
testWidget->cursorForward(false, 10);
QTest::keyClick(testWidget, Qt::Key_Delete);
QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
testWidget->cursorForward(false, 10);
QTest::keyClicks(testWidget, "this should not have any effect!! ");
QCOMPARE(testWidget->text(), QString("the quick dark brown fox"));
}
void tst_QLineEdit::setReadOnly()
{
DEPENDS_ON("isReadOnly");
}
static void figureOutProperKey(Qt::Key &key, Qt::KeyboardModifiers &pressState)
{
#ifdef Q_WS_MAC
static bool tst_lineedit_randomized = false;
// Mac has 3 different ways of accomplishing this (same for moving to the back)
// So I guess we should just randomly do this for now. Which may get people mad, but if
// we fail at one point, it's just a matter of setting roll to the correct value
// instead of random.
if (!tst_lineedit_randomized) {
tst_lineedit_randomized = true;
::srandom(ulong(time(0)));
}
long roll = ::random() % 3;
switch (roll) {
case 0:
key = key == Qt::Key_Home ? Qt::Key_Up : Qt::Key_Down;
break;
case 1:
case 2:
key = key == Qt::Key_Home ? Qt::Key_Left : Qt::Key_Right;
pressState |= (roll == 1) ? Qt::ControlModifier : Qt::MetaModifier;
break;
}
#else
// Naively kill the warning.
key = key;
pressState = pressState;
#endif
}
// Platform specific move. Home and End do nothing on the Mac,
// so do something a bit smarter than tons of #ifdefs
void tst_QLineEdit::psKeyClick(QWidget *target, Qt::Key key, Qt::KeyboardModifiers pressState)
{
figureOutProperKey(key, pressState);
QTest::keyClick(target, key, pressState);
}
void tst_QLineEdit::psKeyClick(QTestEventList &keys, Qt::Key key, Qt::KeyboardModifiers pressState)
{
figureOutProperKey(key, pressState);
keys.addKeyClick(key, pressState);
}
void tst_QLineEdit::cursorPosition()
{
QVERIFY(testWidget->cursorPosition() == 0);
// start with a basic text
QTest::keyClicks(testWidget, "The");
QCOMPARE(testWidget->cursorPosition(), 3);
QTest::keyClicks(testWidget, " quick");
QCOMPARE(testWidget->cursorPosition(), 9);
QTest::keyClicks(testWidget, " brown fox jumps over the lazy dog");
QCOMPARE(testWidget->cursorPosition(), 43);
// The text we have now is:
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// The quick brown fox jumps over the lazy dog
// next we will check some of the cursor movement functions
testWidget->end(false);
QCOMPARE(testWidget->cursorPosition() , 43);
testWidget->cursorForward(false, -1);
QCOMPARE(testWidget->cursorPosition() , 42);
testWidget->cursorBackward(false, 1);
QCOMPARE(testWidget->cursorPosition() , 41);
testWidget->home(false);
QCOMPARE(testWidget->cursorPosition() , 0);
testWidget->cursorForward(false, 1);
QCOMPARE(testWidget->cursorPosition() , 1);
testWidget->cursorForward(false, 9);
QCOMPARE(testWidget->cursorPosition() , 10);
testWidget->cursorWordForward(false); // 'fox'
QCOMPARE(testWidget->cursorPosition(), 16);
testWidget->cursorWordForward(false); // 'jumps'
QCOMPARE(testWidget->cursorPosition(), 20);
testWidget->cursorWordBackward(false); // 'fox'
QCOMPARE(testWidget->cursorPosition(), 16);
testWidget->cursorWordBackward(false); // 'brown'
testWidget->cursorWordBackward(false); // 'quick'
testWidget->cursorWordBackward(false); // 'The'
QCOMPARE(testWidget->cursorPosition(), 0);
testWidget->cursorWordBackward(false); // 'The'
QCOMPARE(testWidget->cursorPosition(), 0);
// Cursor position should be 0 here!
int i;
for (i=0; i<5; i++)
QTest::keyClick(testWidget, Qt::Key_Right);
QCOMPARE(testWidget->cursorPosition(), 5);
psKeyClick(testWidget, Qt::Key_End);
QCOMPARE(testWidget->cursorPosition(), 43);
QTest::keyClick(testWidget, Qt::Key_Left);
QCOMPARE(testWidget->cursorPosition(), 42);
QTest::keyClick(testWidget, Qt::Key_Left);
QCOMPARE(testWidget->cursorPosition(), 41);
psKeyClick(testWidget, Qt::Key_Home);
QCOMPARE(testWidget->cursorPosition(), 0);
// cursorposition when maxlength is set
int maxLength = 9;
testWidget->clear();
testWidget->setMaxLength(maxLength);
QCOMPARE(testWidget->cursorPosition() , 0);
QTest::keyClicks(testWidget, "123ABC123");
QCOMPARE(testWidget->cursorPosition() , maxLength);
psKeyClick(testWidget, Qt::Key_Home);
QCOMPARE(testWidget->cursorPosition() , 0);
psKeyClick(testWidget, Qt::Key_End);
QCOMPARE(testWidget->cursorPosition() , maxLength);
}
/* // tested in cursorPosition
void tst_QLineEdit::cursorLeft()
void tst_QLineEdit::cursorRight()
void tst_QLineEdit::cursorForward()
void tst_QLineEdit::cursorBackward()
void tst_QLineEdit::cursorWordForward()
void tst_QLineEdit::cursorWordBackward()
void tst_QLineEdit::home()
void tst_QLineEdit::end()
*/
void tst_QLineEdit::cursorPositionChanged_data()
{
QTest::addColumn<QTestEventList>("input");
QTest::addColumn<int>("lastPos");
QTest::addColumn<int>("newPos");
QTestEventList keys;
keys.addKeyClick(Qt::Key_A);
QTest::newRow("a") << keys << 0 << 1;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
psKeyClick(keys, Qt::Key_Home);
QTest::newRow("abc<home>") << keys << 3 << 0;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Left);
QTest::newRow("abc<left>") << keys << 3 << 2;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Right);
QTest::newRow("abc<right>") << keys << 2 << 3;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
psKeyClick(keys, Qt::Key_Home);
keys.addKeyClick(Qt::Key_Right);
QTest::newRow("abc<home><right>") << keys << 0 << 1;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Backspace);
QTest::newRow("abc<backspace>") << keys << 3 << 2;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Delete);
QTest::newRow("abc<delete>") << keys << 2 << 3;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Left);
keys.addKeyClick(Qt::Key_Delete);
QTest::newRow("abc<left><delete>") << keys << 3 << 2;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
psKeyClick(keys, Qt::Key_Home);
psKeyClick(keys, Qt::Key_End);
QTest::newRow("abc<home><end>") << keys << 0 << 3;
keys.clear();
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Space);
keys.addKeyClick(Qt::Key_D);
keys.addKeyClick(Qt::Key_E);
keys.addKeyClick(Qt::Key_F);
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_Right, Qt::ControlModifier);
QTest::newRow("abc efg<home><ctrl-right>") << keys
#ifndef Q_WS_MAC
<< 0 << 4;
#else
<< 6 << 7;
#endif
keys.clear();
#ifdef Q_WS_MAC
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Space);
keys.addKeyClick(Qt::Key_D);
keys.addKeyClick(Qt::Key_E);
keys.addKeyClick(Qt::Key_F);
keys.addKeyClick(Qt::Key_Up);
keys.addKeyClick(Qt::Key_Right, Qt::AltModifier);
QTest::newRow("mac equivalent abc efg<up><option-right>") << keys << 0 << 4;
keys.clear();
#endif
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Space);
keys.addKeyClick(Qt::Key_D);
keys.addKeyClick(Qt::Key_E);
keys.addKeyClick(Qt::Key_F);
keys.addKeyClick(Qt::Key_Left, Qt::ControlModifier);
QTest::newRow("abc efg<ctrl-left>") << keys << 7
#ifndef Q_WS_MAC
<< 4;
#else
<< 0;
#endif
keys.clear();
#ifdef Q_WS_MAC
keys.addKeyClick(Qt::Key_A);
keys.addKeyClick(Qt::Key_B);
keys.addKeyClick(Qt::Key_C);
keys.addKeyClick(Qt::Key_Space);
keys.addKeyClick(Qt::Key_D);
keys.addKeyClick(Qt::Key_E);
keys.addKeyClick(Qt::Key_F);
keys.addKeyClick(Qt::Key_Left, Qt::AltModifier);
QTest::newRow("mac equivalent abc efg<option-left>") << keys << 7 << 4;
keys.clear();
#endif
}
void tst_QLineEdit::cursorPositionChanged()
{
QFETCH(QTestEventList, input);
QFETCH(int, lastPos);
QFETCH(int, newPos);
lastCursorPos = 0;
newCursorPos = 0;
input.simulate(testWidget);
QCOMPARE(lastCursorPos, lastPos);
QCOMPARE(newCursorPos, newPos);
}
void tst_QLineEdit::selectedText()
{
QString testString = "Abc defg hijklmno, p 'qrst' uvw xyz";
// start with a basic text
testWidget->setText(testString);
selection_count = 0;
// The text we have now is:
// 1 2 3 4 5
// 012345678901234567890123456789012345678901234567890
// Abc defg hijklmno, p 'qrst' uvw xyz
testWidget->home(false);
QVERIFY(!testWidget->hasSelectedText());
QCOMPARE(testWidget->selectedText(), QString());
// play a bit with the cursorForward, cursorBackward(), etc
testWidget->cursorForward(true, 9);
QVERIFY(testWidget->hasSelectedText());
QCOMPARE(testWidget->selectedText(), QString("Abc defg "));
QVERIFY(selection_count == 1);
// reset selection
testWidget->home(false);
QVERIFY(!testWidget->hasSelectedText());
QCOMPARE(testWidget->selectedText(), QString());
selection_count = 0;
}
/* // tested in selectedText
void tst_QLineEdit::backspace()
void tst_QLineEdit::del()
void tst_QLineEdit::selectionChanged()
void tst_QLineEdit::selectAll()
void tst_QLineEdit::deselect()
*/
void tst_QLineEdit::onSelectionChanged()
{
selection_count++;
}
void tst_QLineEdit::hasSelectedText()
{
DEPENDS_ON("selectedText");
}
void tst_QLineEdit::deleteSelectedText()
{
const QString text = QString::fromLatin1("bar");
QLineEdit edit( text );
QCOMPARE(edit.text(), text);
edit.selectAll();
QTest::keyClick(&edit, Qt::Key_Delete, 0);
QVERIFY(edit.text().isEmpty());
edit.setText(text);
edit.selectAll();
QMenu *menu = edit.createStandardContextMenu();
for (int i = 0; i < menu->actions().count(); ++i) {
QAction *current = menu->actions().at(i);
if (current->text() == QLineEdit::tr("Delete")) {
current->trigger(); //this will delete the whole text selected
QVERIFY(edit.text().isEmpty());
}
}
}
void tst_QLineEdit::textChangedAndTextEdited()
{
changed_count = 0;
edited_count = 0;
QTest::keyClick(testWidget, Qt::Key_A);
QCOMPARE(changed_count, 1);
QVERIFY(edited_count == changed_count);
QTest::keyClick(testWidget, 'b');
QCOMPARE(changed_count, 2);
QVERIFY(edited_count == changed_count);
QTest::keyClick(testWidget, 'c');
QCOMPARE(changed_count, 3);
QVERIFY(edited_count == changed_count);
QTest::keyClick(testWidget, ' ');
QCOMPARE(changed_count, 4);
QVERIFY(edited_count == changed_count);
QTest::keyClick(testWidget, 'd');
QCOMPARE(changed_count, 5);
QVERIFY(edited_count == changed_count);
changed_count = 0;
edited_count = 0;
changed_string = QString::null;
testWidget->setText("foo");
QCOMPARE(changed_count, 1);
QCOMPARE(edited_count, 0);
QCOMPARE(changed_string, QString("foo"));
changed_count = 0;
edited_count = 0;
changed_string = QString::null;
testWidget->setText("");
QCOMPARE(changed_count, 1);
QCOMPARE(edited_count, 0);
QVERIFY(changed_string.isEmpty());
QVERIFY(!changed_string.isNull());
}
void tst_QLineEdit::onTextChanged(const QString &text)
{
changed_count++;
changed_string = text;
}
void tst_QLineEdit::onTextEdited(const QString &/*text*/)
{
edited_count++;
}
void tst_QLineEdit::onCursorPositionChanged(int oldPos, int newPos)
{
lastCursorPos = oldPos;
newCursorPos = newPos;
}
void tst_QLineEdit::returnPressed()
{
return_count = 0;
QTest::keyClick(testWidget, Qt::Key_Return);
QVERIFY(return_count == 1);
return_count = 0;
QTest::keyClick(testWidget, 'A');
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, 'b');
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, 'c');
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, ' ');
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, 'd');
QVERIFY(return_count == 0);
psKeyClick(testWidget, Qt::Key_Home);
QVERIFY(return_count == 0);
psKeyClick(testWidget, Qt::Key_End);
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, Qt::Key_Escape);
QVERIFY(return_count == 0);
QTest::keyClick(testWidget, Qt::Key_Return);
QVERIFY(return_count == 1);
}
// int validator that fixes all !isNumber to '0'
class QIntFixValidator : public QIntValidator {
public:
QIntFixValidator(int min, int max, QObject *parent) : QIntValidator(min, max, parent) {}
void fixup (QString &input) const {
for (int i=0; i<input.length(); ++i)
if (!input.at(i).isNumber()) {
input[(int)i] = QChar('0');
}
}
};
void tst_QLineEdit::returnPressed_maskvalidator_data() {
QTest::addColumn<QString>("inputMask");
QTest::addColumn<bool>("hasValidator");
QTest::addColumn<QTestEventList>("input");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<bool>("returnPressed");
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("no mask, no validator, input '123<cr>'")
<< QString()
<< false
<< keys
<< QString("123")
<< true;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("mask '999', no validator, input '12<cr>'")
<< QString("999")
<< false
<< keys
<< QString("12")
<< false;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("mask '999', no validator, input '123<cr>'")
<< QString("999")
<< false
<< keys
<< QString("123")
<< true;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_3);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("no mask, intfix validator(0,999), input '123<cr>'")
<< QString()
<< true
<< keys
<< QString("123")
<< true;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_7);
keys.addKeyClick(Qt::Key_7);
keys.addKeyClick(Qt::Key_7);
keys.addKeyClick(Qt::Key_7);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("no mask, intfix validator(0,999), input '7777<cr>'")
<< QString()
<< true
<< keys
<< QString("777")
<< true;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_1);
keys.addKeyClick(Qt::Key_2);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("mask '999', intfix validator(0,999), input '12<cr>'")
<< QString("999")
<< true
<< keys
<< QString("12")
<< false;
}
{
QTestEventList keys;
keys.addKeyClick(Qt::Key_Home);
keys.addKeyClick(Qt::Key_Return);
QTest::newRow("mask '999', intfix validator(0,999), input '<cr>'")
<< QString("999")
<< true
<< keys
<< QString("000")
<< true;
}
}
void tst_QLineEdit::returnPressed_maskvalidator()
{
QFETCH(QString, inputMask);
QFETCH(bool, hasValidator);
QFETCH(QTestEventList, input);
QFETCH(QString, expectedText);
QFETCH(bool, returnPressed);
QEXPECT_FAIL("mask '999', intfix validator(0,999), input '12<cr>'", "QIntValidator has changed behaviour. Does not accept spaces. Task 43082.", Abort);
testWidget->setInputMask(inputMask);
if (hasValidator)
testWidget->setValidator(new QIntFixValidator(0, 999, testWidget));
return_count = 0;
input.simulate(testWidget);
QCOMPARE(testWidget->text(), expectedText);
QCOMPARE(return_count , returnPressed ? 1 : 0);
}
void tst_QLineEdit::onReturnPressed()
{
return_count++;
}
void tst_QLineEdit::setValidator()
{
// Verify that we can set and re-set a validator.
QVERIFY(!testWidget->validator());
QIntValidator iv1(0);
testWidget->setValidator(&iv1);
QCOMPARE(testWidget->validator(), static_cast<const QValidator*>(&iv1));
testWidget->setValidator(0);
QVERIFY(testWidget->validator() == 0);
QIntValidator iv2(0, 99, 0);
testWidget->setValidator(&iv2);
QCOMPARE(testWidget->validator(), static_cast<const QValidator *>(&iv2));
testWidget->setValidator(0);
QVERIFY(testWidget->validator() == 0);
}
void tst_QLineEdit::validator()
{
DEPENDS_ON("setValidator");
}
void tst_QLineEdit::clearValidator()
{
DEPENDS_ON("setValidator");
}
void tst_QLineEdit::setValidator_QIntValidator_data()
{
QTest::addColumn<int>("mini");
QTest::addColumn<int>("maxi");
QTest::addColumn<QString>("input");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<bool>("useKeys");
QTest::addColumn<bool>("is_valid");
for (int i=0; i<2; i++) {
bool useKeys = false;
QString inputMode = "insert ";
if (i!=0) {
inputMode = "useKeys ";
useKeys = true;
}
// valid data
QTest::newRow(QString(inputMode + "range [0,9] valid '1'").toLatin1())
<< 0
<< 9
<< QString("1")
<< QString("1")
<< bool(useKeys)
<< bool(true);
QTest::newRow(QString(inputMode + "range [3,7] valid '3'").toLatin1())
<< 3
<< 7
<< QString("3")
<< QString("3")
<< bool(useKeys)
<< bool(true);
QTest::newRow(QString(inputMode + "range [3,7] valid '7'").toLatin1())
<< 3
<< 7
<< QString("7")
<< QString("7")
<< bool(useKeys)
<< bool(true);
QTest::newRow(QString(inputMode + "range [0,100] valid '9'").toLatin1())
<< 0
<< 100
<< QString("9")
<< QString("9")
<< bool(useKeys)
<< bool(true);
QTest::newRow(QString(inputMode + "range [0,100] valid '12'").toLatin1())
<< 0
<< 100
<< QString("12")
<< QString("12")
<< bool(useKeys)
<< bool(true);
QTest::newRow(QString(inputMode + "range [-100,100] valid '-12'").toLatin1())
<< -100
<< 100
<< QString("-12")
<< QString("-12")
<< bool(useKeys)
<< bool(true);
// invalid data
// characters not allowed in QIntValidator
QTest::newRow(QString(inputMode + "range [0,9] inv 'a-a'").toLatin1())
<< 0
<< 9
<< QString("a")
<< QString("")
<< bool(useKeys)
<< bool(false);
QTest::newRow(QString(inputMode + "range [0,9] inv 'A'").toLatin1())
<< 0
<< 9
<< QString("A")
<< QString("")
<< bool(useKeys)
<< bool(false);
// minus sign only allowed with a range on the negative side
QTest::newRow(QString(inputMode + "range [0,100] inv '-'").toLatin1())
<< 0
<< 100
<< QString("-")
<< QString("")
<< bool(useKeys)
<< bool(false);
QTest::newRow(QString(inputMode + "range [0,100] int '153'").toLatin1())
<< 0
<< 100
<< QString("153")
<< QString(useKeys ? "15" : "")
<< bool(useKeys)
<< bool(useKeys ? true : false);
QTest::newRow(QString(inputMode + "range [-100,100] int '-153'").toLatin1())
<< -100
<< 100
<< QString("-153")
<< QString(useKeys ? "-15" : "")
<< bool(useKeys)
<< bool(useKeys ? true : false);
QTest::newRow(QString(inputMode + "range [3,7] int '2'").toLatin1())
<< 3
<< 7
<< QString("2")
<< QString("2")
<< bool(useKeys)
<< bool(false);
QTest::newRow(QString(inputMode + "range [3,7] int '8'").toLatin1())
<< 3
<< 7
<< QString("8")
<< QString("")
<< bool(useKeys)
<< bool(false);
}
}
void tst_QLineEdit::setValidator_QIntValidator()
{
QFETCH(int, mini);
QFETCH(int, maxi);
QFETCH(QString, input);
QFETCH(QString, expectedText);
QFETCH(bool, useKeys);
QFETCH(bool, is_valid);
QIntValidator intValidator(mini, maxi, 0);
testWidget->setValidator(&intValidator);
QVERIFY(testWidget->text().isEmpty());
//qDebug("1 input: '" + input + "' Exp: '" + expectedText + "'");
// tests valid input
if (!useKeys) {
testWidget->insert(input);
} else {
QTest::keyClicks(testWidget, input);
return_count = 0;
QTest::keyClick(testWidget, Qt::Key_Return);
QCOMPARE(return_count, int(is_valid)); // assuming that is_valid = true equals 1
}
//qDebug("2 input: '" + input + "' Exp: '" + expectedText + "'");
// QCOMPARE(testWidget->displayText(), expectedText);
QCOMPARE(testWidget->text(), expectedText);
}
#define NO_PIXMAP_TESTS
void tst_QLineEdit::frame_data()
{
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTest::addColumn<QPixmap>("noFrame");
QTest::addColumn<QPixmap>("useFrame");
QTest::newRow("win");
//#else
// QTest::newRow("x11");
#endif
#endif
}
void tst_QLineEdit::frame()
{
testWidget->setFrame(false);
// verify that the editor is shown without a frame
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTEST(testWidget, "noFrame");
#endif
#endif
QVERIFY(!testWidget->hasFrame());
testWidget->setFrame(true);
// verify that the editor is shown with a frame
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTEST(testWidget, "useFrame");
#endif
#endif
QVERIFY(testWidget->hasFrame());
}
void tst_QLineEdit::alignment()
{
DEPENDS_ON("setAlignment");
}
void tst_QLineEdit::setAlignment_data()
{
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTest::addColumn<QPixmap>("left");
QTest::addColumn<QPixmap>("right");
QTest::addColumn<QPixmap>("hcenter");
QTest::addColumn<QPixmap>("auto");
QTest::newRow("win");
//#else
// QTest::newRow("x11");
#endif
#endif
}
void tst_QLineEdit::setAlignment()
{
testWidget->setText("left");
testWidget->setAlignment(Qt::AlignLeft);
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTEST(testWidget, "left");
#endif
#endif
QVERIFY(testWidget->alignment() == Qt::AlignLeft);
testWidget->setText("hcenter");
testWidget->setAlignment(Qt::AlignHCenter);
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTEST(testWidget, "hcenter");
#endif
#endif
QVERIFY(testWidget->alignment() == Qt::AlignHCenter);
testWidget->setText("right");
testWidget->setAlignment(Qt::AlignRight);
#ifndef NO_PIXMAP_TESTS
#if defined Q_WS_WIN
QTEST(testWidget, "right");
#endif
#endif
QVERIFY(testWidget->alignment() == Qt::AlignRight);
testWidget->setAlignment(Qt::AlignTop);
QVERIFY(testWidget->alignment() == Qt::AlignTop);
testWidget->setAlignment(Qt::AlignBottom);
QVERIFY(testWidget->alignment() == Qt::AlignBottom);
testWidget->setAlignment(Qt::AlignCenter);
QVERIFY(testWidget->alignment() == Qt::AlignCenter);
}
void tst_QLineEdit::isModified()
{
QVERIFY(!testWidget->isModified());
testWidget->setText("bla");
QVERIFY(!testWidget->isModified());
psKeyClick(testWidget, Qt::Key_Home);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Left);
QVERIFY(!testWidget->isModified());
psKeyClick(testWidget, Qt::Key_End);
QVERIFY(!testWidget->isModified());
QTest::keyClicks(testWidget, "T");
QVERIFY(testWidget->isModified());
QTest::keyClicks(testWidget, "his is a string");
QVERIFY(testWidget->isModified());
testWidget->setText("");
QVERIFY(!testWidget->isModified());
testWidget->setText("foo");
QVERIFY(!testWidget->isModified());
}
/*
Obsolete function but as long as we provide it, it needs to work.
*/
void tst_QLineEdit::edited()
{
QVERIFY(!testWidget->isModified());
testWidget->setText("bla");
QVERIFY(!testWidget->isModified());
psKeyClick(testWidget, Qt::Key_Home);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Right);
QVERIFY(!testWidget->isModified());
QTest::keyClick(testWidget, Qt::Key_Left);
QVERIFY(!testWidget->isModified());
psKeyClick(testWidget, Qt::Key_End);
QVERIFY(!testWidget->isModified());
QTest::keyClicks(testWidget, "T");
QVERIFY(testWidget->isModified());
QTest::keyClicks(testWidget, "his is a string");
QVERIFY(testWidget->isModified());
testWidget->setModified(false);
QVERIFY(!testWidget->isModified());
testWidget->setModified(true);
QVERIFY(testWidget->isModified());
}
/*
Obsolete function but as long as we provide it, it needs to work.
*/
void tst_QLineEdit::setEdited()
{
DEPENDS_ON("edited");
}
void tst_QLineEdit::insert()
{
testWidget->insert("This");
testWidget->insert(" is");
testWidget->insert(" a");
testWidget->insert(" test");
QCOMPARE(testWidget->text(), QString("This is a test"));
testWidget->cursorWordBackward(false);
testWidget->cursorBackward(false, 1);
testWidget->insert(" nice");
QCOMPARE(testWidget->text(), QString("This is a nice test"));
testWidget->setCursorPosition(-1);
testWidget->insert("No Crash! ");
QCOMPARE(testWidget->text(), QString("No Crash! This is a nice test"));
}
void tst_QLineEdit::setSelection_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<int>("start");
QTest::addColumn<int>("length");
QTest::addColumn<int>("expectedCursor");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<bool>("expectedHasSelectedText");
QString text = "Abc defg hijklmno, p 'qrst' uvw xyz";
int start, length, pos;
start = 0; length = 1; pos = 1;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("A") << true;
start = 0; length = 2; pos = 2;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("Ab") << true;
start = 0; length = 4; pos = 4;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("Abc ") << true;
start = -1; length = 0; pos = text.length();
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString() << false;
start = 34; length = 1; pos = 35;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("z") << true;
start = 34; length = 2; pos = 35;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("z") << true;
start = 34; length = -1; pos = 33;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("y") << true;
start = 1; length = -2; pos = 0;
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString("A") << true;
start = -1; length = -1; pos = text.length();
QTest::newRow(QString("selection start: %1 length: %2").arg(start).arg(length).toLatin1())
<< text << start << length << pos << QString() << false;
}
void tst_QLineEdit::setSelection()
{
QFETCH(QString, text);
QFETCH(int, start);
QFETCH(int, length);
QFETCH(int, expectedCursor);
QFETCH(QString, expectedText);
QFETCH(bool, expectedHasSelectedText);
testWidget->setText(text);
testWidget->setSelection(start, length);
QCOMPARE(testWidget->hasSelectedText(), expectedHasSelectedText);
QCOMPARE(testWidget->selectedText(), expectedText);
if (expectedCursor >= 0)
QCOMPARE(testWidget->cursorPosition(), expectedCursor);
}
#ifndef QT_NO_CLIPBOARD
void tst_QLineEdit::cut()
{
#ifdef Q_WS_MAC
{
PasteboardRef pasteboard;
OSStatus status = PasteboardCreate(0, &pasteboard);
if (status == noErr)
CFRelease(pasteboard);
else
QSKIP("Autotests run from cron and pasteboard don't get along quite ATM", SkipAll);
}
#endif
// test newlines in cut'n'paste
testWidget->setText("A\nB\nC\n");
testWidget->setSelection(0, 6);
testWidget->cut();
psKeyClick(testWidget, Qt::Key_Home);
testWidget->paste();
QCOMPARE(testWidget->text(), QString("A\nB\nC\n"));
// 1 2 3 4
// 01234567890123456789012345678901234567890
testWidget->setText("Abc defg hijklmno");
testWidget->setSelection(0, 3);
testWidget->cut();
QCOMPARE(testWidget->text(), QString(" defg hijklmno"));
psKeyClick(testWidget, Qt::Key_End);
testWidget->paste();
QCOMPARE(testWidget->text(), QString(" defg hijklmnoAbc"));
psKeyClick(testWidget, Qt::Key_Home);
testWidget->del();
QCOMPARE(testWidget->text(), QString("defg hijklmnoAbc"));
testWidget->setSelection(0, 4);
testWidget->copy();
psKeyClick(testWidget, Qt::Key_End);
testWidget->paste();
QCOMPARE(testWidget->text(), QString("defg hijklmnoAbcdefg"));
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, Qt::Key_Left);
QTest::keyClick(testWidget, ' ');
QCOMPARE(testWidget->text(), QString("defg hijklmno Abcdefg"));
testWidget->setSelection(0, 5);
testWidget->del();
QCOMPARE(testWidget->text(), QString("hijklmno Abcdefg"));
testWidget->end(false);
QTest::keyClick(testWidget, ' ');
testWidget->paste();
QCOMPARE(testWidget->text(), QString("hijklmno Abcdefg defg"));
testWidget->home(false);
testWidget->cursorWordForward(true);
testWidget->cut();
testWidget->end(false);
QTest::keyClick(testWidget, ' ');
testWidget->paste();
testWidget->cursorBackward(true, 1);
testWidget->cut();
QCOMPARE(testWidget->text(), QString("Abcdefg defg hijklmno"));
}
void tst_QLineEdit::copy()
{
DEPENDS_ON("cut");
}
void tst_QLineEdit::paste()
{
DEPENDS_ON("cut");
}
#endif
class InputMaskValidator : public QValidator
{
public:
InputMaskValidator(QObject *parent, const char *name = 0) : QValidator(parent) { setObjectName(name); }
State validate(QString &text, int &pos) const
{
InputMaskValidator *that = (InputMaskValidator *)this;
that->validateText = text;
that->validatePos = pos;
return Acceptable;
}
QString validateText;
int validatePos;
};
void tst_QLineEdit::inputMaskAndValidator_data()
{
QTest::addColumn<QString>("inputMask");
QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<QString>("validateText");
QTest::addColumn<int>("validatePos");
QTestEventList inputKeys;
inputKeys.addKeyClick(Qt::Key_1);
inputKeys.addKeyClick(Qt::Key_2);
QTest::newRow("task28291") << "000;_" << inputKeys << "12_" << 2;
}
void tst_QLineEdit::inputMaskAndValidator()
{
QFETCH(QString, inputMask);
QFETCH(QTestEventList, keys);
QFETCH(QString, validateText);
QFETCH(int, validatePos);
InputMaskValidator imv(testWidget);
testWidget->setValidator(&imv);
testWidget->setInputMask(inputMask);
keys.simulate(testWidget);
QCOMPARE(imv.validateText, validateText);
QCOMPARE(imv.validatePos, validatePos);
}
void tst_QLineEdit::maxLengthAndInputMask()
{
// Really a test for #30447
QVERIFY(testWidget->inputMask().isNull());
testWidget->setMaxLength(10);
QVERIFY(testWidget->maxLength() == 10);
testWidget->setInputMask(QString::null);
QVERIFY(testWidget->inputMask().isNull());
QVERIFY(testWidget->maxLength() == 10);
}
class LineEdit : public QLineEdit
{
public:
LineEdit() { state = Other; }
void keyPressEvent(QKeyEvent *e)
{
QLineEdit::keyPressEvent(e);
if (e->key() == Qt::Key_Enter) {
state = e->isAccepted() ? Accepted : Ignored;
} else {
state = Other;
}
}
enum State {
Accepted,
Ignored,
Other
};
State state;
friend class tst_QLineEdit;
};
Q_DECLARE_METATYPE(LineEdit::State);
void tst_QLineEdit::returnPressedKeyEvent()
{
LineEdit lineedit;
lineedit.show();
QCOMPARE((int)lineedit.state, (int)LineEdit::Other);
QTest::keyClick(&lineedit, Qt::Key_Enter);
QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
connect(&lineedit, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
QTest::keyClick(&lineedit, Qt::Key_Enter);
QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
disconnect(&lineedit, SIGNAL(returnPressed()), this, SLOT(onReturnPressed()));
QTest::keyClick(&lineedit, Qt::Key_Enter);
QCOMPARE((int)lineedit.state, (int)LineEdit::Ignored);
QTest::keyClick(&lineedit, Qt::Key_1);
QCOMPARE((int)lineedit.state, (int)LineEdit::Other);
}
void tst_QLineEdit::keepSelectionOnTabFocusIn()
{
testWidget->setText("hello world");
{
QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
QApplication::sendEvent(testWidget, &e);
}
QCOMPARE(testWidget->selectedText(), QString("hello world"));
testWidget->setSelection(0, 5);
QCOMPARE(testWidget->selectedText(), QString("hello"));
{
QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
QApplication::sendEvent(testWidget, &e);
}
QCOMPARE(testWidget->selectedText(), QString("hello"));
}
void tst_QLineEdit::readOnlyStyleOption()
{
bool wasReadOnly = testWidget->isReadOnly();
QStyle *oldStyle = testWidget->style();
StyleOptionTestStyle myStyle;
testWidget->setStyle(&myStyle);
myStyle.setReadOnly(true);
testWidget->setReadOnly(true);
testWidget->repaint();
qApp->processEvents();
testWidget->setReadOnly(false);
myStyle.setReadOnly(false);
testWidget->repaint();
qApp->processEvents();
testWidget->setReadOnly(wasReadOnly);
testWidget->setStyle(oldStyle);
}
void tst_QLineEdit::validateOnFocusOut()
{
QSignalSpy editingFinishedSpy(testWidget, SIGNAL(editingFinished()));
testWidget->setValidator(new QIntValidator(100, 999, 0));
QTest::keyPress(testWidget, '1');
QTest::keyPress(testWidget, '0');
QCOMPARE(testWidget->text(), QString("10"));
testWidget->clearFocus();
QCOMPARE(editingFinishedSpy.count(), 0);
testWidget->setFocus();
testWidget->activateWindow();
QTRY_VERIFY(testWidget->hasFocus());
QTest::keyPress(testWidget, '0');
QTRY_COMPARE(testWidget->text(), QString("100"));
testWidget->clearFocus();
QCOMPARE(editingFinishedSpy.count(), 1);
}
void tst_QLineEdit::editInvalidText()
{
testWidget->clear();
testWidget->setValidator(new QIntValidator(0, 120, 0));
testWidget->setText("1234");
QVERIFY(!testWidget->hasAcceptableInput());
QTest::keyPress(testWidget, Qt::Key_Backspace);
QTest::keyPress(testWidget, Qt::Key_Backspace);
QTest::keyPress(testWidget, Qt::Key_A);
QTest::keyPress(testWidget, Qt::Key_B);
QTest::keyPress(testWidget, Qt::Key_C);
QTest::keyPress(testWidget, Qt::Key_1);
QVERIFY(testWidget->hasAcceptableInput());
QCOMPARE(testWidget->text(), QString("12"));
testWidget->cursorBackward(false);
testWidget->cursorBackward(true, 2);
QTest::keyPress(testWidget, Qt::Key_Delete);
QVERIFY(testWidget->hasAcceptableInput());
QCOMPARE(testWidget->text(), QString("2"));
QTest::keyPress(testWidget, Qt::Key_1);
QVERIFY(testWidget->hasAcceptableInput());
QCOMPARE(testWidget->text(), QString("12"));
testWidget->setValidator(0);
}
void tst_QLineEdit::charWithAltOrCtrlModifier()
{
testWidget->clear();
QCOMPARE(testWidget->text(), QString(""));
QTest::keyPress(testWidget, Qt::Key_Plus);
QCOMPARE(testWidget->text(), QString("+"));
QTest::keyPress(testWidget, Qt::Key_Plus, Qt::ControlModifier);
QCOMPARE(testWidget->text(), QString("++"));
QTest::keyPress(testWidget, Qt::Key_Plus, Qt::AltModifier);
QCOMPARE(testWidget->text(), QString("+++"));
QTest::keyPress(testWidget, Qt::Key_Plus, Qt::AltModifier | Qt::ControlModifier);
QCOMPARE(testWidget->text(), QString("++++"));
}
void tst_QLineEdit::leftKeyOnSelectedText()
{
testWidget->clear();
testWidget->setText("0123");
testWidget->setCursorPosition(4);
QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
QCOMPARE(testWidget->cursorPosition(), 3);
QCOMPARE(testWidget->selectedText(), QString("3"));
QTest::keyClick(testWidget, Qt::Key_Left, Qt::ShiftModifier);
QCOMPARE(testWidget->cursorPosition(), 2);
QCOMPARE(testWidget->selectedText(), QString("23"));
QTest::keyClick(testWidget, Qt::Key_Left);
#ifdef Q_OS_WIN
QCOMPARE(testWidget->cursorPosition(), 1);
#else
// X11 used to behave like window prior to 4.2. Changes caused by QKeySequence
// resulted in an inadvertant change in behavior
QCOMPARE(testWidget->cursorPosition(), 2);
#endif
}
void tst_QLineEdit::inlineCompletion()
{
testWidget->clear();
QStandardItemModel *model = new QStandardItemModel;
QStandardItem *root = model->invisibleRootItem();
QStandardItem *items[5];
for (int i = 0; i < 5; i++) {
items[i] = new QStandardItem(QString("item%1").arg(i));
if ((i+2)%2 == 0) { // disable 0,2,4
items[i]->setFlags(items[i]->flags() & ~Qt::ItemIsEnabled);
}
root->appendRow(items[i]);
}
QCompleter *completer = new QCompleter(model);
completer->setCompletionMode(QCompleter::InlineCompletion);
completer->setCaseSensitivity(Qt::CaseInsensitive);
testWidget->setFocus();
QTRY_COMPARE(qApp->activeWindow(), (QWidget*)testWidget);
testWidget->setCompleter(completer);
// sanity
QTest::keyClick(testWidget, Qt::Key_X);
QCOMPARE(testWidget->selectedText(), QString());
QCOMPARE(testWidget->text(), QString("x"));
QTest::keyClick(testWidget, Qt::Key_Down, Qt::ControlModifier);
QCOMPARE(testWidget->selectedText(), QString());
QCOMPARE(testWidget->text(), QString("x"));
QTest::keyClick(testWidget, Qt::Key_Up, Qt::ControlModifier);
QCOMPARE(testWidget->selectedText(), QString());
QCOMPARE(testWidget->text(), QString("x"));
testWidget->clear();
QTest::keyClick(testWidget, Qt::Key_I);
QCOMPARE(testWidget->selectedText(), QString("tem1"));
Qt::KeyboardModifiers keyboardModifiers = Qt::ControlModifier;
#ifdef Q_WS_MAC
keyboardModifiers |= Qt::AltModifier;
#endif
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
QCOMPARE(testWidget->selectedText(), QString("tem3"));
// wraps around (Default)
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
QCOMPARE(testWidget->selectedText(), QString("tem1"));
QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers);
QCOMPARE(testWidget->selectedText(), QString("tem3"));
// should not wrap
completer->setWrapAround(false);
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
QCOMPARE(testWidget->selectedText(), QString("tem3"));
QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers); // item1
QTest::keyClick(testWidget, Qt::Key_Up, keyboardModifiers); // item1
QCOMPARE(testWidget->selectedText(), QString("tem1"));
// trivia :)
root->appendRow(new QStandardItem("item11"));
root->appendRow(new QStandardItem("item12"));
testWidget->clear();
QTest::keyClick(testWidget, Qt::Key_I);
QCOMPARE(testWidget->selectedText(), QString("tem1"));
QTest::keyClick(testWidget, Qt::Key_Delete);
QCOMPARE(testWidget->selectedText(), QString());
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
QCOMPARE(testWidget->selectedText(), QString("tem1")); // neato
testWidget->setText("item1");
testWidget->setSelection(1, 2);
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers);
testWidget->end(false);
QCOMPARE(testWidget->text(), QString("item1")); // no effect for selection in "middle"
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers); // item1
QTest::keyClick(testWidget, Qt::Key_Down, keyboardModifiers); // item11
QCOMPARE(testWidget->text(), QString("item11"));
delete model;
delete completer;
}
void tst_QLineEdit::noTextEditedOnClear()
{
testWidget->setText("Test");
QSignalSpy textEditedSpy(testWidget, SIGNAL(textEdited(const QString &)));
testWidget->clear();
QCOMPARE(textEditedSpy.count(), 0);
}
void tst_QLineEdit::textMargin_data()
{
QTest::addColumn<int>("left");
QTest::addColumn<int>("top");
QTest::addColumn<int>("right");
QTest::addColumn<int>("bottom");
QTest::addColumn<QPoint>("mousePressPos");
QTest::addColumn<int>("cursorPosition");
QLineEdit testWidget;
QFontMetrics metrics(testWidget.font());
const QString s = QLatin1String("MMM MMM MMM");
// Different styles generate different offsets, so
// calculate the width rather than hardcode it.
const int pixelWidthOfM = metrics.width(s, 1);
const int pixelWidthOfMMM_MM = metrics.width(s, 6);
QTest::newRow("default-0") << 0 << 0 << 0 << 0 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
QTest::newRow("default-1") << 0 << 0 << 0 << 0 << QPoint(1, 1) << 0;
QTest::newRow("default-2") << -1 << 0 << -1 << 0 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
QTest::newRow("default-3") << 0 << 0 << 0 << 0 << QPoint(pixelWidthOfM, 1) << 1;
QTest::newRow("hor-0") << 10 << 0 << 10 << 0 << QPoint(1, 1) << 0;
QTest::newRow("hor-1") << 10 << 0 << 10 << 0 << QPoint(10, 1) << 0;
QTest::newRow("hor-2") << 20 << 0 << 10 << 0 << QPoint(20, 1) << 0;
if (!qApp->style()->inherits("QMacStyle")) { //MacStyle doesn't support verticals margins.
QTest::newRow("default-2-ver") << -1 << -1 << -1 << -1 << QPoint(pixelWidthOfMMM_MM, 0) << 6;
QTest::newRow("ver") << 0 << 10 << 0 << 10 << QPoint(1, 1) << 0;
}
}
void tst_QLineEdit::textMargin()
{
QFETCH(int, left);
QFETCH(int, top);
QFETCH(int, right);
QFETCH(int, bottom);
QFETCH(QPoint, mousePressPos);
QFETCH(int, cursorPosition);
// Put the line edit into a toplevel window to avoid
// resizing by the window system.
QWidget tlw;
QLineEdit testWidget(&tlw);
testWidget.setGeometry(100, 100, 100, 30);
testWidget.setText("MMM MMM MMM");
testWidget.setCursorPosition(6);
QSize sizeHint = testWidget.sizeHint();
testWidget.setTextMargins(left, top, right, bottom);
sizeHint.setWidth(sizeHint.width() + left + right);
sizeHint.setHeight(sizeHint.height() + top +bottom);
QCOMPARE(testWidget.sizeHint(), sizeHint);
testWidget.setFrame(false);
tlw.show();
int l;
int t;
int r;
int b;
testWidget.getTextMargins(&l, &t, &r, &b);
QCOMPARE(left, l);
QCOMPARE(top, t);
QCOMPARE(right, r);
QCOMPARE(bottom, b);
QTest::mouseClick(&testWidget, Qt::LeftButton, 0, mousePressPos);
QTRY_COMPARE(testWidget.cursorPosition(), cursorPosition);
}
void tst_QLineEdit::cursor()
{
#ifdef QT_NO_CURSOR
QSKIP("Qt compiled without cursor support", SkipAll);
#else
testWidget->setReadOnly(false);
QCOMPARE(testWidget->cursor().shape(), Qt::IBeamCursor);
testWidget->setReadOnly(true);
QCOMPARE(testWidget->cursor().shape(), Qt::ArrowCursor);
testWidget->setReadOnly(false);
QCOMPARE(testWidget->cursor().shape(), Qt::IBeamCursor);
#endif
}
class task180999_Widget : public QWidget
{
public:
task180999_Widget(QWidget *parent = 0) : QWidget(parent)
{
QHBoxLayout *layout = new QHBoxLayout(this);
lineEdit1.setText("some text 1 ...");
lineEdit2.setText("some text 2 ...");
layout->addWidget(&lineEdit1);
layout->addWidget(&lineEdit2);
}
QLineEdit lineEdit1;
QLineEdit lineEdit2;
};
void tst_QLineEdit::task180999_focus()
{
task180999_Widget widget;
widget.lineEdit1.setFocus();
widget.show();
widget.lineEdit2.setFocus();
widget.lineEdit2.selectAll();
widget.hide();
widget.lineEdit1.setFocus();
widget.show();
QTest::qWait(200);
widget.activateWindow();
QTRY_VERIFY(!widget.lineEdit2.hasSelectedText());
}
void tst_QLineEdit::task174640_editingFinished()
{
QWidget mw;
QVBoxLayout *layout = new QVBoxLayout(&mw);
QLineEdit *le1 = new QLineEdit(&mw);
QLineEdit *le2 = new QLineEdit(&mw);
layout->addWidget(le1);
layout->addWidget(le2);
mw.show();
QApplication::setActiveWindow(&mw);
mw.activateWindow();
QTest::qWaitForWindowShown(&mw);
QTRY_COMPARE(&mw, QApplication::activeWindow());
QSignalSpy editingFinishedSpy(le1, SIGNAL(editingFinished()));
le1->setFocus();
QTest::qWait(20);
QTRY_VERIFY(le1->hasFocus());
QCOMPARE(editingFinishedSpy.count(), 0);
le2->setFocus();
QTest::qWait(20);
QTRY_VERIFY(le2->hasFocus());
QCOMPARE(editingFinishedSpy.count(), 1);
editingFinishedSpy.clear();
le1->setFocus();
QTest::qWait(20);
QTRY_VERIFY(le1->hasFocus());
QMenu *testMenu1 = new QMenu(le1);
testMenu1->addAction("foo");
testMenu1->addAction("bar");
testMenu1->show();
QTest::qWaitForWindowShown(testMenu1);
QTest::qWait(20);
mw.activateWindow();
delete testMenu1;
QCOMPARE(editingFinishedSpy.count(), 0);
QTRY_VERIFY(le1->hasFocus());
QMenu *testMenu2 = new QMenu(le2);
testMenu2->addAction("foo2");
testMenu2->addAction("bar2");
testMenu2->show();
QTest::qWaitForWindowShown(testMenu2);
QTest::qWait(20);
mw.activateWindow();
delete testMenu2;
QCOMPARE(editingFinishedSpy.count(), 1);
}
#ifndef QT_NO_COMPLETER
class task198789_Widget : public QWidget
{
Q_OBJECT
public:
task198789_Widget(QWidget *parent = 0) : QWidget(parent)
{
QStringList wordList;
wordList << "alpha" << "omega" << "omicron" << "zeta";
lineEdit = new QLineEdit(this);
completer = new QCompleter(wordList, this);
lineEdit->setCompleter(completer);
connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
}
QLineEdit *lineEdit;
QCompleter *completer;
QString currentCompletion;
private slots:
void textChanged(const QString &)
{
currentCompletion = completer->currentCompletion();
}
};
void tst_QLineEdit::task198789_currentCompletion()
{
task198789_Widget widget;
widget.show();
qApp->processEvents();
QTest::keyPress(widget.lineEdit, 'o');
QTest::keyPress(widget.lineEdit, 'm');
QTest::keyPress(widget.lineEdit, 'i');
QCOMPARE(widget.currentCompletion, QLatin1String("omicron"));
}
void tst_QLineEdit::task210502_caseInsensitiveInlineCompletion()
{
QString completion("ABCD");
QStringList completions;
completions << completion;
QLineEdit lineEdit;
QCompleter completer(completions);
completer.setCaseSensitivity(Qt::CaseInsensitive);
completer.setCompletionMode(QCompleter::InlineCompletion);
lineEdit.setCompleter(&completer);
lineEdit.show();
QTest::qWaitForWindowShown(&lineEdit);
QApplication::setActiveWindow(&lineEdit);
lineEdit.setFocus();
QTRY_VERIFY(lineEdit.hasFocus());
QTest::keyPress(&lineEdit, 'a');
QTest::keyPress(&lineEdit, Qt::Key_Return);
QCOMPARE(lineEdit.text(), completion);
}
#endif // QT_NO_COMPLETER
void tst_QLineEdit::task229938_dontEmitChangedWhenTextIsNotChanged()
{
QLineEdit lineEdit;
lineEdit.setMaxLength(5);
lineEdit.show();
#ifdef Q_WS_X11
// to be safe and avoid failing setFocus with window managers
qt_x11_wait_for_window_manager(&lineEdit);
#endif
lineEdit.setFocus();
QSignalSpy changedSpy(&lineEdit, SIGNAL(textChanged(QString)));
QTest::qWait(200);
QTest::keyPress(&lineEdit, 'a');
QTest::keyPress(&lineEdit, 'b');
QTest::keyPress(&lineEdit, 'c');
QTest::keyPress(&lineEdit, 'd');
QTest::keyPress(&lineEdit, 'e');
QTest::keyPress(&lineEdit, 'f');
QCOMPARE(changedSpy.count(), 5);
}
void tst_QLineEdit::task233101_cursorPosAfterInputMethod_data()
{
QTest::addColumn<int>("maxLength");
QTest::addColumn<int>("cursorPos");
QTest::addColumn<int>("replacementStart");
QTest::addColumn<int>("replacementLength");
QTest::addColumn<QString>("commitString");
QTest::newRow("") << 4 << 4 << 0 << 0 << QString("");
QTest::newRow("") << 4 << 4 << 0 << 0 << QString("x");
QTest::newRow("") << 4 << 4 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 3 << 0 << 0 << QString("");
QTest::newRow("") << 4 << 3 << 0 << 0 << QString("x");
QTest::newRow("") << 4 << 3 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 0 << 0 << 0 << QString("");
QTest::newRow("") << 4 << 0 << 0 << 0 << QString("x");
QTest::newRow("") << 4 << 0 << 0 << 0 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 4 << -4 << 4 << QString("");
QTest::newRow("") << 4 << 4 << -4 << 4 << QString("x");
QTest::newRow("") << 4 << 4 << -4 << 4 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 3 << -3 << 4 << QString("");
QTest::newRow("") << 4 << 3 << -3 << 4 << QString("x");
QTest::newRow("") << 4 << 3 << -3 << 4 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 0 << 0 << 4 << QString("");
QTest::newRow("") << 4 << 0 << 0 << 4 << QString("x");
QTest::newRow("") << 4 << 0 << 0 << 4 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 4 << -4 << 0 << QString("");
QTest::newRow("") << 4 << 4 << -4 << 0 << QString("x");
QTest::newRow("") << 4 << 4 << -4 << 0 << QString("xxxxxxxxxxxxxxxx");
QTest::newRow("") << 4 << 3 << -3 << 0 << QString("");
QTest::newRow("") << 4 << 3 << -3 << 0 << QString("x");
QTest::newRow("") << 4 << 3 << -3 << 0 << QString("xxxxxxxxxxxxxxxx");
}
void tst_QLineEdit::task233101_cursorPosAfterInputMethod()
{
QFETCH(int, maxLength);
QFETCH(int, cursorPos);
QFETCH(int, replacementStart);
QFETCH(int, replacementLength);
QFETCH(QString, commitString);
QLineEdit lineEdit;
lineEdit.setMaxLength(maxLength);
lineEdit.insert(QString().fill(QLatin1Char('a'), cursorPos));
QCOMPARE(lineEdit.cursorPosition(), cursorPos);
QInputMethodEvent event;
event.setCommitString(QLatin1String("x"), replacementStart, replacementLength);
qApp->sendEvent(&lineEdit, &event);
QVERIFY(lineEdit.cursorPosition() >= 0);
QVERIFY(lineEdit.cursorPosition() <= lineEdit.text().size());
QVERIFY(lineEdit.text().size() <= lineEdit.maxLength());
}
void tst_QLineEdit::task241436_passwordEchoOnEditRestoreEchoMode()
{
QStyleOptionFrameV2 opt;
QChar fillChar = testWidget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, &opt, testWidget);
testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
testWidget->setFocus();
QApplication::setActiveWindow(testWidget);
QTRY_VERIFY(testWidget->hasFocus());
QTest::keyPress(testWidget, '0');
QCOMPARE(testWidget->displayText(), QString("0"));
testWidget->setEchoMode(QLineEdit::Normal);
testWidget->clearFocus();
QCOMPARE(testWidget->displayText(), QString("0"));
testWidget->activateWindow();
testWidget->setFocus();
testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
QTest::keyPress(testWidget, '0');
QCOMPARE(testWidget->displayText(), QString("0"));
testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
QCOMPARE(testWidget->displayText(), QString("0"));
testWidget->clearFocus();
QCOMPARE(testWidget->displayText(), QString(fillChar));
// restore clean state
testWidget->setEchoMode(QLineEdit::Normal);
}
void tst_QLineEdit::task248948_redoRemovedSelection()
{
testWidget->setText("a");
testWidget->selectAll();
QTest::keyPress(testWidget, Qt::Key_Delete);
testWidget->undo();
testWidget->redo();
QTest::keyPress(testWidget, 'a');
QTest::keyPress(testWidget, 'b');
QCOMPARE(testWidget->text(), QLatin1String("ab"));
}
void tst_QLineEdit::taskQTBUG_4401_enterKeyClearsPassword()
{
QString password("Wanna guess?");
testWidget->setText(password);
testWidget->setEchoMode(QLineEdit::PasswordEchoOnEdit);
testWidget->setFocus();
testWidget->selectAll();
QApplication::setActiveWindow(testWidget);
QTRY_VERIFY(testWidget->hasFocus());
QTest::keyPress(testWidget, Qt::Key_Enter);
QTRY_COMPARE(testWidget->text(), password);
}
void tst_QLineEdit::taskQTBUG_4679_moveToStartEndOfBlock()
{
#ifdef Q_OS_MAC
const QString text("there are no blocks for lineEdit");
testWidget->setText(text);
testWidget->setCursorPosition(5);
QCOMPARE(testWidget->cursorPosition(), 5);
testWidget->setFocus();
QTest::keyPress(testWidget, Qt::Key_A, Qt::MetaModifier);
QCOMPARE(testWidget->cursorPosition(), 0);
QTest::keyPress(testWidget, Qt::Key_E, Qt::MetaModifier);
QCOMPARE(testWidget->cursorPosition(), text.size());
#endif // Q_OS_MAC
}
void tst_QLineEdit::taskQTBUG_4679_selectToStartEndOfBlock()
{
#ifdef Q_OS_MAC
const QString text("there are no blocks for lineEdit, select all");
testWidget->setText(text);
testWidget->setCursorPosition(5);
QCOMPARE(testWidget->cursorPosition(), 5);
testWidget->setFocus();
QTest::keyPress(testWidget, Qt::Key_A, Qt::MetaModifier | Qt::ShiftModifier);
QCOMPARE(testWidget->cursorPosition(), 0);
QVERIFY(testWidget->hasSelectedText());
QCOMPARE(testWidget->selectedText(), text.mid(0, 5));
QTest::keyPress(testWidget, Qt::Key_E, Qt::MetaModifier | Qt::ShiftModifier);
QCOMPARE(testWidget->cursorPosition(), text.size());
QVERIFY(testWidget->hasSelectedText());
QCOMPARE(testWidget->selectedText(), text.mid(5));
#endif // Q_OS_MAC
}
#ifndef QT_NO_CONTEXTMENU
void tst_QLineEdit::taskQTBUG_7902_contextMenuCrash()
{
// Would pass before the associated commit, but left as a guard.
QLineEdit *w = new QLineEdit;
w->show();
QTest::qWaitForWindowShown(w);
QTimer ti;
w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater()));
ti.start(200);
QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center());
qApp->postEvent(w, cme);
QTest::qWait(300);
// No crash, it's allright.
}
#endif
void tst_QLineEdit::taskQTBUG_7395_readOnlyShortcut()
{
//ReadOnly QLineEdit should not intercept shortcut.
QLineEdit le;
le.setReadOnly(true);
QAction action(QString::fromLatin1("hello"), &le);
action.setShortcut(QString::fromLatin1("p"));
QSignalSpy spy(&action, SIGNAL(triggered()));
le.addAction(&action);
le.show();
QTest::qWaitForWindowShown(&le);
QApplication::setActiveWindow(&le);
le.setFocus();
QTRY_VERIFY(le.hasFocus());
QTest::keyClick(0, Qt::Key_P);
QCOMPARE(spy.count(), 1);
}
void tst_QLineEdit::QTBUG697_paletteCurrentColorGroup()
{
#ifndef Q_WS_X11
QSKIP("Only tested on X11", SkipAll);
#endif
QLineEdit le;
le.setText(" ");
QPalette p = le.palette();
p.setBrush(QPalette::Active, QPalette::Highlight, Qt::green);
p.setBrush(QPalette::Inactive, QPalette::Highlight, Qt::red);
le.setPalette(p);
le.show();
QApplication::setActiveWindow(&le);
QTest::qWaitForWindowShown(&le);
le.setFocus();
QTRY_VERIFY(le.hasFocus());
le.selectAll();
QImage img(le.size(),QImage::Format_ARGB32 );
le.render(&img);
QCOMPARE(img.pixel(10, le.height()/2), QColor(Qt::green).rgb());
QApplication::setActiveWindow(0);
le.render(&img);
QCOMPARE(img.pixel(10, le.height()/2), QColor(Qt::red).rgb());
}
void tst_QLineEdit::QTBUG13520_textNotVisible()
{
LineEdit le;
le.setAlignment( Qt::AlignRight | Qt::AlignVCenter);
le.show();
QTest::qWaitForWindowShown(&le);
le.setText("01-ST16-01SIL-MPL001wfgsdfgsdgsdfgsdfgsdfgsdfgsdfg");
le.setCursorPosition(0);
QTest::qWait(100); //just make sure we get he lineedit correcly painted
QVERIFY(le.cursorRect().center().x() < le.width() / 2);
}
void tst_QLineEdit::bidiVisualMovement_data()
{
QTest::addColumn<QString>("logical");
QTest::addColumn<int>("basicDir");
QTest::addColumn<IntList>("positionList");
QTest::newRow("Latin text")
<< QString::fromUtf8("abc")
<< (int) QChar::DirL
<< (IntList() << 0 << 1 << 2 << 3);
QTest::newRow("Hebrew text, one item")
<< QString::fromUtf8("\327\220\327\221\327\222")
<< (int) QChar::DirR
<< (QList<int>() << 0 << 1 << 2 << 3);
QTest::newRow("Hebrew text after Latin text")
<< QString::fromUtf8("abc\327\220\327\221\327\222")
<< (int) QChar::DirL
<< (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
QTest::newRow("Latin text after Hebrew text")
<< QString::fromUtf8("\327\220\327\221\327\222abc")
<< (int) QChar::DirR
<< (QList<int>() << 0 << 1 << 2 << 6 << 5 << 4 << 3);
QTest::newRow("LTR, 3 items")
<< QString::fromUtf8("abc\327\220\327\221\327\222abc")
<< (int) QChar::DirL
<< (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
QTest::newRow("RTL, 3 items")
<< QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222")
<< (int) QChar::DirR
<< (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 9);
QTest::newRow("LTR, 4 items")
<< QString::fromUtf8("abc\327\220\327\221\327\222abc\327\220\327\221\327\222")
<< (int) QChar::DirL
<< (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
QTest::newRow("RTL, 4 items")
<< QString::fromUtf8("\327\220\327\221\327\222abc\327\220\327\221\327\222abc")
<< (int) QChar::DirR
<< (QList<int>() << 0 << 1 << 2 << 5 << 4 << 3 << 6 << 7 << 8 << 12 << 11 << 10 << 9);
}
void tst_QLineEdit::bidiVisualMovement()
{
QFETCH(QString, logical);
QFETCH(int, basicDir);
QFETCH(IntList, positionList);
QLineEdit le;
le.setText(logical);
le.setCursorMoveStyle(Qt::VisualMoveStyle);
le.setCursorPosition(0);
bool moved;
int i = 0, oldPos, newPos = 0;
do {
oldPos = newPos;
QVERIFY(oldPos == positionList[i]);
if (basicDir == QChar::DirL) {
QTest::keyClick(&le, Qt::Key_Right);
} else
QTest::keyClick(&le, Qt::Key_Left);
newPos = le.cursorPosition();
moved = (oldPos != newPos);
i++;
} while (moved);
QVERIFY(i == positionList.size());
do {
i--;
oldPos = newPos;
QVERIFY(oldPos == positionList[i]);
if (basicDir == QChar::DirL) {
QTest::keyClick(&le, Qt::Key_Left);
} else
{
QTest::keyClick(&le, Qt::Key_Right);
}
newPos = le.cursorPosition();
moved = (oldPos != newPos);
} while (moved && i >= 0);
}
void tst_QLineEdit::bidiLogicalMovement_data()
{
bidiVisualMovement_data();
}
void tst_QLineEdit::bidiLogicalMovement()
{
QFETCH(QString, logical);
QFETCH(int, basicDir);
QLineEdit le;
le.setText(logical);
le.setCursorMoveStyle(Qt::LogicalMoveStyle);
le.setCursorPosition(0);
bool moved;
int i = 0, oldPos, newPos = 0;
do {
oldPos = newPos;
QVERIFY(oldPos == i);
if (basicDir == QChar::DirL) {
QTest::keyClick(&le, Qt::Key_Right);
} else
QTest::keyClick(&le, Qt::Key_Left);
newPos = le.cursorPosition();
moved = (oldPos != newPos);
i++;
} while (moved);
do {
i--;
oldPos = newPos;
QVERIFY(oldPos == i);
if (basicDir == QChar::DirL) {
QTest::keyClick(&le, Qt::Key_Left);
} else
{
QTest::keyClick(&le, Qt::Key_Right);
}
newPos = le.cursorPosition();
moved = (oldPos != newPos);
} while (moved && i >= 0);
}
void tst_QLineEdit::selectAndCursorPosition()
{
testWidget->setText("This is a long piece of text");
testWidget->setSelection(0, 5);
QCOMPARE(testWidget->cursorPosition(), 5);
testWidget->setSelection(5, -5);
QCOMPARE(testWidget->cursorPosition(), 0);
}
void tst_QLineEdit::inputMethodSelection()
{
testWidget->setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
testWidget->setSelection(0,0);
QSignalSpy selectionSpy(testWidget, SIGNAL(selectionChanged()));
QCOMPARE(selectionSpy.count(), 0);
QCOMPARE(testWidget->selectionStart(), -1);
testWidget->setSelection(0,5);
QCOMPARE(selectionSpy.count(), 1);
QCOMPARE(testWidget->selectionStart(), 0);
QList<QInputMethodEvent::Attribute> attributes;
attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
QInputMethodEvent event("", attributes);
QApplication::sendEvent(testWidget, &event);
QCOMPARE(selectionSpy.count(), 2);
QCOMPARE(testWidget->selectionStart(), 12);
}
QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc"