summaryrefslogtreecommitdiffstats
path: root/tests/auto/qplaintextedit/tst_qplaintextedit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qplaintextedit/tst_qplaintextedit.cpp')
-rw-r--r--tests/auto/qplaintextedit/tst_qplaintextedit.cpp1500
1 files changed, 1500 insertions, 0 deletions
diff --git a/tests/auto/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/qplaintextedit/tst_qplaintextedit.cpp
new file mode 100644
index 0000000..6835c21
--- /dev/null
+++ b/tests/auto/qplaintextedit/tst_qplaintextedit.cpp
@@ -0,0 +1,1500 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <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)
+ // 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);
+ ed->resize(1, 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);
+
+ 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
+
+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"