/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #define protected public #include #undef protected #include #include #include #include #include #include #include "../qtextdocument/common.h" class tst_QTextPieceTable : public QObject { Q_OBJECT public: tst_QTextPieceTable(); public slots: void init(); void cleanup(); private slots: void insertion1(); void insertion2(); void insertion3(); void insertion4(); void insertion5(); void removal1(); void removal2(); void removal3(); void removal4(); void undoRedo1(); void undoRedo2(); void undoRedo3(); void undoRedo4(); void undoRedo5(); void undoRedo6(); void undoRedo7(); void undoRedo8(); void undoRedo9(); void undoRedo10(); void undoRedo11(); void checkDocumentChanged(); void checkDocumentChanged2(); void setBlockFormat(); void blockInsertion(); void blockInsertion2(); void blockRemoval1(); void blockRemoval2(); void blockRemoval3(); void blockRemoval4(); void blockRemoval5(); void checkBlockSeparation(); void checkFrames1(); void removeFrameDirect(); void removeWithChildFrame(); void clearWithFrames(); private: QTextDocument *doc; QTextDocumentPrivate *table; int blockFormatIndex; int charFormatIndex; }; tst_QTextPieceTable::tst_QTextPieceTable() { doc = 0; table = 0; } void tst_QTextPieceTable::init() { doc = new QTextDocument(0); table = doc->docHandle(); blockFormatIndex = table->formatCollection()->indexForFormat(QTextBlockFormat()); charFormatIndex = table->formatCollection()->indexForFormat(QTextCharFormat()); } void tst_QTextPieceTable::cleanup() { delete doc; doc = 0; } void tst_QTextPieceTable::insertion1() { table->insert(0, "aacc", charFormatIndex); QCOMPARE(table->plainText(), QString("aacc")); table->insert(2, "bb", charFormatIndex); QCOMPARE(table->plainText(), QString("aabbcc")); table->insert(1, "1", charFormatIndex); QCOMPARE(table->plainText(), QString("a1abbcc")); table->insert(6, "d", charFormatIndex); QCOMPARE(table->plainText(), QString("a1abbcdc")); table->insert(8, "z", charFormatIndex); QCOMPARE(table->plainText(), QString("a1abbcdcz")); } void tst_QTextPieceTable::insertion2() { table->insert(0, "bb", charFormatIndex); QCOMPARE(table->plainText(), QString("bb")); } void tst_QTextPieceTable::insertion3() { QString compare; for (int i = 0; i < 20000; ++i) { int pos = QRandomGenerator::global()->bounded(i+1); QChar c((unsigned short)(i & 0xff) + 1); QString str; str += c; table->insert(pos, str, charFormatIndex); compare.insert(pos, str); } QCOMPARE(table->plainText(), compare); } void tst_QTextPieceTable::insertion4() { QString compare; for (int i = 0; i < 20000; ++i) { int pos = QRandomGenerator::global()->generate() % (i+1); QChar c((unsigned short)((i % 26) + (i>25?'A':'a'))); QString str; str += c; str += c; table->insert(pos, str, charFormatIndex); compare.insert(pos, str); // if (table->text() != compare) { // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1()); // exit(12); // } } QCOMPARE(table->plainText(), compare); } void tst_QTextPieceTable::insertion5() { QString compare; for (int i = 0; i < 20000; ++i) { int pos = QRandomGenerator::global()->generate() % (i+1); QChar c((unsigned short)((i % 26) + (i>25?'A':'a'))); QString str; str += c; str += c; if (c == 'a') { table->insertBlock(pos, blockFormatIndex, charFormatIndex); str = QChar(QChar::ParagraphSeparator); } else { table->insert(pos, str, charFormatIndex); } compare.insert(pos, str); } QCOMPARE(table->plainText(), compare); for (QTextBlock it = table->blocksBegin(); it != table->blocksEnd(); it = it.next()) { QTextDocumentPrivate::FragmentIterator fit = table->find(it.position()); QCOMPARE(fit.position(), it.position()); } } void tst_QTextPieceTable::removal1() { table->insert(0, "abbccc", charFormatIndex); QCOMPARE(table->plainText(), QString("abbccc")); table->remove(1, 2); QCOMPARE(table->plainText(), QString("accc")); table->insert(1, "1", charFormatIndex); QCOMPARE(table->plainText(), QString("a1ccc")); table->remove(4, 1); QCOMPARE(table->plainText(), QString("a1cc")); table->insert(4, "z", charFormatIndex); QCOMPARE(table->plainText(), QString("a1ccz")); } void tst_QTextPieceTable::removal2() { table->insert(0, "bb", charFormatIndex); QCOMPARE(table->plainText(), QString("bb")); table->remove(0, 2); QCOMPARE(table->plainText(), QString("")); table->insertBlock(0, blockFormatIndex, charFormatIndex); QCOMPARE(table->plainText(), QString(QChar(QChar::ParagraphSeparator))); table->remove(0, 1); QCOMPARE(table->plainText(), QString("")); table->insert(0, "bb", charFormatIndex); QCOMPARE(table->plainText(), QString("bb")); table->insertBlock(1, blockFormatIndex, charFormatIndex); QCOMPARE(table->plainText(), QString("b") + QString(QChar(QChar::ParagraphSeparator)) + QString("b")); table->remove(1, 1); QCOMPARE(table->plainText(), QString("bb")); } void tst_QTextPieceTable::removal3() { QString compare; int l = 0; for (int i = 0; i < 20000; ++i) { bool remove = l && (QRandomGenerator::global()->bounded(2)); int pos = QRandomGenerator::global()->bounded(remove ? l : (l+1)); QChar c((unsigned short)((i % 26) + (i>25?'A':'a'))); QString str; str += c; str += c; if (remove && pos < table->length()) { compare.remove(pos, 1); table->remove(pos, 1); } else { compare.insert(pos, str); table->insert(pos, str, charFormatIndex); } l += remove ? -1 : 2; // if (table->text() != compare) { // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->text().latin1()); // exit(12); // } } QCOMPARE(table->plainText(), compare); } void tst_QTextPieceTable::removal4() { QString compare; int l = 0; for (int i = 0; i < 20000; ++i) { bool remove = l && (QRandomGenerator::global()->bounded(2)); int pos = (l > 1) ? QRandomGenerator::global()->bounded(remove ? l-1 : l) : 0; QChar c((unsigned short)((i % 26) + (i>25?'A':'a'))); QString str; if (c != 'a') { str += c; str += c; } else { str = QChar(QChar::ParagraphSeparator); } if (remove && pos < table->length() - 1) { compare.remove(pos, 1); table->remove(pos, 1); } else { if (str[0] == QChar(QChar::ParagraphSeparator)) table->insertBlock(pos, blockFormatIndex, charFormatIndex); else table->insert(pos, str, charFormatIndex); compare.insert(pos, str); } l += remove ? -1 : 2; // if (table->plainText() != compare) { // qDebug("compare failed: i=%d (current char=%c) insert at %d\nexpected '%s'\ngot '%s'", i, (i % 26) + (i>25?'A':'a'), pos, compare.latin1(), table->plainText().latin1()); // exit(12); // } } QCOMPARE(table->plainText(), compare); } void tst_QTextPieceTable::undoRedo1() { table->insert(0, "01234567", charFormatIndex); table->insert(0, "a", charFormatIndex); table->insert(1, "b", charFormatIndex); QCOMPARE(table->plainText(), QString("ab01234567")); table->undo(); QCOMPARE(table->plainText(), QString("01234567")); table->redo(); QCOMPARE(table->plainText(), QString("ab01234567")); table->undo(); table->insert(1, "c", charFormatIndex); QCOMPARE(table->plainText(), QString("0c1234567")); table->undo(); QCOMPARE(table->plainText(), QString("01234567")); table->undo(); QVERIFY(table->plainText().isEmpty()); } void tst_QTextPieceTable::undoRedo2() { table->insert(0, "01", charFormatIndex); table->insert(1, "a", charFormatIndex); QCOMPARE(table->plainText(), QString("0a1")); table->undo(); QCOMPARE(table->plainText(), QString("01")); table->undo(); QCOMPARE(table->plainText(), QString("")); table->redo(); QCOMPARE(table->plainText(), QString("01")); table->redo(); QCOMPARE(table->plainText(), QString("0a1")); } void tst_QTextPieceTable::undoRedo3() { table->insert(0, "01", charFormatIndex); table->insert(2, "ab", charFormatIndex); table->remove(2, 1); QCOMPARE(table->plainText(), QString("01b")); table->undo(); QCOMPARE(table->plainText(), QString("01ab")); table->undo(); QVERIFY(table->plainText().isEmpty()); table->redo(); QCOMPARE(table->plainText(), QString("01ab")); table->redo(); QCOMPARE(table->plainText(), QString("01b")); } void tst_QTextPieceTable::undoRedo4() { table->insert(0, "01", charFormatIndex); table->insert(0, "ab", charFormatIndex); table->remove(0, 1); QCOMPARE(table->plainText(), QString("b01")); table->undo(); QCOMPARE(table->plainText(), QString("ab01")); table->undo(); QCOMPARE(table->plainText(), QString("01")); table->undo(); QCOMPARE(table->plainText(), QString("")); table->redo(); QCOMPARE(table->plainText(), QString("01")); table->redo(); QCOMPARE(table->plainText(), QString("ab01")); table->redo(); QCOMPARE(table->plainText(), QString("b01")); } void tst_QTextPieceTable::undoRedo5() { table->beginEditBlock(); table->insert(0, "01", charFormatIndex); table->remove(1, 1); table->endEditBlock(); QCOMPARE(table->plainText(), QString("0")); table->undo(); QCOMPARE(table->plainText(), QString("")); } void tst_QTextPieceTable::undoRedo6() { // this is essentially a test for the undoStack[undoPosition - 1].block = false in PieceTable::endUndoBlock() QTextDocument doc; QTextCursor cursor(&doc); cursor.insertText("Hello World"); cursor.insertBlock(); cursor.insertText("Hello World2"); cursor.movePosition(QTextCursor::Start); QTextBlockFormat bfmt; bfmt.setAlignment(Qt::AlignHCenter); cursor.setBlockFormat(bfmt); QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter); QTextCursor range = cursor; range.clearSelection(); range.movePosition(QTextCursor::Start); range.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); QTextCharFormat modifier; modifier.setFontItalic(true); range.mergeCharFormat(modifier); cursor.movePosition(QTextCursor::Start); QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter); doc.undo(); QCOMPARE(cursor.blockFormat().alignment(), Qt::AlignHCenter); } void tst_QTextPieceTable::undoRedo7() { table->insert(0, "a", charFormatIndex); table->insert(1, "b", charFormatIndex); QCOMPARE(table->plainText(), QString("ab")); table->undo(); QVERIFY(table->plainText().isEmpty()); } void tst_QTextPieceTable::undoRedo8() { table->insert(0, "a", charFormatIndex); table->insert(1, "b", charFormatIndex); QCOMPARE(table->plainText(), QString("ab")); table->remove(0, 1); table->remove(0, 1); QVERIFY(table->plainText().isEmpty()); table->undo(); QCOMPARE(table->plainText(), QString("ab")); } void tst_QTextPieceTable::undoRedo9() { table->insert(0, "a", charFormatIndex); table->insert(1, "b", charFormatIndex); QCOMPARE(table->plainText(), QString("ab")); table->remove(1, 1); table->remove(0, 1); QVERIFY(table->plainText().isEmpty()); table->undo(); QCOMPARE(table->plainText(), QString("ab")); } void tst_QTextPieceTable::undoRedo10() { // testcase for the beginUndoBlock/endUndoBlock calls being surrounded by an if (undoEnabled) QTextCharFormat cf; cf.setForeground(Qt::blue); int cfIdx = table->formatCollection()->indexForFormat(cf); QTextBlockFormat f; int idx = table->formatCollection()->indexForFormat(f); table->insert(0, "a", cfIdx); table->insertBlock(1, idx, cfIdx); table->insert(1, "b", cfIdx); cf.setForeground(Qt::red); int newCfIdx = table->formatCollection()->indexForFormat(cf); table->setCharFormat(0, 3, cf, QTextDocumentPrivate::MergeFormat); QCOMPARE(table->find(0).value()->format, newCfIdx); table->undo(); QCOMPARE(table->find(0).value()->format, cfIdx); } void tst_QTextPieceTable::undoRedo11() { const int loops = 20; QString compare; int l = 0; for (int i = 0; i < loops; ++i) { bool remove = l && (QRandomGenerator::global()->bounded(2)); int pos = (l > 1) ? QRandomGenerator::global()->bounded(remove ? l-1 : l) : 0; QChar c((unsigned short)((i % 26) + (i>25?'A':'a'))); QString str; str += c; str += c; if (remove) { compare.remove(pos, 1); table->remove(pos, 1); } else { compare.insert(pos, str); table->insert(pos, str, charFormatIndex); } l += remove ? -1 : 2; } QCOMPARE(table->plainText(), compare); for (int i = 0; i < loops; ++i) table->undo(); QCOMPARE(table->plainText(), QString("")); for (int i = 0; i < loops; ++i) table->redo(); QCOMPARE(table->plainText(), compare); } void tst_QTextPieceTable::checkDocumentChanged() { table->enableUndoRedo(false); QTestDocumentLayout *layout = new QTestDocumentLayout(doc); doc->setDocumentLayout(layout); // single insert layout->expect(0, 0, 15); table->insert(0, "012345678901234", charFormatIndex); QVERIFY(!layout->error); // single remove layout->expect(0, 5, 0); table->remove(0, 5); QVERIFY(!layout->error); // symmetric insert/remove layout->expect(0, 0, 0); table->beginEditBlock(); table->insert(0, "01234", charFormatIndex); table->remove(0, 5); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 5, 5); table->beginEditBlock(); table->remove(0, 5); table->insert(0, "01234", charFormatIndex); table->endEditBlock(); QVERIFY(!layout->error); // replace layout->expect(0, 3, 5); table->beginEditBlock(); table->remove(0, 3); table->insert(0, "01234", charFormatIndex); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 0, 2); table->beginEditBlock(); table->insert(0, "01234", charFormatIndex); table->remove(0, 3); table->endEditBlock(); QVERIFY(!layout->error); // insert + remove inside insert block layout->expect(0, 0, 2); table->beginEditBlock(); table->insert(0, "01234", charFormatIndex); table->remove(1, 3); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 0, 2); table->beginEditBlock(); table->insert(0, "01234", charFormatIndex); table->remove(2, 3); table->endEditBlock(); QVERIFY(!layout->error); // insert + remove partly outside layout->expect(0, 1, 0); table->beginEditBlock(); table->insert(1, "0", charFormatIndex); table->remove(0, 2); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 1, 1); table->beginEditBlock(); table->insert(1, "01", charFormatIndex); table->remove(0, 2); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 1, 2); table->beginEditBlock(); table->insert(1, "012", charFormatIndex); table->remove(0, 2); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(1, 1, 0); table->beginEditBlock(); table->insert(1, "0", charFormatIndex); table->remove(1, 2); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(1, 1, 1); table->beginEditBlock(); table->insert(1, "01", charFormatIndex); table->remove(2, 2); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(1, 1, 2); table->beginEditBlock(); table->insert(1, "012", charFormatIndex); table->remove(3, 2); table->endEditBlock(); QVERIFY(!layout->error); // insert + remove non overlapping layout->expect(0, 1, 1); table->beginEditBlock(); table->insert(1, "0", charFormatIndex); table->remove(0, 1); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 2, 2); table->beginEditBlock(); table->insert(2, "1", charFormatIndex); table->remove(0, 1); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 2, 2); table->beginEditBlock(); table->remove(0, 1); table->insert(1, "0", charFormatIndex); table->endEditBlock(); QVERIFY(!layout->error); layout->expect(0, 3, 3); table->beginEditBlock(); table->remove(0, 1); table->insert(2, "1", charFormatIndex); table->endEditBlock(); layout->expect(0, 3, 3); QTextCharFormat fmt; fmt.setForeground(Qt::blue); table->beginEditBlock(); table->setCharFormat(0, 1, fmt); table->setCharFormat(2, 1, fmt); table->endEditBlock(); QVERIFY(!layout->error); } void tst_QTextPieceTable::checkDocumentChanged2() { QTestDocumentLayout *layout = new QTestDocumentLayout(doc); doc->setDocumentLayout(layout); QTextCharFormat fmt; fmt.setForeground(Qt::blue); int anotherCharFormatIndex = table->formatCollection()->indexForFormat(fmt); layout->expect(0, 0, 12); table->beginEditBlock(); table->insert(0, "0123", charFormatIndex); table->insert(4, "4567", anotherCharFormatIndex); table->insert(8, "8901", charFormatIndex); table->endEditBlock(); QVERIFY(!layout->error); fmt.setFontItalic(true); layout->expect(1, 10, 10); table->beginEditBlock(); table->setCharFormat(8, 3, fmt); table->setCharFormat(4, 4, fmt); table->setCharFormat(1, 3, fmt); table->endEditBlock(); QVERIFY(!layout->error); } void tst_QTextPieceTable::setBlockFormat() { QTextBlockFormat bfmt; int index = table->formatCollection()->indexForFormat(bfmt); table->insertBlock(0, index, charFormatIndex); table->insertBlock(0, index, charFormatIndex); table->insertBlock(0, index, charFormatIndex); QTextBlockFormat newbfmt = bfmt; newbfmt.setAlignment(Qt::AlignRight); index = table->formatCollection()->indexForFormat(bfmt); QTextBlock b = table->blocksFind(1); table->setBlockFormat(b, b, newbfmt); QCOMPARE(table->blocksFind(0).blockFormat(), bfmt); QCOMPARE(table->blocksFind(1).blockFormat(), newbfmt); QCOMPARE(table->blocksFind(2).blockFormat(), bfmt); } void tst_QTextPieceTable::blockInsertion() { QTextBlockFormat fmt; fmt.setTopMargin(100); int idx = table->formatCollection()->indexForFormat(fmt); int charFormat = table->formatCollection()->indexForFormat(QTextCharFormat()); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); table->insertBlock(0, idx, charFormat); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).blockFormat(), fmt); table->undo(); QCOMPARE(table->blockMap().length(), 1); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); table->redo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).blockFormat(), fmt); } void tst_QTextPieceTable::blockInsertion2() { // caused evil failing assertion in fragmentmap int pos = 0; table->insertBlock(pos, blockFormatIndex, charFormatIndex); pos += 1; table->insert(pos, "a", charFormatIndex); pos += 1; pos -= 1; table->insertBlock(pos, blockFormatIndex, charFormatIndex); QCOMPARE(table->blocksFind(0).position(), 0); QCOMPARE(table->blocksFind(1).position(), 1); QCOMPARE(table->blocksFind(2).position(), 2); } /* Tests correct removal behaviour when deleting over block boundaries or complete blocks. */ void tst_QTextPieceTable::blockRemoval1() { QTextBlockFormat fmt1; fmt1.setTopMargin(100); QTextBlockFormat fmt2; fmt2.setAlignment(Qt::AlignRight); int idx1 = table->formatCollection()->indexForFormat(fmt1); int idx2 = table->formatCollection()->indexForFormat(fmt2); table->insert(0, "0123", charFormatIndex); table->insertBlock(4, idx1, charFormatIndex); table->insert(5, "5678", charFormatIndex); table->insertBlock(9, idx2, charFormatIndex); table->insert(10, "0123", charFormatIndex); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->beginEditBlock(); table->remove(5, 5); table->endEditBlock(); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt2); QCOMPARE(table->blocksFind(4).position(), 0); QCOMPARE(table->blocksFind(5).position(), 5); table->undo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->redo(); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt2); QCOMPARE(table->blocksFind(4).position(), 0); QCOMPARE(table->blocksFind(5).position(), 5); } void tst_QTextPieceTable::blockRemoval2() { QTextBlockFormat fmt1; fmt1.setTopMargin(100); QTextBlockFormat fmt2; fmt2.setAlignment(Qt::AlignRight); int idx1 = table->formatCollection()->indexForFormat(fmt1); int idx2 = table->formatCollection()->indexForFormat(fmt2); table->insert(0, "0123", charFormatIndex); table->insertBlock(4, idx1, charFormatIndex); table->insert(5, "5678", charFormatIndex); table->insertBlock(9, idx2, charFormatIndex); table->insert(10, "0123", charFormatIndex); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->remove(4, 1); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(6).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).position(), 0); QCOMPARE(table->blocksFind(6).position(), 0); table->undo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->redo(); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(6).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).position(), 0); QCOMPARE(table->blocksFind(6).position(), 0); } void tst_QTextPieceTable::blockRemoval3() { QTextBlockFormat fmt1; fmt1.setTopMargin(100); QTextBlockFormat fmt2; fmt2.setAlignment(Qt::AlignRight); int idx1 = table->formatCollection()->indexForFormat(fmt1); int idx2 = table->formatCollection()->indexForFormat(fmt2); table->insert(0, "0123", charFormatIndex); table->insertBlock(4, idx1, charFormatIndex); table->insert(5, "5678", charFormatIndex); table->insertBlock(9, idx2, charFormatIndex); table->insert(10, "0123", charFormatIndex); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->beginEditBlock(); table->remove(3, 4); table->endEditBlock(); QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); table->undo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->redo(); QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); } void tst_QTextPieceTable::blockRemoval4() { #if 0 QTextBlockFormat fmt1; fmt1.setTopMargin(100); QTextBlockFormat fmt2; fmt2.setAlignment(Qt::AlignRight); int idx1 = table->formatCollection()->indexForFormat(fmt1); int idx2 = table->formatCollection()->indexForFormat(fmt2); table->insert(0, "0123", charFormatIndex); table->insertBlock(4, idx1, charFormatIndex); table->insert(5, "5678", charFormatIndex); table->insertBlock(9, idx2, charFormatIndex); table->insert(10, "0123", charFormatIndex); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->remove(3, 7); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); table->undo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->redo(); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); QCOMPARE(table->blocksFind(1).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); #endif } void tst_QTextPieceTable::blockRemoval5() { QTextBlockFormat fmt1; fmt1.setTopMargin(100); QTextBlockFormat fmt2; fmt2.setAlignment(Qt::AlignRight); int idx1 = table->formatCollection()->indexForFormat(fmt1); int idx2 = table->formatCollection()->indexForFormat(fmt2); table->insert(0, "0123", charFormatIndex); table->insertBlock(4, idx1, charFormatIndex); table->insert(5, "5678", charFormatIndex); table->insertBlock(9, idx2, charFormatIndex); table->insert(10, "0123", charFormatIndex); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->beginEditBlock(); table->remove(3, 8); table->endEditBlock(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); table->undo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(4).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), fmt1); QCOMPARE(table->blocksFind(10).blockFormat(), fmt2); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(6).position(), 5); QCOMPARE(table->blocksFind(11).position(), 10); table->redo(); QCOMPARE(table->blocksFind(0).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(5).blockFormat(), QTextBlockFormat()); QCOMPARE(table->blocksFind(1).position(), 0); QCOMPARE(table->blocksFind(5).position(), 0); } void tst_QTextPieceTable::checkBlockSeparation() { table->insertBlock(0, blockFormatIndex, charFormatIndex); table->insertBlock(1, blockFormatIndex, charFormatIndex); QVERIFY(table->find(0) != table->find(1)); } void tst_QTextPieceTable::checkFrames1() { QTextFrameFormat ffmt; table->insert(0, "Hello", charFormatIndex); QPointer frame = table->insertFrame(1, 3, ffmt); QTextFrame *root = table->rootFrame(); QCOMPARE(root, frame->parentFrame()); QVERIFY(root); QVERIFY(!root->parentFrame()); QCOMPARE(root->childFrames().count(), 1); QVERIFY(frame->format() == ffmt); QCOMPARE(frame->firstPosition(), 2); QCOMPARE(frame->lastPosition(), 4); QPointer frame2 = table->insertFrame(2, 3, ffmt); QCOMPARE(root->childFrames().count(), 1); QCOMPARE(root->childFrames().at(0), frame.data()); QCOMPARE(frame->childFrames().count(), 1); QCOMPARE(frame2->childFrames().count(), 0); QCOMPARE(frame2->parentFrame(), frame.data()); QCOMPARE(frame2->firstPosition(), 3); QCOMPARE(frame2->lastPosition(), 4); QVERIFY(frame->format() == ffmt); QCOMPARE(frame->firstPosition(), 2); QCOMPARE(frame->lastPosition(), 6); table->removeFrame(frame); QCOMPARE(root->childFrames().count(), 1); QCOMPARE(root->childFrames().at(0), frame2.data()); QVERIFY(!frame); QCOMPARE(frame2->childFrames().count(), 0); QCOMPARE(frame2->parentFrame(), root); QCOMPARE(frame2->firstPosition(), 2); QCOMPARE(frame2->lastPosition(), 3); table->undo(); frame = table->frameAt(2); QCOMPARE(root->childFrames().count(), 1); QCOMPARE(root->childFrames().at(0), frame.data()); QCOMPARE(frame->childFrames().count(), 1); QCOMPARE(frame->childFrames().at(0), frame2.data()); QCOMPARE(frame2->childFrames().count(), 0); QCOMPARE(frame2->parentFrame(), frame.data()); QCOMPARE(frame2->firstPosition(), 3); QCOMPARE(frame2->lastPosition(), 4); QCOMPARE(frame->firstPosition(), 2); QCOMPARE(frame->lastPosition(), 6); table->undo(); QCOMPARE(root->childFrames().count(), 1); QCOMPARE(root->childFrames().at(0), frame.data()); QCOMPARE(frame->childFrames().count(), 0); QVERIFY(!frame2); QCOMPARE(frame->firstPosition(), 2); QCOMPARE(frame->lastPosition(), 4); } void tst_QTextPieceTable::removeFrameDirect() { QTextFrameFormat ffmt; table->insert(0, "Hello", charFormatIndex); QTextFrame *frame = table->insertFrame(1, 5, ffmt); QCOMPARE(frame->parentFrame(), table->rootFrame()); const int start = frame->firstPosition() - 1; const int end = frame->lastPosition(); const int length = end - start + 1; table->remove(start, length); } void tst_QTextPieceTable::removeWithChildFrame() { /* The piecetable layout is: ... 1 BeginningOfFrame(first frame) 2 text 3 BeginningOfFrame(second frame) 4 text 5 text 6 EndOfFrame(second frame) 7 text 8 text 9 EndOfFrame(first frame) ... The idea is to remove from [2] until [6], basically some trailing text and the second frame. In this case frameAt(2) != frameAt(6), so the assertion in remove() needed an adjustement. */ QTextFrameFormat ffmt; table->insert(0, "Hello World", charFormatIndex); QTextFrame *frame = table->insertFrame(1, 6, ffmt); QTextFrame *childFrame = table->insertFrame(3, 5, ffmt); Q_UNUSED(frame); Q_UNUSED(childFrame); // used to give a failing assertion table->remove(2, 5); QVERIFY(true); } void tst_QTextPieceTable::clearWithFrames() { /* The piecetable layout is: ... 1 BeginningOfFrame(first frame) 2 text 3 EndOfFrame(first frame) 4 BeginningOfFrame(second frame) 5 text 6 text 7 EndOfFrame(second frame) ... The idea is to remove from [1] until [7]. */ QTextFrameFormat ffmt; table->insert(0, "Hello World", charFormatIndex); QTextFrame *firstFrame = table->insertFrame(1, 2, ffmt); QTextFrame *secondFrame = table->insertFrame(4, 6, ffmt); const int start = firstFrame->firstPosition() - 1; const int end = secondFrame->lastPosition(); const int length = end - start + 1; // used to give a failing assertion table->remove(start, length); QVERIFY(true); } QTEST_MAIN(tst_QTextPieceTable) #include "tst_qtextpiecetable.moc"