diff --git a/libs/textlayout/tests/MockRootAreaProvider.cpp b/libs/textlayout/tests/MockRootAreaProvider.cpp index 8ed52040637..156bdb39349 100644 --- a/libs/textlayout/tests/MockRootAreaProvider.cpp +++ b/libs/textlayout/tests/MockRootAreaProvider.cpp @@ -1,74 +1,83 @@ /* This file is part of the KDE project * Copyright (C) 2011 C. Boemann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "MockRootAreaProvider.h" #include "KoTextLayoutRootArea.h" +#include + MockRootAreaProvider::MockRootAreaProvider() - : m_area(0), - m_suggestedRect(QRectF(100, 100, 200,1000)), - m_askedForMoreThenOneArea(false) + : maxPosition(0) + , m_suggestedRect(QRectF(100, 100, 200, 1000)) + , m_askedForMoreThenOneArea(false) { } -KoTextLayoutRootArea *MockRootAreaProvider::provide(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &, int requestedPosition, bool *isNewRootArea) +KoTextLayoutRootArea *MockRootAreaProvider::provide(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &constraint, int requestedPosition, bool *isNewRootArea) { - if(m_area == 0) { - m_area = new KoTextLayoutRootArea(documentLayout); - *isNewRootArea = true; - return m_area; + if (maxPosition > 0 && requestedPosition > maxPosition) { + qInfo()<<"To many area requests:"< 1); + *isNewRootArea = !m_areas.contains(requestedPosition); + if (!m_areas.contains(requestedPosition)) { + m_areas.insert(requestedPosition, new KoTextLayoutRootArea(documentLayout)); + qInfo()<<"New area provided:"< 0; - return requestedPosition == 0 ? m_area : 0; + return m_areas.value(requestedPosition); } void MockRootAreaProvider::doPostLayout(KoTextLayoutRootArea *rootArea, bool isNewRootArea) { Q_UNUSED(rootArea); Q_UNUSED(isNewRootArea); } void MockRootAreaProvider::updateAll() { } void MockRootAreaProvider::releaseAllAfter(KoTextLayoutRootArea *afterThis) { Q_UNUSED(afterThis); } -QRectF MockRootAreaProvider::suggestRect(KoTextLayoutRootArea *rootArea) +QRectF MockRootAreaProvider::suggestRect(KoTextLayoutRootArea */*rootArea*/) { - Q_UNUSED(rootArea); return m_suggestedRect; } void MockRootAreaProvider::setSuggestedRect(QRectF rect) { m_suggestedRect = rect; } QList MockRootAreaProvider::relevantObstructions(KoTextLayoutRootArea *rootArea) { Q_UNUSED(rootArea); QList obstructions; return obstructions; } + +KoTextLayoutRootArea *MockRootAreaProvider::area(int pos) const +{ + return m_areas.value(pos); +} diff --git a/libs/textlayout/tests/MockRootAreaProvider.h b/libs/textlayout/tests/MockRootAreaProvider.h index 1d00423730c..637ca2a7c68 100644 --- a/libs/textlayout/tests/MockRootAreaProvider.h +++ b/libs/textlayout/tests/MockRootAreaProvider.h @@ -1,47 +1,51 @@ /* This file is part of the KDE project * Copyright (C) 2011 C. Boemann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef MOCKROOTAREAPROVIDER_H #define MOCKROOTAREAPROVIDER_H #include "KoTextLayoutRootAreaProvider.h" #include +#include class MockRootAreaProvider : public KoTextLayoutRootAreaProvider { public: MockRootAreaProvider(); /// reimplemented virtual KoTextLayoutRootArea *provide(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &constraints, int requestedPosition, bool *isNewArea); virtual void releaseAllAfter(KoTextLayoutRootArea *afterThis); virtual void doPostLayout(KoTextLayoutRootArea *rootArea, bool isNewRootArea); virtual QRectF suggestRect(KoTextLayoutRootArea *rootArea); virtual QList relevantObstructions(KoTextLayoutRootArea *rootArea); virtual void updateAll(); void setSuggestedRect(QRectF rect); - KoTextLayoutRootArea *m_area; + KoTextLayoutRootArea *area(int pos = 0) const; + + int maxPosition; + QMap m_areas; QRectF m_suggestedRect; bool m_askedForMoreThenOneArea; }; #endif diff --git a/libs/textlayout/tests/TestDocumentLayout.cpp b/libs/textlayout/tests/TestDocumentLayout.cpp index 37d273de9f5..82fd51af29e 100644 --- a/libs/textlayout/tests/TestDocumentLayout.cpp +++ b/libs/textlayout/tests/TestDocumentLayout.cpp @@ -1,194 +1,194 @@ /* * This file is part of Calligra tests * * Copyright (C) 2006-2010 Thomas Zander * Copyright (C) 2009-2010 C. Boemann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "TestDocumentLayout.h" #include "MockRootAreaProvider.h" #include #include #include #include #include #include #include #include #include #include void TestDocumentLayout::initTestCase() { m_doc = 0; m_layout = 0; } void TestDocumentLayout::setupTest(const QString &initText) { m_doc = new QTextDocument; Q_ASSERT(m_doc); MockRootAreaProvider *provider = new MockRootAreaProvider(); Q_ASSERT(provider); KoTextDocument(m_doc).setInlineTextObjectManager(new KoInlineTextObjectManager); m_doc->setDefaultFont(QFont("Sans Serif", 12, QFont::Normal, false)); //do it manually since we do not load the appDefaultStyle m_styleManager = new KoStyleManager(0); KoTextDocument(m_doc).setStyleManager(m_styleManager); m_layout = new KoTextDocumentLayout(m_doc, provider); Q_ASSERT(m_layout); m_doc->setDocumentLayout(m_layout); if (!initText.isEmpty()) { QTextCursor cursor(m_doc); cursor.insertText(initText); KoParagraphStyle style; style.setStyleId(101); // needed to do manually since we don't use the stylemanager QTextBlock b2 = m_doc->begin(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } } void TestDocumentLayout::testHitTest() { // init a basic document with 3 parags. setupTest(); m_doc->setHtml("

lsdjflkdsjf lsdkjf lsdlflksejrl sdflsd flksjdf lksjrpdslfjfsdhtwkr[ivxxmvlwerponldsjf;dslflkjsorindfsn;epsdf

sldkfnwerpodsnf

sldkjfnpqwrdsf

"); QTextBlock block = m_doc->begin(); qreal offset = 50.0; qreal lineHeight = 0; int lines = 0, parag = 0; qreal paragOffets[3]; while (1) { if (!block.isValid()) break; paragOffets[parag++] = offset; QTextLayout *txtLayout = block.layout(); txtLayout->beginLayout(); while (1) { QTextLine line = txtLayout->createLine(); if (!line.isValid()) break; ++lines; line.setLineWidth(50); line.setPosition(QPointF(20, offset)); offset += 20; lineHeight = line.height(); } txtLayout->endLayout(); block = block.next(); } m_layout->layout(); MockRootAreaProvider *p = dynamic_cast(m_layout->provider()); - QVERIFY(p->m_area); + QVERIFY(p->area()); QCOMPARE(lines, 8); /* Following is device-/font-dependent and therefore can be different on other computers // outside text - QCOMPARE(p->m_area->hitTest(QPointF(0, 0), Qt::FuzzyHit).position, 0); - QCOMPARE(p->m_area->hitTest(QPointF(0, 0), Qt::ExactHit).position, -1); - QCOMPARE(p->m_area->hitTest(QPointF(19, 49), Qt::ExactHit).position, 51); - QCOMPARE(p->m_area->hitTest(QPointF(71, 0), Qt::ExactHit).position, -1); - QCOMPARE(p->m_area->hitTest(QPointF(71, 51), Qt::ExactHit).position, 62); + QCOMPARE(p->area()->hitTest(QPointF(0, 0), Qt::FuzzyHit).position, 0); + QCOMPARE(p->area()->hitTest(QPointF(0, 0), Qt::ExactHit).position, -1); + QCOMPARE(p->area()->hitTest(QPointF(19, 49), Qt::ExactHit).position, 51); + QCOMPARE(p->area()->hitTest(QPointF(71, 0), Qt::ExactHit).position, -1); + QCOMPARE(p->area()->hitTest(QPointF(71, 51), Qt::ExactHit).position, 62); // first char - QCOMPARE(p->m_area->hitTest(QPointF(20, 51), Qt::ExactHit).position, 52); - QCOMPARE(p->m_area->hitTest(QPointF(20, 50), Qt::ExactHit).position, 52); + QCOMPARE(p->area()->hitTest(QPointF(20, 51), Qt::ExactHit).position, 52); + QCOMPARE(p->area()->hitTest(QPointF(20, 50), Qt::ExactHit).position, 52); // below line 1 - //QCOMPARE(p->m_area->hitTest(QPointF(20, 51 + lineHeight), Qt::ExactHit).position, -1); - //QVERIFY(p->m_area->hitTest(QPointF(20, 51 + lineHeight), Qt::FuzzyHit).position > 0); // line 2 + //QCOMPARE(p->area()->hitTest(QPointF(20, 51 + lineHeight), Qt::ExactHit).position, -1); + //QVERIFY(p->area()->hitTest(QPointF(20, 51 + lineHeight), Qt::FuzzyHit).position > 0); // line 2 // parag2 - QCOMPARE(p->m_area->hitTest(QPointF(20, paragOffets[1]), Qt::ExactHit).position, 139); - QCOMPARE(p->m_area->hitTest(QPointF(20, paragOffets[1]), Qt::FuzzyHit).position, 139); - QVERIFY(p->m_area->hitTest(QPointF(20, paragOffets[1] + 20), Qt::FuzzyHit).position >= 139); + QCOMPARE(p->area()->hitTest(QPointF(20, paragOffets[1]), Qt::ExactHit).position, 139); + QCOMPARE(p->area()->hitTest(QPointF(20, paragOffets[1]), Qt::FuzzyHit).position, 139); + QVERIFY(p->area()->hitTest(QPointF(20, paragOffets[1] + 20), Qt::FuzzyHit).position >= 139); */ Q_UNUSED(lineHeight); // used in the above commented piece of code Q_UNUSED(paragOffets); // used in the above commented piece of code } void TestDocumentLayout::testRootAreaZeroWidth() { setupTest("a"); MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); provider->setSuggestedRect(QRectF(10., 10., 0., 200.)); m_layout->layout(); QVERIFY(!provider->m_askedForMoreThenOneArea); - QVERIFY(provider->m_area); - QVERIFY(!provider->m_area->isDirty()); - QVERIFY(!provider->m_area->virginPage()); - QVERIFY(provider->m_area->nextStartOfArea()); - QVERIFY(!provider->m_area->isStartingAt(provider->m_area->nextStartOfArea())); - QCOMPARE(provider->m_area->boundingRect().topLeft(), QPointF(10.,10.)); - //QCOMPARE(provider->m_area->boundingRect().height(), qreal(14.4)); - QCOMPARE(provider->m_area->referenceRect().topLeft(), QPointF(10.,10.)); - //QCOMPARE(provider->m_area->referenceRect().bottomLeft(), QPointF(0.,14.4)); + QVERIFY(provider->area()); + QVERIFY(!provider->area()->isDirty()); + QVERIFY(!provider->area()->virginPage()); + QVERIFY(provider->area()->nextStartOfArea()); + QVERIFY(!provider->area()->isStartingAt(provider->area()->nextStartOfArea())); + QCOMPARE(provider->area()->boundingRect().topLeft(), QPointF(10.,10.)); + //QCOMPARE(provider->area()->boundingRect().height(), qreal(14.4)); + QCOMPARE(provider->area()->referenceRect().topLeft(), QPointF(10.,10.)); + //QCOMPARE(provider->area()->referenceRect().bottomLeft(), QPointF(0.,14.4)); } void TestDocumentLayout::testRootAreaZeroHeight() { setupTest("a"); MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); provider->setSuggestedRect(QRectF(10., 10., 200.,0.)); m_layout->layout(); QVERIFY(!provider->m_askedForMoreThenOneArea); // we add the text anyways even if it does not match in height - QVERIFY(provider->m_area); - QVERIFY(!provider->m_area->isDirty()); - QVERIFY(!provider->m_area->virginPage()); // should not be virigin any longer cause we added text - QVERIFY(provider->m_area->nextStartOfArea()); - QVERIFY(!provider->m_area->isStartingAt(provider->m_area->nextStartOfArea())); // start- and end-iterator should not be equal cause we added text - QCOMPARE(provider->m_area->boundingRect(), QRectF(10.,10.,200.,0.)); - QCOMPARE(provider->m_area->referenceRect(), QRectF(10.,10.,200.,0.)); + QVERIFY(provider->area()); + QVERIFY(!provider->area()->isDirty()); + QVERIFY(!provider->area()->virginPage()); // should not be virigin any longer cause we added text + QVERIFY(provider->area()->nextStartOfArea()); + QVERIFY(!provider->area()->isStartingAt(provider->area()->nextStartOfArea())); // start- and end-iterator should not be equal cause we added text + QCOMPARE(provider->area()->boundingRect(), QRectF(10.,10.,200.,0.)); + QCOMPARE(provider->area()->referenceRect(), QRectF(10.,10.,200.,0.)); } void TestDocumentLayout::testRootAreaZeroWidthAndHeight() { setupTest("a"); MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); provider->setSuggestedRect(QRectF(10., 10., 0., 0.)); m_layout->layout(); QVERIFY(!provider->m_askedForMoreThenOneArea); - QVERIFY(provider->m_area); - QVERIFY(!provider->m_area->isDirty()); - QVERIFY(!provider->m_area->virginPage()); - QVERIFY(provider->m_area->nextStartOfArea()); - QVERIFY(!provider->m_area->isStartingAt(provider->m_area->nextStartOfArea())); - QCOMPARE(provider->m_area->boundingRect().topLeft(), QPointF(10.,10.)); - QCOMPARE(provider->m_area->boundingRect().height(), qreal(0.)); - //QCOMPARE(provider->m_area->boundingRect().width(), qreal(6.67188)); - QCOMPARE(provider->m_area->referenceRect(), QRectF(10.,10.,0.,0.)); + QVERIFY(provider->area()); + QVERIFY(!provider->area()->isDirty()); + QVERIFY(!provider->area()->virginPage()); + QVERIFY(provider->area()->nextStartOfArea()); + QVERIFY(!provider->area()->isStartingAt(provider->area()->nextStartOfArea())); + QCOMPARE(provider->area()->boundingRect().topLeft(), QPointF(10.,10.)); + QCOMPARE(provider->area()->boundingRect().height(), qreal(0.)); + //QCOMPARE(provider->area()->boundingRect().width(), qreal(6.67188)); + QCOMPARE(provider->area()->referenceRect(), QRectF(10.,10.,0.,0.)); } QTEST_MAIN(TestDocumentLayout) diff --git a/libs/textlayout/tests/TestTableLayout.cpp b/libs/textlayout/tests/TestTableLayout.cpp index 51950f01d82..ce132161742 100644 --- a/libs/textlayout/tests/TestTableLayout.cpp +++ b/libs/textlayout/tests/TestTableLayout.cpp @@ -1,372 +1,620 @@ /* * This file is part of Calligra tests * * Copyright (C) 2006-2010 Thomas Zander * Copyright (C) 2011 C. Boemann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "TestTableLayout.h" #include "MockRootAreaProvider.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include #include +#include +#include #include #include #include #include #define FRAME_SPACING 10.0 void TestTableLayout::initTestCase() { m_doc = 0; m_layout = 0; m_loremIpsum = QString("Lorem ipsum dolor sit amet, XgXgectetuer adiXiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi."); } void TestTableLayout::cleanupTestCase() { delete m_doc; + m_doc = 0; } QTextCursor TestTableLayout::setupTest() { delete m_doc; m_doc = new QTextDocument; Q_ASSERT(m_doc); MockRootAreaProvider *provider = new MockRootAreaProvider(); Q_ASSERT(provider); KoTextDocument(m_doc).setInlineTextObjectManager(new KoInlineTextObjectManager); m_doc->setDefaultFont(QFont("Sans Serif", 12, QFont::Normal, false)); //do it manually since we do not load the appDefaultStyle m_styleManager = new KoStyleManager(0); KoTextDocument(m_doc).setStyleManager(m_styleManager); m_layout = new KoTextDocumentLayout(m_doc, provider); Q_ASSERT(m_layout); m_doc->setDocumentLayout(m_layout); m_block = m_doc->begin(); QTextCursor cursor(m_doc); return cursor; } void TestTableLayout::setupTest(const QString &mergedText, const QString &topRightText, const QString &midRightText, const QString &bottomLeftText, const QString &bottomMidText, const QString &bottomRightText, KoTableStyle* tableStyle) { QTextCursor cursor = setupTest(); KoParagraphStyle style; style.setStyleId(101); // needed to do manually since we don't use the stylemanager style.applyStyle(m_block); QTextTableFormat tableFormat; if (tableStyle) tableStyle->applyStyle(tableFormat); m_table = cursor.insertTable(3,3,tableFormat); m_table->mergeCells(0,0,2,2); if (mergedText.length() > 0) { m_table->cellAt(0,0).firstCursorPosition().insertText(mergedText); QTextBlock b2 = m_table->cellAt(0,0).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } if (topRightText.length() > 0) { m_table->cellAt(0,2).firstCursorPosition().insertText(topRightText); QTextBlock b2 = m_table->cellAt(0,2).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } if (midRightText.length() > 0) { m_table->cellAt(1,2).firstCursorPosition().insertText(midRightText); QTextBlock b2 = m_table->cellAt(1,2).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } if (bottomLeftText.length() > 0) { m_table->cellAt(2,0).firstCursorPosition().insertText(bottomLeftText); QTextBlock b2 = m_table->cellAt(2,0).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } if (bottomMidText.length() > 0) { m_table->cellAt(2,1).firstCursorPosition().insertText(bottomMidText); QTextBlock b2 = m_table->cellAt(2,1).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } if (bottomRightText.length() > 0) { m_table->cellAt(2,2).firstCursorPosition().insertText(bottomRightText); QTextBlock b2 = m_table->cellAt(2,2).firstCursorPosition().block(); while (b2.isValid()) { style.applyStyle(b2); b2 = b2.next(); } } } QTextBlock TestTableLayout::mergedCellBlock() const { return m_table->cellAt(0,0).firstCursorPosition().block(); } QTextBlock TestTableLayout::topRightCellBlock() const { return m_table->cellAt(0,2).firstCursorPosition().block(); } QTextBlock TestTableLayout::midRightCellBlock() const { return m_table->cellAt(1,2).firstCursorPosition().block(); } QTextBlock TestTableLayout::bottomLeftCellBlock() const { return m_table->cellAt(2,0).firstCursorPosition().block(); } QTextBlock TestTableLayout::bottomMidCellBlock() const { return m_table->cellAt(2,1).firstCursorPosition().block(); } QTextBlock TestTableLayout::bottomRightCellBlock() const { return m_table->cellAt(2,2).firstCursorPosition().block(); } void TestTableLayout::testSetupTest() { setupTest("m","02","12","20","21","22"); m_layout->layout(); QCOMPARE(mergedCellBlock().text(), QString("m")); QCOMPARE(topRightCellBlock().text(), QString("02")); QCOMPARE(midRightCellBlock().text(), QString("12")); QCOMPARE(bottomLeftCellBlock().text(), QString("20")); QCOMPARE(bottomMidCellBlock().text(), QString("21")); QCOMPARE(bottomRightCellBlock().text(), QString("22")); } void TestTableLayout::testMergedCells() { QTextCursor cursor = setupTest(); m_table = cursor.insertTable(3, 5); m_table->mergeCells(0,0,2,2); m_table->mergeCells(0,2,3,1); m_table->mergeCells(0,3,3,1); m_table->mergeCells(0,4,3,1); m_table->mergeCells(2,0,1,1); m_table->mergeCells(2,1,1,1); m_layout->layout(); - QVERIFY(!dynamic_cast(m_layout->provider())->m_askedForMoreThenOneArea); + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(!provider->m_askedForMoreThenOneArea); + // check if table is layed out + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(m_table == p.table, "m_table not found in area 0"); } void TestTableLayout::testColumnWidthUndefined() { setupTest("","","","","",""); m_layout->layout(); QCOMPARE(m_table->columns(), 3); QCOMPARE(m_table->rows(), 3); QVERIFY(qAbs(m_block.layout()->lineAt(0).width() - 200.0) < ROUNDING); QTextLayout *lay = bottomLeftCellBlock().layout(); QVERIFY(lay); QCOMPARE(lay->lineCount(), 1); QVERIFY(qAbs(lay->lineAt(0).width() - 200.0/3) < ROUNDING); lay = bottomMidCellBlock().layout(); QVERIFY(lay); QCOMPARE(lay->lineCount(), 1); QVERIFY(qAbs(lay->lineAt(0).width() - 200.0/3) < ROUNDING); lay = bottomRightCellBlock().layout(); QVERIFY(lay); QCOMPARE(lay->lineCount(), 1); QVERIFY(qAbs(lay->lineAt(0).width() - 200.0/3) < ROUNDING); } void TestTableLayout::testColumnWidthFixed() { KoTableStyle *tableStyle = new KoTableStyle; tableStyle->setWidth(QTextLength(QTextLength::FixedLength, 150.0)); setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text", tableStyle); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableColumnStyle column1style; column1style.setColumnWidth(2.3); styleManager.setColumnStyle(0, column1style); KoTableColumnStyle column2style; column2style.setColumnWidth(122.5); styleManager.setColumnStyle(1, column2style); KoTableColumnStyle column3style; column3style.setColumnWidth(362.9); styleManager.setColumnStyle(2, column3style); m_layout->layout(); QVERIFY(qAbs(QTextCursor(m_table->parentFrame()).block().layout()->lineAt(0).width() - 200.0) < ROUNDING); // table should grow to 200 QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).width() - 124.8) < ROUNDING); QVERIFY(qAbs(topRightCellBlock().layout()->lineAt(0).width() - 362.9) < ROUNDING); QVERIFY(qAbs(bottomLeftCellBlock().layout()->lineAt(0).width() - 2.3) < ROUNDING); QVERIFY(qAbs(bottomMidCellBlock().layout()->lineAt(0).width() - 122.5) < ROUNDING); QVERIFY(qAbs(bottomRightCellBlock().layout()->lineAt(0).width() - 362.9) < ROUNDING); } void TestTableLayout::testColumnWidthFixedZero() { setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text"); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableColumnStyle column1style; column1style.setColumnWidth(0.0); styleManager.setColumnStyle(0, column1style); KoTableColumnStyle column2style; column2style.setColumnWidth(120.5); styleManager.setColumnStyle(1, column2style); KoTableColumnStyle column3style; column3style.setColumnWidth(0.1); styleManager.setColumnStyle(2, column3style); m_layout->layout(); QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).width() - 120.5) < ROUNDING); QVERIFY(qAbs(topRightCellBlock().layout()->lineAt(0).width() - 0.1) < ROUNDING); //FIXME QVERIFY(qAbs(bottomLeftCellBlock().layout()->lineAt(0).width() - 0.0) < ROUNDING); QVERIFY(qAbs(bottomMidCellBlock().layout()->lineAt(0).width() - 120.5) < ROUNDING); //FIXME QVERIFY(qAbs(bottomRightCellBlock().layout()->lineAt(0).width() - 0.0) < ROUNDING); } void TestTableLayout::testColumnWidthFixedShrink() { KoTableStyle *tableStyle = new KoTableStyle; //tableStyle->setWidth(QTextLength(QTextLength::FixedLength, 200.0)); // no table-width defined setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text", tableStyle); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableColumnStyle column1style; column1style.setColumnWidth(2.3); styleManager.setColumnStyle(0, column1style); KoTableColumnStyle column2style; column2style.setColumnWidth(122.5); styleManager.setColumnStyle(1, column2style); KoTableColumnStyle column3style; column3style.setColumnWidth(362.9); styleManager.setColumnStyle(2, column3style); m_layout->layout(); QVERIFY(qAbs(QTextCursor(m_table->parentFrame()).block().layout()->lineAt(0).width() - 200.0) < ROUNDING); // table should grow to 200 QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).width() - 26.5938) < ROUNDING); QVERIFY(qAbs(topRightCellBlock().layout()->lineAt(0).width() - 267) < ROUNDING); QVERIFY(qAbs(bottomMidCellBlock().layout()->lineAt(0).width() - 26.5938) < ROUNDING); QVERIFY(qAbs(bottomRightCellBlock().layout()->lineAt(0).width() - 267) < ROUNDING); } void TestTableLayout::testColumnWidthRelative() { setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text"); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableColumnStyle column1style; column1style.setRelativeColumnWidth(0.2); styleManager.setColumnStyle(0, column1style); KoTableColumnStyle column2style; column2style.setRelativeColumnWidth(0.5); styleManager.setColumnStyle(1, column2style); KoTableColumnStyle column3style; column3style.setRelativeColumnWidth(0.1); styleManager.setColumnStyle(2, column3style); m_layout->layout(); QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).width() - 200.0*0.2 - 200.0*0.5) < ROUNDING); QVERIFY(qAbs(topRightCellBlock().layout()->lineAt(0).width() - 200.0*0.1) < ROUNDING); QVERIFY(qAbs(bottomLeftCellBlock().layout()->lineAt(0).width() - 200.0*0.2) < ROUNDING); QVERIFY(qAbs(bottomMidCellBlock().layout()->lineAt(0).width() - 200.0*0.5) < ROUNDING); QVERIFY(qAbs(bottomRightCellBlock().layout()->lineAt(0).width() - 200.0*0.1) < ROUNDING); } void TestTableLayout::testRowHeightFixed() { KoTableStyle *tableStyle = new KoTableStyle; setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text", tableStyle); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableRowStyle row1style; row1style.setRowHeight(3.2); styleManager.setRowStyle(1, row1style); m_layout->layout(); QVERIFY(!dynamic_cast(m_layout->provider())->m_askedForMoreThenOneArea); //QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).height() - 14) < ROUNDING); } void TestTableLayout::testRowHeightMinimum() { KoTableStyle *tableStyle = new KoTableStyle; setupTest("merged text", "top right text", "mid right text", "bottom left text", "bottom mid text", "bottom right text", tableStyle); KoTableColumnAndRowStyleManager styleManager = KoTableColumnAndRowStyleManager::getManager(m_table); KoTableRowStyle row1style; row1style.setMinimumRowHeight(3.2); styleManager.setRowStyle(1, row1style); m_layout->layout(); QVERIFY(!dynamic_cast(m_layout->provider())->m_askedForMoreThenOneArea); //QVERIFY(qAbs(mergedCellBlock().layout()->lineAt(0).height() - 14) < ROUNDING); } +QTextTable *TestTableLayout::addTable(QTextCursor cursor, int rows, int columns, KoTableStyle* tableStyle) +{ + KoParagraphStyle style; + style.setStyleId(101); // needed to do manually since we don't use the stylemanager + style.applyStyle(m_block); + QTextTableFormat tableFormat; + if (tableStyle) { + tableStyle->applyStyle(tableFormat); + } + QTextTable *table = cursor.insertTable(rows, columns, tableFormat); + for (int r = 0; r < table->rows(); ++r) { + for (int c = 0; c < table->columns(); ++c) { + QString s = QString("Cell %1, %2").arg(r, c); + table->cellAt(r,c).firstCursorPosition().insertText(s); + QTextBlock b2 = table->cellAt(r,c).firstCursorPosition().block(); + while (b2.isValid()) { + style.applyStyle(b2); + b2 = b2.next(); + } + } + } + return table; +} + +void TestTableLayout::testOneTableNeedsTwoRootAreas() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 6, 3); + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 90)); + provider->maxPosition = 10; // guard against loop + + m_layout->layout(); + + QCOMPARE(provider->m_areas.count(), 2); + + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); + + // table2 starts in first area and continues into second area + point = provider->area(1)->referenceRect().topLeft() + QPointF(0., 10.); + p = provider->area(1)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 1"); +} + +void TestTableLayout::testTwoTablesNeedsTwoRootAreas() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 2, 3); + QTextTable *table2 = addTable(c, 3, 3); + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 90)); + + m_layout->layout(); + + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + + QCOMPARE(provider->m_areas.count(), 2); + + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); + + // table2 starts in first area and continues into second area + point = provider->area(1)->referenceRect().topLeft() + QPointF(0., 10.); + p = provider->area(1)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 == p.table, "table2 not found in area 1"); +} + +void TestTableLayout::testMergedRowsSpansAreas() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 6, 3); + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 90)); + provider->maxPosition = 10; // guard against loop + + table1->mergeCells(0,0,2,1); + table1->mergeCells(0,1,2,1); + table1->mergeCells(0,2,2,1); + + table1->mergeCells(2,0,2,1); + table1->mergeCells(2,1,2,1); + table1->mergeCells(2,2,2,1); + + table1->mergeCells(4,0,2,1); + table1->mergeCells(4,1,2,1); + table1->mergeCells(4,2,2,1); + + m_layout->layout(); + + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + // should be room in two areas (it is if cells are not merged) + QCOMPARE(provider->m_areas.count(), 2); + + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); + + point = provider->area(1)->referenceRect().topLeft() + QPointF(0., 10.); + p = provider->area(1)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 1"); +} + +void TestTableLayout::testMergedRowsSpansAreas2() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 10, 3); + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 110)); + provider->maxPosition = 10; // guard against loop + + table1->mergeCells(0,0,2,1); + table1->mergeCells(0,1,2,1); + table1->mergeCells(0,2,2,1); + + table1->mergeCells(2,0,2,1); + table1->mergeCells(2,1,2,1); + table1->mergeCells(2,2,2,1); + + table1->mergeCells(4,0,2,1); + table1->mergeCells(4,1,2,1); + table1->mergeCells(4,2,2,1); + + table1->mergeCells(6,0,2,1); + table1->mergeCells(6,1,2,1); + table1->mergeCells(6,2,2,1); + + table1->mergeCells(8,0,2,1); + table1->mergeCells(8,1,2,1); + table1->mergeCells(8,2,2,1); + + m_layout->layout(); + + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + QVERIFY2(provider->m_areas.count() <= 5, "Table should fit in max 5 areas, possibly in 3"); + + // check if table is layed out at all + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); +} + +void TestTableLayout::testTwoTablesMergedRowsSpansAreas() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 4, 3); + QTextTable *table2 = addTable(c, 3, 3); + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 90)); + provider->maxPosition = 10; // guard against loop + + table2->mergeCells(0,0,2,1); + table2->mergeCells(0,1,2,1); + table2->mergeCells(0,2,2,1); + + m_layout->layout(); + + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + + QCOMPARE(provider->m_areas.count(), 2); + + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); + + // intention: there should not be room left for another row in area 0, so table2 should start in next area + point = provider->area(0)->referenceRect().bottomLeft() + QPointF(0., -10.); + p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 != p.table, "table2 found in area 0, possibly due font size"); + + point = provider->area(1)->referenceRect().topLeft() + QPointF(0., 20.); + p = provider->area(1)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 == p.table, "table2 not found in area 1"); +} + +void TestTableLayout::testTwoTablesMergedRowsSpansThreeAreas() +{ + QTextCursor c = setupTest(); + QTextTable *table1 = addTable(c, 4, 3); + QTextTable *table2 = addTable(c, 8, 3); // should need 2 areas + + MockRootAreaProvider *provider = dynamic_cast(m_layout->provider()); + QVERIFY(provider); + provider->setSuggestedRect(QRect(100, 100, 200, 90)); + provider->maxPosition = 10; // guard against loop + + table2->mergeCells(0,0,2,1); + table2->mergeCells(0,1,2,1); + table2->mergeCells(0,2,2,1); + + m_layout->layout(); + + for (int i = 0; i < provider->m_areas.count(); ++i) { + qInfo()<<"area:"<area(i)->referenceRect(); + } + + QCOMPARE(provider->m_areas.count(), 3); + + QPointF point = provider->area(0)->referenceRect().topLeft() + QPointF(0., 20.); + KoPointedAt p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table1 == p.table, "table1 not found in area 0"); + + // intention: there should not be room left for another row in area 0, so table2 should start in next area + point = provider->area(0)->referenceRect().bottomLeft() + QPointF(0., -10.); + p = provider->area(0)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 != p.table, "table2 found in area 0, possibly due font size"); + + point = provider->area(1)->referenceRect().topLeft() + QPointF(0., 20.); + p = provider->area(1)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 == p.table, "table2 not found in area 1"); + + point = provider->area(2)->referenceRect().topLeft() + QPointF(0., 20.); + p = provider->area(2)->hitTest(point, Qt::FuzzyHit); + QVERIFY2(table2 == p.table, "table2 not found in area 2"); +} + QTEST_MAIN(TestTableLayout) diff --git a/libs/textlayout/tests/TestTableLayout.h b/libs/textlayout/tests/TestTableLayout.h index 3356a623898..3a06a9db83f 100644 --- a/libs/textlayout/tests/TestTableLayout.h +++ b/libs/textlayout/tests/TestTableLayout.h @@ -1,120 +1,127 @@ /* * This file is part of Calligra tests * * Copyright (C) 2006-2010 Thomas Zander * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TESTTABLELAYOUT_H #define TESTTABLELAYOUT_H #include #include #include #include class KoStyleManager; class KoTableStyle; class QTextDocument; class QTextTable; #define ROUNDING 0.126 class TestTableLayout : public QObject { Q_OBJECT public: TestTableLayout() {} private Q_SLOTS: void initTestCase(); void cleanupTestCase(); /** * make sure our private method setupTest() does what we think it does */ void testSetupTest(); /** * Test merged cells. In this testcase the table is modelled after a special case where we happened * to end in an infinite layout-loop in the past. The loop was caused by us not being able to place * content in a cell and therefore we keeped on to ask for new root-areas. This test should verify * exactly this case. */ void testMergedCells(); - /** * If no column-width is defined then the available width should be distributed among * the available columns. Since the provided rootArea's have a width of 200 and we * have 3 columns it is expected that every of the columns has a width of 200/3. */ void testColumnWidthUndefined(); /** * If the column-width is explicit defined then we expect that those widths are used. */ void testColumnWidthFixed(); /** * Test fixed column-width of zero. */ void testColumnWidthFixedZero(); /** * If the table-width is not defined then the table get's the width of it's parent * what is the rootArea in our case. If now the defined fixed column-width's are * in total larger then those table-width then they need to be shrink proportional * to match into the available table-width. */ void testColumnWidthFixedShrink(); /** * Test relative column-width. */ void testColumnWidthRelative(); /** * Test fixed row height. The row is smaller then the text that is within the cells. Expected * is that the resulting table will still match to the available space and won't be spread * over multiple pages. This tests for bug #275409. */ void testRowHeightFixed(); /** * Test minimum row-height. */ void testRowHeightMinimum(); + void testOneTableNeedsTwoRootAreas(); + void testTwoTablesNeedsTwoRootAreas(); + void testMergedRowsSpansAreas(); + void testMergedRowsSpansAreas2(); + void testTwoTablesMergedRowsSpansAreas(); + void testTwoTablesMergedRowsSpansThreeAreas(); + private: QTextCursor setupTest(); void setupTest(const QString &mergedText, const QString &topRightText, const QString &midRightText, const QString &bottomLeftText, const QString &bottomMidText, const QString &bottomRightText, KoTableStyle* tableStyle = 0); + QTextTable *addTable(QTextCursor cursor, int rows, int columns, KoTableStyle* tableStyle = 0); private: QTextDocument *m_doc; KoTextDocumentLayout *m_layout; QTextBlock m_block; QTextBlock mergedCellBlock() const; QTextBlock topRightCellBlock() const; QTextBlock midRightCellBlock() const; QTextBlock bottomLeftCellBlock() const; QTextBlock bottomMidCellBlock() const; QTextBlock bottomRightCellBlock() const; QString m_loremIpsum; KoStyleManager *m_styleManager; QTextTable *m_table; }; #endif