/****************************************************************************
**
** Copyright (C) 2009 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$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qtextedit.h>
#include <qtextcursor.h>
#include <qtextlist.h>
#include <qdebug.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <qtextbrowser.h>
#include <private/qtextcontrol_p.h>
#include <qscrollbar.h>
#include <qtextobject.h>
#include <qabstracttextdocumentlayout.h>
#include <qtextdocumentfragment.h>
#include "qplaintextedit.h"
//Used in copyAvailable
typedef QPair<Qt::Key, Qt::KeyboardModifier> keyPairType;
typedef QList<keyPairType> pairListType;
Q_DECLARE_METATYPE(pairListType);
Q_DECLARE_METATYPE(keyPairType);
Q_DECLARE_METATYPE(QList<bool>);
#ifdef Q_WS_MAC
#include <Carbon/Carbon.h>
#endif
QT_FORWARD_DECLARE_CLASS(QPlainTextEdit)
//TESTED_CLASS=
//TESTED_FILES=gui/widgets/qtextedit.h gui/widgets/qtextedit.cpp
class tst_QPlainTextEdit : public QObject
{
Q_OBJECT
public:
tst_QPlainTextEdit();
public slots:
void initTestCase();
void init();
void cleanup();
private slots:
void getSetCheck();
#ifndef QT_NO_CLIPBOARD
void clearMustNotChangeClipboard();
#endif
void clearMustNotResetRootFrameMarginToDefault();
void paragSeparatorOnPlaintextAppend();
#ifndef QT_NO_CLIPBOARD
void selectAllSetsNotSelection();
#endif
void asciiTab();
void setDocument();
void emptyAppend();
void appendOnEmptyDocumentShouldReuseInitialParagraph();
void cursorPositionChanged();
void setTextCursor();
#ifndef QT_NO_CLIPBOARD
void undoAvailableAfterPaste();
#endif
void undoRedoAvailableRepetition();
void appendShouldNotTouchTheSelection();
void backspace();
void shiftBackspace();
void undoRedo();
void preserveCharFormatInAppend();
#ifndef QT_NO_CLIPBOARD
void copyAndSelectAllInReadonly();
#endif
void ctrlAltInput();
void noPropertiesOnDefaultTextEditCharFormat();
void setPlainTextShouldEmitTextChangedOnce();
void overwriteMode();
void shiftDownInLineLastShouldSelectToEnd_data();
void shiftDownInLineLastShouldSelectToEnd();
void undoRedoShouldRepositionTextEditCursor();
void lineWrapModes();
void mouseCursorShape();
void implicitClear();
void undoRedoAfterSetContent();
void numPadKeyNavigation();
void moveCursor();
#ifndef QT_NO_CLIPBOARD
void mimeDataReimplementations();
#endif
void shiftEnterShouldInsertLineSeparator();
void selectWordsFromStringsContainingSeparators_data();
void selectWordsFromStringsContainingSeparators();
#ifndef QT_NO_CLIPBOARD
void canPaste();
void copyAvailable_data();
void copyAvailable();
#endif
void ensureCursorVisibleOnInitialShow();
void setTextInsideResizeEvent();
void colorfulAppend();
void ensureVisibleWithRtl();
void preserveCharFormatAfterSetPlainText();
void extraSelections();
void adjustScrollbars();
void textObscuredByScrollbars();
void setTextPreservesUndoRedoEnabled();
void wordWrapProperty();
void lineWrapProperty();
void selectionChanged();
void blockCountChanged();
private:
void createSelection();
int blockCount() const;
int lineCount() const;
bool nativeClipboardWorking();
QPlainTextEdit *ed;
qreal rootFrameMargin;
};
bool tst_QPlainTextEdit::nativeClipboardWorking()
{
#ifdef Q_WS_MAC
PasteboardRef pasteboard;
OSStatus status = PasteboardCreate(0, &pasteboard);
if (status == noErr)
CFRelease(pasteboard);
return status == noErr;
#endif
return true;
}
// Testing get/set functions
void tst_QPlainTextEdit::getSetCheck()
{
QPlainTextEdit obj1;
// QTextDocument * QPlainTextEdit::document()
// void QPlainTextEdit::setDocument(QTextDocument *)
QTextDocument *var1 = new QTextDocument;
var1->setDocumentLayout(new QPlainTextDocumentLayout(var1));
obj1.setDocument(var1);
QCOMPARE(var1, obj1.document());
obj1.setDocument((QTextDocument *)0);
QVERIFY(var1 != obj1.document()); // QPlainTextEdit creates a new document when setting 0
QVERIFY((QTextDocument *)0 != obj1.document());
delete var1;
// bool QPlainTextEdit::tabChangesFocus()
// void QPlainTextEdit::setTabChangesFocus(bool)
obj1.setTabChangesFocus(false);
QCOMPARE(false, obj1.tabChangesFocus());
obj1.setTabChangesFocus(true);
QCOMPARE(true, obj1.tabChangesFocus());
// LineWrapMode QPlainTextEdit::lineWrapMode()
// void QPlainTextEdit::setLineWrapMode(LineWrapMode)
obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::NoWrap));
QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::NoWrap), obj1.lineWrapMode());
obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::WidgetWidth));
QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::WidgetWidth), obj1.lineWrapMode());
// obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedPixelWidth));
// QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedPixelWidth), obj1.lineWrapMode());
// obj1.setLineWrapMode(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedColumnWidth));
// QCOMPARE(QPlainTextEdit::LineWrapMode(QPlainTextEdit::FixedColumnWidth), obj1.lineWrapMode());
// bool QPlainTextEdit::overwriteMode()
// void QPlainTextEdit::setOverwriteMode(bool)
obj1.setOverwriteMode(false);
QCOMPARE(false, obj1.overwriteMode());
obj1.setOverwriteMode(true);
QCOMPARE(true, obj1.overwriteMode());
// int QPlainTextEdit::tabStopWidth()
// void QPlainTextEdit::setTabStopWidth(int)
obj1.setTabStopWidth(0);
QCOMPARE(0, obj1.tabStopWidth());
obj1.setTabStopWidth(INT_MIN);
QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
#if defined(QT_ARCH_WINDOWSCE) || defined (QT_ARCH_SYMBIAN)
// due to rounding error in qRound when qreal==float
// we cannot use INT_MAX for this check
obj1.setTabStopWidth(SHRT_MAX*2);
QCOMPARE(SHRT_MAX*2, obj1.tabStopWidth());
#else
obj1.setTabStopWidth(INT_MAX);
QCOMPARE(INT_MAX, obj1.tabStopWidth());
#endif
}
class QtTestDocumentLayout : public QAbstractTextDocumentLayout
{
Q_OBJECT
public:
inline QtTestDocumentLayout(QPlainTextEdit *edit, QTextDocument *doc, int &itCount)
: QAbstractTextDocumentLayout(doc), useBiggerSize(false), ed(edit), iterationCounter(itCount) {}
virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &) {}
virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const { return 0; }
virtual void documentChanged(int, int, int) {}
virtual int pageCount() const { return 1; }
virtual QSizeF documentSize() const { return usedSize; }
virtual QRectF frameBoundingRect(QTextFrame *) const { return QRectF(); }
virtual QRectF blockBoundingRect(const QTextBlock &) const { return QRectF(); }
bool useBiggerSize;
QSize usedSize;
QPlainTextEdit *ed;
int &iterationCounter;
};
tst_QPlainTextEdit::tst_QPlainTextEdit()
{}
void tst_QPlainTextEdit::initTestCase()
{
#ifdef Q_OS_WINCE //disable magic for WindowsCE
qApp->setAutoMaximizeThreshold(-1);
#endif
}
void tst_QPlainTextEdit::init()
{
ed = new QPlainTextEdit(0);
rootFrameMargin = ed->document()->documentMargin();
}
void tst_QPlainTextEdit::cleanup()
{
delete ed;
ed = 0;
}
void tst_QPlainTextEdit::createSelection()
{
QTest::keyClicks(ed, "Hello World");
/* go to start */
#ifndef Q_WS_MAC
QTest::keyClick(ed, Qt::Key_Home, Qt::ControlModifier);
#else
QTest::keyClick(ed, Qt::Key_Home);
#endif
QCOMPARE(ed->textCursor().position(), 0);
/* select until end of text */
#ifndef Q_WS_MAC
QTest::keyClick(ed, Qt::Key_End, Qt::ControlModifier | Qt::ShiftModifier);
#else
QTest::keyClick(ed, Qt::Key_End, Qt::ShiftModifier);
#endif
QCOMPARE(ed->textCursor().position(), 11);
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::clearMustNotChangeClipboard()
{
if (!nativeClipboardWorking())
QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
ed->textCursor().insertText("Hello World");
QString txt("This is different text");
QApplication::clipboard()->setText(txt);
ed->clear();
QCOMPARE(QApplication::clipboard()->text(), txt);
}
#endif
void tst_QPlainTextEdit::clearMustNotResetRootFrameMarginToDefault()
{
QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
ed->clear();
QCOMPARE(ed->document()->rootFrame()->frameFormat().margin(), rootFrameMargin);
}
void tst_QPlainTextEdit::paragSeparatorOnPlaintextAppend()
{
ed->appendPlainText("Hello\nWorld");
int cnt = 0;
QTextBlock blk = ed->document()->begin();
while (blk.isValid()) {
++cnt;
blk = blk.next();
}
QCOMPARE(cnt, 2);
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::selectAllSetsNotSelection()
{
if (!QApplication::clipboard()->supportsSelection()) {
QSKIP("Test only relevant for systems with selection", SkipAll);
return;
}
QApplication::clipboard()->setText(QString("foobar"), QClipboard::Selection);
QVERIFY(QApplication::clipboard()->text(QClipboard::Selection) == QString("foobar"));
ed->insertPlainText("Hello World");
ed->selectAll();
QCOMPARE(QApplication::clipboard()->text(QClipboard::Selection), QString::fromAscii("foobar"));
}
#endif
void tst_QPlainTextEdit::asciiTab()
{
QPlainTextEdit edit;
edit.setPlainText("\t");
edit.show();
qApp->processEvents();
QCOMPARE(edit.toPlainText().at(0), QChar('\t'));
}
void tst_QPlainTextEdit::setDocument()
{
QTextDocument *document = new QTextDocument(ed);
document->setDocumentLayout(new QPlainTextDocumentLayout(document));
QTextCursor(document).insertText("Test");
ed->setDocument(document);
QCOMPARE(ed->toPlainText(), QString("Test"));
}
int tst_QPlainTextEdit::blockCount() const
{
int blocks = 0;
for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
++blocks;
return blocks;
}
int tst_QPlainTextEdit::lineCount() const
{
int lines = 0;
for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next()) {
ed->document()->documentLayout()->blockBoundingRect(block);
lines += block.layout()->lineCount();
}
return lines;
}
// Supporter issue #56783
void tst_QPlainTextEdit::emptyAppend()
{
ed->appendPlainText("Blah");
QCOMPARE(blockCount(), 1);
ed->appendPlainText(QString::null);
QCOMPARE(blockCount(), 2);
ed->appendPlainText(QString(" "));
QCOMPARE(blockCount(), 3);
}
void tst_QPlainTextEdit::appendOnEmptyDocumentShouldReuseInitialParagraph()
{
QCOMPARE(blockCount(), 1);
ed->appendPlainText("Blah");
QCOMPARE(blockCount(), 1);
}
class CursorPositionChangedRecorder : public QObject
{
Q_OBJECT
public:
inline CursorPositionChangedRecorder(QPlainTextEdit *ed)
: editor(ed)
{
connect(editor, SIGNAL(cursorPositionChanged()), this, SLOT(recordCursorPos()));
}
QList<int> cursorPositions;
private slots:
void recordCursorPos()
{
cursorPositions.append(editor->textCursor().position());
}
private:
QPlainTextEdit *editor;
};
void tst_QPlainTextEdit::cursorPositionChanged()
{
QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
spy.clear();
QTest::keyClick(ed, Qt::Key_A);
QCOMPARE(spy.count(), 1);
QTextCursor cursor = ed->textCursor();
cursor.movePosition(QTextCursor::Start);
ed->setTextCursor(cursor);
cursor.movePosition(QTextCursor::End);
spy.clear();
cursor.insertText("Test");
QCOMPARE(spy.count(), 0);
cursor.movePosition(QTextCursor::End);
ed->setTextCursor(cursor);
cursor.movePosition(QTextCursor::Start);
spy.clear();
cursor.insertText("Test");
QCOMPARE(spy.count(), 1);
spy.clear();
QTest::keyClick(ed, Qt::Key_Left);
QCOMPARE(spy.count(), 1);
CursorPositionChangedRecorder spy2(ed);
QVERIFY(ed->textCursor().position() > 0);
ed->setPlainText("Hello World");
QCOMPARE(spy2.cursorPositions.count(), 1);
QCOMPARE(spy2.cursorPositions.at(0), 0);
QCOMPARE(ed->textCursor().position(), 0);
}
void tst_QPlainTextEdit::setTextCursor()
{
QSignalSpy spy(ed, SIGNAL(cursorPositionChanged()));
ed->setPlainText("Test");
QTextCursor cursor = ed->textCursor();
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter);
spy.clear();
ed->setTextCursor(cursor);
QCOMPARE(spy.count(), 1);
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::undoAvailableAfterPaste()
{
if (!nativeClipboardWorking())
QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
QSignalSpy spy(ed->document(), SIGNAL(undoAvailable(bool)));
const QString txt("Test");
QApplication::clipboard()->setText(txt);
ed->paste();
QVERIFY(spy.count() >= 1);
QCOMPARE(ed->toPlainText(), txt);
}
#endif
class UndoRedoRecorder : public QObject
{
Q_OBJECT
public:
UndoRedoRecorder(QTextDocument *doc)
: undoRepetitions(false)
, redoRepetitions(false)
, undoCount(0)
, redoCount(0)
{
connect(doc, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool)));
connect(doc, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool)));
}
bool undoRepetitions;
bool redoRepetitions;
private slots:
void undoAvailable(bool enabled) {
if (undoCount > 0 && enabled == lastUndoEnabled)
undoRepetitions = true;
++undoCount;
lastUndoEnabled = enabled;
}
void redoAvailable(bool enabled) {
if (redoCount > 0 && enabled == lastRedoEnabled)
redoRepetitions = true;
++redoCount;
lastRedoEnabled = enabled;
}
private:
bool lastUndoEnabled;
bool lastRedoEnabled;
int undoCount;
int redoCount;
};
void tst_QPlainTextEdit::undoRedoAvailableRepetition()
{
UndoRedoRecorder spy(ed->document());
ed->textCursor().insertText("ABC\n\nDEF\n\nGHI\n");
ed->textCursor().insertText("foo\n");
ed->textCursor().insertText("bar\n");
ed->undo(); ed->undo(); ed->undo();
ed->redo(); ed->redo(); ed->redo();
QVERIFY(!spy.undoRepetitions);
QVERIFY(!spy.redoRepetitions);
}
void tst_QPlainTextEdit::appendShouldNotTouchTheSelection()
{
QTextCursor cursor(ed->document());
QTextCharFormat fmt;
fmt.setForeground(Qt::blue);
cursor.insertText("H", fmt);
fmt.setForeground(Qt::red);
cursor.insertText("ey", fmt);
cursor.insertText("some random text inbetween");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
QCOMPARE(cursor.selectedText(), QString("Hey"));
ed->setTextCursor(cursor);
QVERIFY(ed->textCursor().hasSelection());
ed->appendHtml("<b>Some Bold Text</b>");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
}
void tst_QPlainTextEdit::backspace()
{
QTextCursor cursor = ed->textCursor();
QTextListFormat listFmt;
listFmt.setStyle(QTextListFormat::ListDisc);
listFmt.setIndent(1);
cursor.insertList(listFmt);
cursor.insertText("A");
ed->setTextCursor(cursor);
// delete 'A'
QTest::keyClick(ed, Qt::Key_Backspace);
QVERIFY(ed->textCursor().currentList());
// delete list
QTest::keyClick(ed, Qt::Key_Backspace);
QVERIFY(!ed->textCursor().currentList());
QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
// outdent paragraph
QTest::keyClick(ed, Qt::Key_Backspace);
QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
}
void tst_QPlainTextEdit::shiftBackspace()
{
QTextCursor cursor = ed->textCursor();
QTextListFormat listFmt;
listFmt.setStyle(QTextListFormat::ListDisc);
listFmt.setIndent(1);
cursor.insertList(listFmt);
cursor.insertText("A");
ed->setTextCursor(cursor);
// delete 'A'
QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
QVERIFY(ed->textCursor().currentList());
// delete list
QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
QVERIFY(!ed->textCursor().currentList());
QCOMPARE(ed->textCursor().blockFormat().indent(), 1);
// outdent paragraph
QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier);
QCOMPARE(ed->textCursor().blockFormat().indent(), 0);
}
void tst_QPlainTextEdit::undoRedo()
{
ed->clear();
QTest::keyClicks(ed, "abc d");
QCOMPARE(ed->toPlainText(), QString("abc d"));
ed->undo();
QCOMPARE(ed->toPlainText(), QString());
ed->redo();
QCOMPARE(ed->toPlainText(), QString("abc d"));
#ifdef Q_WS_WIN
// shortcut for undo
QTest::keyClick(ed, Qt::Key_Backspace, Qt::AltModifier);
QCOMPARE(ed->toPlainText(), QString());
// shortcut for redo
QTest::keyClick(ed, Qt::Key_Backspace, Qt::ShiftModifier|Qt::AltModifier);
QCOMPARE(ed->toPlainText(), QString("abc d"));
#endif
}
// Task #70465
void tst_QPlainTextEdit::preserveCharFormatInAppend()
{
ed->appendHtml("First para");
ed->appendHtml("<b>Second para</b>");
ed->appendHtml("third para");
QTextCursor cursor(ed->textCursor());
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
QCOMPARE(cursor.block().text(), QString("First para"));
cursor.movePosition(QTextCursor::NextBlock);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Bold);
QCOMPARE(cursor.block().text(), QString("Second para"));
cursor.movePosition(QTextCursor::NextBlock);
cursor.movePosition(QTextCursor::NextCharacter);
QCOMPARE(cursor.charFormat().fontWeight(), (int)QFont::Normal);
QCOMPARE(cursor.block().text(), QString("third para"));
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::copyAndSelectAllInReadonly()
{
if (!nativeClipboardWorking())
QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
ed->setReadOnly(true);
ed->setPlainText("Hello World");
QTextCursor cursor = ed->textCursor();
cursor.clearSelection();
ed->setTextCursor(cursor);
QVERIFY(!ed->textCursor().hasSelection());
QCOMPARE(ed->toPlainText(), QString("Hello World"));
// shouldn't do anything
QTest::keyClick(ed, Qt::Key_A);
QCOMPARE(ed->toPlainText(), QString("Hello World"));
QTest::keyClick(ed, Qt::Key_A, Qt::ControlModifier);
QVERIFY(ed->textCursor().hasSelection());
QApplication::clipboard()->setText(QString());
QVERIFY(QApplication::clipboard()->text().isEmpty());
QTest::keyClick(ed, Qt::Key_C, Qt::ControlModifier);
QCOMPARE(QApplication::clipboard()->text(), QString("Hello World"));
}
#endif
void tst_QPlainTextEdit::ctrlAltInput()
{
QTest::keyClick(ed, Qt::Key_At, Qt::ControlModifier | Qt::AltModifier);
QCOMPARE(ed->toPlainText(), QString("@"));
}
void tst_QPlainTextEdit::noPropertiesOnDefaultTextEditCharFormat()
{
// there should be no properties set on the default/initial char format
// on a text edit. Font properties instead should be taken from the
// widget's font (in sync with defaultFont property in document) and the
// foreground color should be taken from the palette.
QCOMPARE(ed->textCursor().charFormat().properties().count(), 0);
}
void tst_QPlainTextEdit::setPlainTextShouldEmitTextChangedOnce()
{
QSignalSpy spy(ed, SIGNAL(textChanged()));
ed->setPlainText("Yankee Doodle");
QCOMPARE(spy.count(), 1);
ed->setPlainText("");
QCOMPARE(spy.count(), 2);
}
void tst_QPlainTextEdit::overwriteMode()
{
QVERIFY(!ed->overwriteMode());
QTest::keyClicks(ed, "Some first text");
QCOMPARE(ed->toPlainText(), QString("Some first text"));
ed->setOverwriteMode(true);
QTextCursor cursor = ed->textCursor();
cursor.setPosition(5);
ed->setTextCursor(cursor);
QTest::keyClicks(ed, "shiny");
QCOMPARE(ed->toPlainText(), QString("Some shiny text"));
cursor.movePosition(QTextCursor::End);
ed->setTextCursor(cursor);
QTest::keyClick(ed, Qt::Key_Enter);
ed->setOverwriteMode(false);
QTest::keyClicks(ed, "Second paragraph");
QCOMPARE(blockCount(), 2);
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfBlock);
QCOMPARE(cursor.position(), 15);
ed->setTextCursor(cursor);
ed->setOverwriteMode(true);
QTest::keyClicks(ed, " blah");
QCOMPARE(blockCount(), 2);
QTextBlock block = ed->document()->begin();
QCOMPARE(block.text(), QString("Some shiny text blah"));
block = block.next();
QCOMPARE(block.text(), QString("Second paragraph"));
}
void tst_QPlainTextEdit::shiftDownInLineLastShouldSelectToEnd_data()
{
// shift cursor-down in the last line should select to the end of the document
QTest::addColumn<QString>("input");
QTest::addColumn<int>("totalLineCount");
QTest::newRow("1") << QString("Foo\nBar") << 2;
QTest::newRow("2") << QString("Foo\nBar") + QChar(QChar::LineSeparator) + QString("Baz") << 3;
}
void tst_QPlainTextEdit::shiftDownInLineLastShouldSelectToEnd()
{
QFETCH(QString, input);
QFETCH(int, totalLineCount);
ed->setPlainText(input);
ed->show();
// ensure we're layouted
for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
ed->document()->documentLayout()->blockBoundingRect(block);
QCOMPARE(blockCount(), 2);
int lineCount = 0;
for (QTextBlock block = ed->document()->begin(); block.isValid(); block = block.next())
lineCount += block.layout()->lineCount();
QCOMPARE(lineCount, totalLineCount);
QTextCursor cursor = ed->textCursor();
cursor.movePosition(QTextCursor::Start);
ed->setTextCursor(cursor);
for (int i = 0; i < lineCount; ++i) {
QTest::keyClick(ed, Qt::Key_Down, Qt::ShiftModifier);
}
input.replace(QLatin1Char('\n'), QChar(QChar::ParagraphSeparator));
QCOMPARE(ed->textCursor().selectedText(), input);
QVERIFY(ed->textCursor().atEnd());
// also test that without shift modifier the cursor does not move to the end
// for Key_Down in the last line
cursor.movePosition(QTextCursor::Start);
ed->setTextCursor(cursor);
for (int i = 0; i < lineCount; ++i) {
QTest::keyClick(ed, Qt::Key_Down);
}
QVERIFY(!ed->textCursor().atEnd());
}
void tst_QPlainTextEdit::undoRedoShouldRepositionTextEditCursor()
{
ed->setPlainText("five\nlines\nin\nthis\ntextedit");
QTextCursor cursor = ed->textCursor();
cursor.movePosition(QTextCursor::Start);
ed->setUndoRedoEnabled(false);
ed->setUndoRedoEnabled(true);
QVERIFY(!ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
cursor.insertText("Blah");
QVERIFY(ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
cursor.movePosition(QTextCursor::End);
ed->setTextCursor(cursor);
QVERIFY(QMetaObject::invokeMethod(ed, "undo"));
QVERIFY(!ed->document()->isUndoAvailable());
QVERIFY(ed->document()->isRedoAvailable());
QCOMPARE(ed->textCursor().position(), 0);
cursor.movePosition(QTextCursor::End);
ed->setTextCursor(cursor);
QVERIFY(QMetaObject::invokeMethod(ed, "redo"));
QVERIFY(ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
QCOMPARE(ed->textCursor().position(), 4);
}
void tst_QPlainTextEdit::lineWrapModes()
{
QWidget *window = new QWidget;
ed->setParent(window);
window->show();
ed->show();
ed->setPlainText("a b c d e f g h i j k l m n o p q r s t u v w x y z");
ed->setLineWrapMode(QPlainTextEdit::NoWrap);
QCOMPARE(lineCount(), 1);
ed->setLineWrapMode(QPlainTextEdit::WidgetWidth);
// QPlainTextEdit does lazy line layout on resize, only for the visible blocks.
// We thus need to make it wide enough to show something visible.
int minimumWidth = 2 * ed->document()->documentMargin();
minimumWidth += ed->fontMetrics().width(QLatin1Char('a'));
ed->resize(minimumWidth, 1000);
QCOMPARE(lineCount(), 26);
ed->setParent(0);
delete window;
}
void tst_QPlainTextEdit::mouseCursorShape()
{
#ifndef QT_NO_CURSOR
// always show an IBeamCursor, see change 170146
QVERIFY(!ed->isReadOnly());
QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
ed->setReadOnly(true);
QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
ed->setPlainText("Foo");
QVERIFY(ed->viewport()->cursor().shape() == Qt::IBeamCursor);
#endif
}
void tst_QPlainTextEdit::implicitClear()
{
// test that QPlainTextEdit::setHtml, etc. avoid calling clear() but instead call
// QTextDocument::setHtml/etc. instead, which also clear the contents and
// cached resource but preserve manually added resources. setHtml on a textedit
// should behave the same as on a document with respect to that.
// see also clearResources() autotest in qtextdocument
// regular resource for QTextDocument
QUrl testUrl(":/foobar");
QVariant testResource("hello world");
ed->document()->addResource(QTextDocument::ImageResource, testUrl, testResource);
QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
ed->setPlainText("Blah");
QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
ed->setPlainText("<b>Blah</b>");
QVERIFY(ed->document()->resource(QTextDocument::ImageResource, testUrl) == testResource);
ed->clear();
QVERIFY(!ed->document()->resource(QTextDocument::ImageResource, testUrl).isValid());
QVERIFY(ed->toPlainText().isEmpty());
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::copyAvailable_data()
{
QTest::addColumn<pairListType>("keystrokes");
QTest::addColumn<QList<bool> >("copyAvailable");
QTest::addColumn<QString>("function");
pairListType keystrokes;
QList<bool> copyAvailable;
keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier);
copyAvailable << true ;
QTest::newRow(QString("Case1 B,B, <- + shift | signals: true").toLatin1())
<< keystrokes << copyAvailable << QString();
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
<< qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
copyAvailable << true << false;
QTest::newRow(QString("Case2 T,A,A, <- + shift, cut() | signals: true, false").toLatin1())
<< keystrokes << copyAvailable << QString("cut");
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
<< qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier);
copyAvailable << true;
QTest::newRow(QString("Case3 T,A,A, <- + shift, <- + shift, <- + shift, copy() | signals: true").toLatin1())
<< keystrokes << copyAvailable << QString("copy");
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
<< qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
<< qMakePair(Qt::Key_X, Qt::ControlModifier);
copyAvailable << true << false;
QTest::newRow(QString("Case4 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, paste() | signals: true, false").toLatin1())
<< keystrokes << copyAvailable << QString("paste");
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_B, Qt::NoModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier);
copyAvailable << true << false;
QTest::newRow(QString("Case5 B,B, <- + shift, <- | signals: true, false").toLatin1())
<< keystrokes << copyAvailable << QString();
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_B, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::NoModifier)
<< qMakePair(Qt::Key_Right, Qt::ShiftModifier);
copyAvailable << true << false << true << false;
QTest::newRow(QString("Case6 B,A, <- + shift, ->, <- + shift | signals: true, false, true, false").toLatin1())
<< keystrokes << copyAvailable << QString("cut");
keystrokes.clear();
copyAvailable.clear();
keystrokes << qMakePair(Qt::Key_T, Qt::NoModifier) << qMakePair(Qt::Key_A, Qt::NoModifier)
<< qMakePair(Qt::Key_A, Qt::NoModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
<< qMakePair(Qt::Key_Left, Qt::ShiftModifier) << qMakePair(Qt::Key_Left, Qt::ShiftModifier)
<< qMakePair(Qt::Key_X, Qt::ControlModifier);
copyAvailable << true << false << true;
QTest::newRow(QString("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true").toLatin1())
<< keystrokes << copyAvailable << QString("undo");
}
//Tests the copyAvailable slot for several cases
void tst_QPlainTextEdit::copyAvailable()
{
QFETCH(pairListType,keystrokes);
QFETCH(QList<bool>, copyAvailable);
QFETCH(QString, function);
#ifdef Q_WS_MAC
QSKIP("copyAvailable has never passed on Mac, task to fix is 132482", SkipAll);
#endif
ed->clear();
QApplication::clipboard()->clear();
QVERIFY(!ed->canPaste());
QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool)));
//Execute Keystrokes
foreach(keyPairType keyPair, keystrokes) {
QTest::keyClick(ed, keyPair.first, keyPair.second );
}
//Execute ed->"function"
if (function == "cut")
ed->cut();
else if (function == "copy")
ed->copy();
else if (function == "paste")
ed->paste();
else if (function == "undo")
ed->paste();
else if (function == "redo")
ed->paste();
//Compare spied signals
QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true",
"Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort);
QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count());
for (int i=0;i<spyCopyAvailabe.count(); i++) {
QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0);
QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1());
}
}
#endif
void tst_QPlainTextEdit::undoRedoAfterSetContent()
{
QVERIFY(!ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
ed->setPlainText("Foobar");
QVERIFY(!ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
ed->setPlainText("<p>bleh</p>");
QVERIFY(!ed->document()->isUndoAvailable());
QVERIFY(!ed->document()->isRedoAvailable());
}
void tst_QPlainTextEdit::numPadKeyNavigation()
{
ed->setPlainText("Hello World");
QCOMPARE(ed->textCursor().position(), 0);
QTest::keyClick(ed, Qt::Key_Right, Qt::KeypadModifier);
QCOMPARE(ed->textCursor().position(), 1);
}
void tst_QPlainTextEdit::moveCursor()
{
ed->setPlainText("Test");
QSignalSpy cursorMovedSpy(ed, SIGNAL(cursorPositionChanged()));
QCOMPARE(ed->textCursor().position(), 0);
ed->moveCursor(QTextCursor::NextCharacter);
QCOMPARE(ed->textCursor().position(), 1);
QCOMPARE(cursorMovedSpy.count(), 1);
ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
QCOMPARE(ed->textCursor().position(), 2);
QCOMPARE(cursorMovedSpy.count(), 2);
QCOMPARE(ed->textCursor().selectedText(), QString("e"));
}
class MyTextEdit : public QPlainTextEdit
{
public:
inline MyTextEdit()
: createMimeDataCallCount(0),
canInsertCallCount(0),
insertCallCount(0)
{}
mutable int createMimeDataCallCount;
mutable int canInsertCallCount;
mutable int insertCallCount;
virtual QMimeData *createMimeDataFromSelection() const {
createMimeDataCallCount++;
return QPlainTextEdit::createMimeDataFromSelection();
}
virtual bool canInsertFromMimeData(const QMimeData *source) const {
canInsertCallCount++;
return QPlainTextEdit::canInsertFromMimeData(source);
}
virtual void insertFromMimeData(const QMimeData *source) {
insertCallCount++;
QPlainTextEdit::insertFromMimeData(source);
}
};
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::mimeDataReimplementations()
{
MyTextEdit ed;
ed.setPlainText("Hello World");
QCOMPARE(ed.createMimeDataCallCount, 0);
QCOMPARE(ed.canInsertCallCount, 0);
QCOMPARE(ed.insertCallCount, 0);
ed.selectAll();
QCOMPARE(ed.createMimeDataCallCount, 0);
QCOMPARE(ed.canInsertCallCount, 0);
QCOMPARE(ed.insertCallCount, 0);
ed.copy();
QCOMPARE(ed.createMimeDataCallCount, 1);
QCOMPARE(ed.canInsertCallCount, 0);
QCOMPARE(ed.insertCallCount, 0);
#ifdef QT_BUILD_INTERNAL
QTextControl *control = qFindChild<QTextControl *>(&ed);
QVERIFY(control);
control->canInsertFromMimeData(QApplication::clipboard()->mimeData());
QCOMPARE(ed.createMimeDataCallCount, 1);
QCOMPARE(ed.canInsertCallCount, 1);
QCOMPARE(ed.insertCallCount, 0);
ed.paste();
QCOMPARE(ed.createMimeDataCallCount, 1);
QCOMPARE(ed.canInsertCallCount, 1);
QCOMPARE(ed.insertCallCount, 1);
#endif
}
#endif
void tst_QPlainTextEdit::shiftEnterShouldInsertLineSeparator()
{
QTest::keyClick(ed, Qt::Key_A);
QTest::keyClick(ed, Qt::Key_Enter, Qt::ShiftModifier);
QTest::keyClick(ed, Qt::Key_B);
QString expected;
expected += 'a';
expected += QChar::LineSeparator;
expected += 'b';
QCOMPARE(ed->textCursor().block().text(), expected);
}
void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators_data()
{
QTest::addColumn<QString>("testString");
QTest::addColumn<QString>("selectedWord");
QStringList wordSeparators;
wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "["
<< "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp);
foreach (QString s, wordSeparators)
QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo");
}
void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators()
{
QFETCH(QString, testString);
QFETCH(QString, selectedWord);
ed->setPlainText(testString);
QTextCursor cursor = ed->textCursor();
cursor.movePosition(QTextCursor::StartOfLine);
cursor.select(QTextCursor::WordUnderCursor);
QVERIFY(cursor.hasSelection());
QCOMPARE(cursor.selection().toPlainText(), selectedWord);
cursor.clearSelection();
}
#ifndef QT_NO_CLIPBOARD
void tst_QPlainTextEdit::canPaste()
{
if (!nativeClipboardWorking())
QSKIP("Clipboard not working with cron-started unit tests", SkipAll);
QApplication::clipboard()->setText(QString());
QVERIFY(!ed->canPaste());
QApplication::clipboard()->setText("Test");
QVERIFY(ed->canPaste());
ed->setTextInteractionFlags(Qt::NoTextInteraction);
QVERIFY(!ed->canPaste());
}
#endif
void tst_QPlainTextEdit::ensureCursorVisibleOnInitialShow()
{
QString manyPagesOfPlainText;
for (int i = 0; i < 800; ++i)
manyPagesOfPlainText += QLatin1String("Blah blah blah blah blah blah\n");
ed->setPlainText(manyPagesOfPlainText);
QCOMPARE(ed->textCursor().position(), 0);
ed->moveCursor(QTextCursor::End);
ed->show();
QVERIFY(ed->verticalScrollBar()->value() > 10);
ed->moveCursor(QTextCursor::Start);
QVERIFY(ed->verticalScrollBar()->value() < 10);
ed->hide();
ed->verticalScrollBar()->setValue(ed->verticalScrollBar()->maximum());
ed->show();
QCOMPARE(ed->verticalScrollBar()->value(), ed->verticalScrollBar()->maximum());
}
class TestEdit : public QPlainTextEdit
{
public:
TestEdit() : resizeEventCalled(false) {}
bool resizeEventCalled;
protected:
virtual void resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
setPlainText("<img src=qtextbrowser-resizeevent.png width=" + QString::number(size().width()) + "><br>Size is " + QString::number(size().width()) + " x " + QString::number(size().height()));
resizeEventCalled = true;
}
};
void tst_QPlainTextEdit::setTextInsideResizeEvent()
{
TestEdit edit;
edit.show();
edit.resize(800, 600);
QVERIFY(edit.resizeEventCalled);
}
void tst_QPlainTextEdit::colorfulAppend()
{
QTextCharFormat fmt;
fmt.setForeground(QBrush(Qt::red));
ed->mergeCurrentCharFormat(fmt);
ed->appendPlainText("Red");
fmt.setForeground(QBrush(Qt::blue));
ed->mergeCurrentCharFormat(fmt);
ed->appendPlainText("Blue");
fmt.setForeground(QBrush(Qt::green));
ed->mergeCurrentCharFormat(fmt);
ed->appendPlainText("Green");
QCOMPARE(ed->document()->blockCount(), 3);
QTextBlock block = ed->document()->begin();
QCOMPARE(block.begin().fragment().text(), QString("Red"));
QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::red);
block = block.next();
QCOMPARE(block.begin().fragment().text(), QString("Blue"));
QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::blue);
block = block.next();
QCOMPARE(block.begin().fragment().text(), QString("Green"));
QVERIFY(block.begin().fragment().charFormat().foreground().color() == Qt::green);
}
void tst_QPlainTextEdit::ensureVisibleWithRtl()
{
ed->setLayoutDirection(Qt::RightToLeft);
ed->setLineWrapMode(QPlainTextEdit::NoWrap);
QString txt(500, QChar(QLatin1Char('a')));
QCOMPARE(txt.length(), 500);
ed->setPlainText(txt);
ed->resize(100, 100);
ed->show();
qApp->processEvents();
QVERIFY(ed->horizontalScrollBar()->maximum() > 0);
ed->moveCursor(QTextCursor::Start);
QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
ed->moveCursor(QTextCursor::End);
QCOMPARE(ed->horizontalScrollBar()->value(), 0);
ed->moveCursor(QTextCursor::Start);
QCOMPARE(ed->horizontalScrollBar()->value(), ed->horizontalScrollBar()->maximum());
ed->moveCursor(QTextCursor::End);
QCOMPARE(ed->horizontalScrollBar()->value(), 0);
}
void tst_QPlainTextEdit::preserveCharFormatAfterSetPlainText()
{
QTextCharFormat fmt;
fmt.setForeground(QBrush(Qt::blue));
ed->mergeCurrentCharFormat(fmt);
ed->setPlainText("This is blue");
ed->appendPlainText("This should still be blue");
QTextBlock block = ed->document()->begin();
block = block.next();
QCOMPARE(block.text(), QString("This should still be blue"));
QVERIFY(block.begin().fragment().charFormat().foreground().color() == QColor(Qt::blue));
}
void tst_QPlainTextEdit::extraSelections()
{
ed->setPlainText("Hello World");
QTextCursor c = ed->textCursor();
c.movePosition(QTextCursor::Start);
c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
const int endPos = c.position();
QTextEdit::ExtraSelection sel;
sel.cursor = c;
ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
c.movePosition(QTextCursor::Start);
c.movePosition(QTextCursor::NextWord);
const int wordPos = c.position();
c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
sel.cursor = c;
ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
QList<QTextEdit::ExtraSelection> selections = ed->extraSelections();
QCOMPARE(selections.count(), 1);
QCOMPARE(selections.at(0).cursor.position(), endPos);
QCOMPARE(selections.at(0).cursor.anchor(), wordPos);
}
void tst_QPlainTextEdit::adjustScrollbars()
{
// For some reason ff is defined to be << on Mac Panther / gcc 3.3
#undef ff
QFont ff(ed->font());
ff.setFamily("Tahoma");
ff.setPointSize(11);
ed->setFont(ff);
ed->setMinimumSize(140, 100);
ed->setMaximumSize(140, 100);
ed->show();
QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
ed->setPlainText(txt + txt + txt + txt);
QVERIFY(ed->verticalScrollBar()->maximum() > 0);
ed->moveCursor(QTextCursor::End);
int oldMaximum = ed->verticalScrollBar()->maximum();
QTextCursor cursor = ed->textCursor();
cursor.insertText(QLatin1String("\n"));
cursor.deletePreviousChar();
QCOMPARE(ed->verticalScrollBar()->maximum(), oldMaximum);
}
class SignalReceiver : public QObject
{
Q_OBJECT
public:
SignalReceiver() : received(0) {}
int receivedSignals() const { return received; }
QTextCharFormat charFormat() const { return format; }
public slots:
void charFormatChanged(const QTextCharFormat &tcf) { ++received; format = tcf; }
private:
QTextCharFormat format;
int received;
};
void tst_QPlainTextEdit::textObscuredByScrollbars()
{
ed->textCursor().insertText(
"ab cab cab c abca kjsdf lka sjd lfk jsal df j kasdf abc ab abc "
"a b c d e f g h i j k l m n o p q r s t u v w x y z "
"abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
"ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
"abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
"ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
"abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
"ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
"abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
"ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
"abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc "
"ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab"
);
ed->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ed->show();
QSize documentSize = ed->document()->documentLayout()->documentSize().toSize();
QSize viewportSize = ed->viewport()->size();
QVERIFY(documentSize.width() <= viewportSize.width());
}
void tst_QPlainTextEdit::setTextPreservesUndoRedoEnabled()
{
QVERIFY(ed->isUndoRedoEnabled());
ed->setPlainText("Test");
QVERIFY(ed->isUndoRedoEnabled());
ed->setUndoRedoEnabled(false);
QVERIFY(!ed->isUndoRedoEnabled());
ed->setPlainText("Test2");
QVERIFY(!ed->isUndoRedoEnabled());
ed->setPlainText("<p>hello");
QVERIFY(!ed->isUndoRedoEnabled());
}
void tst_QPlainTextEdit::wordWrapProperty()
{
{
QPlainTextEdit edit;
QTextDocument *doc = new QTextDocument(&edit);
doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
edit.setDocument(doc);
edit.setWordWrapMode(QTextOption::NoWrap);
QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
}
{
QPlainTextEdit edit;
QTextDocument *doc = new QTextDocument(&edit);
doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
edit.setWordWrapMode(QTextOption::NoWrap);
edit.setDocument(doc);
QVERIFY(doc->defaultTextOption().wrapMode() == QTextOption::NoWrap);
}
}
void tst_QPlainTextEdit::lineWrapProperty()
{
QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
QVERIFY(ed->lineWrapMode() == QPlainTextEdit::WidgetWidth);
ed->setLineWrapMode(QPlainTextEdit::NoWrap);
QVERIFY(ed->lineWrapMode() == QPlainTextEdit::NoWrap);
QVERIFY(ed->wordWrapMode() == QTextOption::WrapAtWordBoundaryOrAnywhere);
QVERIFY(ed->document()->defaultTextOption().wrapMode() == QTextOption::NoWrap);
}
void tst_QPlainTextEdit::selectionChanged()
{
ed->setPlainText("Hello World");
ed->moveCursor(QTextCursor::Start);
QSignalSpy selectionChangedSpy(ed, SIGNAL(selectionChanged()));
QTest::keyClick(ed, Qt::Key_Right);
QCOMPARE(ed->textCursor().position(), 1);
QCOMPARE(selectionChangedSpy.count(), 0);
QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
QCOMPARE(ed->textCursor().position(), 2);
QCOMPARE(selectionChangedSpy.count(), 1);
QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
QCOMPARE(ed->textCursor().position(), 3);
QCOMPARE(selectionChangedSpy.count(), 2);
QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier);
QCOMPARE(ed->textCursor().position(), 4);
QCOMPARE(selectionChangedSpy.count(), 3);
QTest::keyClick(ed, Qt::Key_Right);
QCOMPARE(ed->textCursor().position(), 5);
QCOMPARE(selectionChangedSpy.count(), 4);
QTest::keyClick(ed, Qt::Key_Right);
QCOMPARE(ed->textCursor().position(), 6);
QCOMPARE(selectionChangedSpy.count(), 4);
}
void tst_QPlainTextEdit::blockCountChanged()
{
QSignalSpy blockCountCpangedSpy(ed, SIGNAL(blockCountChanged(int)));
ed->setPlainText("Hello");
QCOMPARE(blockCountCpangedSpy.count(), 0);
ed->setPlainText("Hello World");
QCOMPARE(blockCountCpangedSpy.count(), 0);
ed->setPlainText("Hello \n World \n this \n has \n more \n blocks \n than \n just \n one");
QCOMPARE(blockCountCpangedSpy.count(), 1);
ed->setPlainText("One");
QCOMPARE(blockCountCpangedSpy.count(), 2);
ed->setPlainText("One \n Two");
QCOMPARE(blockCountCpangedSpy.count(), 3);
ed->setPlainText("Three \n Four");
QCOMPARE(blockCountCpangedSpy.count(), 3);
}
QTEST_MAIN(tst_QPlainTextEdit)
#include "tst_qplaintextedit.moc"