/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { char const DATA_DIRECTORY[] = "/sw/qa/extras/uiwriter/data2/"; char const FLOATING_TABLE_DATA_DIRECTORY[] = "/sw/qa/extras/uiwriter/data/floating_table/"; } // namespace /// Second set of tests asserting the behavior of Writer user interface shells. class SwUiWriterTest2 : public SwModelTestBase { public: virtual std::unique_ptr preTest(const char* filename) override { m_aSavedSettings = Application::GetSettings(); if (OString(filename).indexOf("LocaleArabic") != -1) { std::unique_ptr pResetter( new Resetter([this]() { Application::SetSettings(this->m_aSavedSettings); })); AllSettings aSettings(m_aSavedSettings); aSettings.SetLanguageTag(LanguageTag("ar")); Application::SetSettings(aSettings); return pResetter; } return nullptr; } protected: AllSettings m_aSavedSettings; SwDoc* createDoc(const char* pName = nullptr); }; static void lcl_dispatchCommand(const uno::Reference& xComponent, const OUString& rCommand, const uno::Sequence& rPropertyValues) { uno::Reference xController = uno::Reference(xComponent, uno::UNO_QUERY_THROW)->getCurrentController(); CPPUNIT_ASSERT(xController.is()); uno::Reference xFrame(xController->getFrame(), uno::UNO_QUERY); CPPUNIT_ASSERT(xFrame.is()); uno::Reference xContext = ::comphelper::getProcessComponentContext(); uno::Reference xDispatchHelper(frame::DispatchHelper::create(xContext)); CPPUNIT_ASSERT(xDispatchHelper.is()); xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, rPropertyValues); } SwDoc* SwUiWriterTest2::createDoc(const char* pName) { if (!pName) loadURL("private:factory/swriter", nullptr); else load(DATA_DIRECTORY, pName); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); return pTextDoc->GetDocShell()->GetDoc(); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf47471_paraStyleBackground) { SwDoc* pDoc = createDoc("tdf47471_paraStyleBackground.odt"); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT_EQUAL(OUString("00Background"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(sal_Int32(14729933), getProperty(getParagraph(2), "FillColor")); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->EndPara(/*bSelect=*/true); lcl_dispatchCommand(mxComponent, ".uno:ResetAttributes", {}); // the background color should revert to the color for 00Background style CPPUNIT_ASSERT_EQUAL(sal_Int32(14605542), getProperty(getParagraph(2), "FillColor")); // the paragraph style should not be reset CPPUNIT_ASSERT_EQUAL(OUString("00Background"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("00Background"), getProperty(getParagraph(3), "ParaStyleName")); // Save it and load it back. reload("writer8", "tdf47471_paraStyleBackgroundRT.odt"); CPPUNIT_ASSERT_EQUAL(sal_Int32(14605542), getProperty(getParagraph(2), "FillColor")); // on round-trip, the paragraph style name was lost CPPUNIT_ASSERT_EQUAL(OUString("00Background"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("00Background"), getProperty(getParagraph(3), "ParaStyleName")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf101534) { // Copy the first paragraph of the document. load(DATA_DIRECTORY, "tdf101534.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->EndPara(/*bSelect=*/true); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Copy(); // Go to the second paragraph, assert that we have margins as direct // formatting. pWrtShell->Down(/*bSelect=*/false); SfxItemSet aSet(pWrtShell->GetAttrPool(), svl::Items{}); pWrtShell->GetCurAttr(aSet); CPPUNIT_ASSERT(aSet.HasItem(RES_LR_SPACE)); // Make sure that direct formatting is preserved during paste. pWrtShell->EndPara(/*bSelect=*/false); TransferableDataHelper aHelper(pTransfer.get()); SwTransferable::Paste(*pWrtShell, aHelper); aSet.ClearItem(); pWrtShell->GetCurAttr(aSet); // This failed, direct formatting was lost. CPPUNIT_ASSERT(aSet.HasItem(RES_LR_SPACE)); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineMoveInsertInDelete) { loadURL("private:factory/swriter", nullptr); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); SwWrtShell* const pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Insert(" foo"); pWrtShell->SttEndDoc(true); pWrtShell->InsertFootnote(""); CPPUNIT_ASSERT(pWrtShell->IsCursorInFootnote()); RedlineFlags const mode(pWrtShell->GetRedlineFlags() | RedlineFlags::On); CPPUNIT_ASSERT(mode & (RedlineFlags::ShowDelete | RedlineFlags::ShowInsert)); pWrtShell->SetRedlineFlags(mode); // insert redline pWrtShell->Insert("bar"); // first delete redline, logically containing the insert redline // (note: Word apparently allows similar things...) pWrtShell->SttEndDoc(true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); pWrtShell->Delete(); // the footnote // second delete redline, following the first one pWrtShell->EndOfSection(false); pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, /*bBasicCall=*/false); pWrtShell->Delete(); // "foo" // hiding used to copy the 2nd delete redline "foo", but not delete it pWrtShell->SetRedlineFlags(mode & ~RedlineFlags::ShowDelete); // hide CPPUNIT_ASSERT_EQUAL( OUString(" "), pWrtShell->GetCursor()->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); pWrtShell->SetRedlineFlags(mode); // show again CPPUNIT_ASSERT_EQUAL( OUString(u"\u0001 foo"), pWrtShell->GetCursor()->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineInHiddenSection) { loadURL("private:factory/swriter", nullptr); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); SwWrtShell* const pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->SplitNode(); pWrtShell->Insert("foo"); pWrtShell->SplitNode(); pWrtShell->Insert("bar"); pWrtShell->SplitNode(); pWrtShell->Insert("baz"); RedlineFlags const mode(pWrtShell->GetRedlineFlags() | RedlineFlags::On); CPPUNIT_ASSERT(mode & (RedlineFlags::ShowDelete | RedlineFlags::ShowInsert)); pWrtShell->SetRedlineFlags(mode); // delete paragraph "bar" pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 2, /*bBasicCall=*/false); pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 8, /*bBasicCall=*/false); pWrtShell->Delete(); pWrtShell->StartOfSection(); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); pWrtShell->EndOfSection(true); SwSectionData section(CONTENT_SECTION, pWrtShell->GetUniqueSectionName()); section.SetHidden(true); SwSection const* pSection = pWrtShell->InsertSection(section, nullptr); SwSectionNode const* pNode = pSection->GetFormat()->GetSectionNode(); CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 1]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 2]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 3]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT(pNode->GetNodes()[pNode->GetIndex() + 4]->IsEndNode()); pWrtShell->SetRedlineFlags(mode & ~RedlineFlags::ShowDelete); // hide CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 1]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT(pNode->GetNodes()[pNode->GetIndex() + 2]->IsEndNode()); pWrtShell->SetRedlineFlags(mode); // show again CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 1]->GetTextNode()->getLayoutFrame(nullptr)); // there was a frame created here CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 2]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT( !pNode->GetNodes()[pNode->GetIndex() + 3]->GetTextNode()->getLayoutFrame(nullptr)); CPPUNIT_ASSERT(pNode->GetNodes()[pNode->GetIndex() + 4]->IsEndNode()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf54819) { load(DATA_DIRECTORY, "tdf54819.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(1), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); //turn on red-lining and hide changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible", !IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // remove first paragraph with paragraph break SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // remaining paragraph keeps its original style CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(1), "ParaStyleName")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf54819_keep_numbering_with_Undo) { load(DATA_DIRECTORY, "tdf54819b.odt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // heading CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // next paragraph: bulleted list item CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(3), "ParaStyleName")); OUString sNumName = getProperty(getParagraph(3), "NumberingStyleName"); CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); //turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible", !IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // remove heading with paragraph break SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // solved problem: changing paragraph style after deletion CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); sNumName = getProperty(getParagraph(2), "NumberingStyleName"); // solved problem: lost numbering CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); // accept deletion, remaining (now second) paragraph: still bulleted list item IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.AcceptAllRedline(true); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); sNumName = getProperty(getParagraph(2), "NumberingStyleName"); CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); // solved problem: Undo with the workaround sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); rUndoManager.Undo(); rUndoManager.Undo(); // heading CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // next paragraph: bulleted list item CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(3), "ParaStyleName")); sNumName = getProperty(getParagraph(3), "NumberingStyleName"); CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf119571_keep_numbering_with_Undo) { // as the previous test, but with partial paragraph deletion load(DATA_DIRECTORY, "tdf54819b.odt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // heading CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // next paragraph: bulleted list item CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(3), "ParaStyleName")); OUString sNumName = getProperty(getParagraph(3), "NumberingStyleName"); CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); //turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible", !IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // remove only end part of the heading with paragraph break SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // solved problem: changing paragraph style after deletion CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); // solved problem: apply numbering CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // accept deletion, remaining (now second) paragraph: it is still heading IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.AcceptAllRedline(true); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // solved problem: Undo with the workaround sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); rUndoManager.Undo(); rUndoManager.Undo(); // heading CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty(getParagraph(2), "NumberingStyleName")); // next paragraph: bulleted list item CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(3), "ParaStyleName")); sNumName = getProperty(getParagraph(3), "NumberingStyleName"); CPPUNIT_ASSERT_MESSAGE("Missing numbering style", !sNumName.isEmpty()); CPPUNIT_ASSERT_MESSAGE("Not a bulleted list item", sNumName != "Outline"); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf109376_redline) { SwDoc* pDoc = createDoc(); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT(pWrtShell); // need 2 paragraphs to get to the bMoveNds case pWrtShell->Insert("foo"); pWrtShell->SplitNode(); pWrtShell->Insert("bar"); pWrtShell->SplitNode(); pWrtShell->StartOfSection(false); // add AT_PARA fly at 1st to be deleted node SwFormatAnchor anchor(RndStdIds::FLY_AT_PARA); anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint()); SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items{}); flySet.Put(anchor); SwFormatFrameSize size(ATT_MIN_SIZE, 1000, 1000); flySet.Put(size); // set a size, else we get 1 char per line... SwFrameFormat const* pFly = pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true); CPPUNIT_ASSERT(pFly != nullptr); pWrtShell->SttEndDoc(false); SwInsertTableOptions tableOpt(SwInsertTableFlags::DefaultBorder, 0); const SwTable& rTable = pWrtShell->InsertTable(tableOpt, 1, 1); pWrtShell->StartOfSection(false); SwPaM pam(*pWrtShell->GetCursor()->GetPoint()); pam.SetMark(); pam.GetPoint()->nNode = *rTable.GetTableNode(); pam.GetPoint()->nContent.Assign(nullptr, 0); pam.Exchange(); // same selection direction as in doc compare... IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); rIDRA.AppendRedline(new SwRangeRedline(RedlineType::Delete, pam), true); // this used to assert/crash with m_pAnchoredFlys mismatch because the // fly was not deleted but its anchor was moved to the SwTableNode rIDRA.AcceptAllRedline(true); CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); rUndoManager.Undo(); CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); rUndoManager.Redo(); CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); rUndoManager.Undo(); CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf109376) { SwDoc* pDoc = createDoc(); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT(pWrtShell); // need 2 paragraphs to get to the bMoveNds case pWrtShell->Insert("foo"); pWrtShell->SplitNode(); pWrtShell->Insert("bar"); pWrtShell->SplitNode(); pWrtShell->StartOfSection(false); // add AT_PARA fly at 1st to be deleted node SwFormatAnchor anchor(RndStdIds::FLY_AT_PARA); anchor.SetAnchor(pWrtShell->GetCursor()->GetPoint()); SfxItemSet flySet(pDoc->GetAttrPool(), svl::Items{}); flySet.Put(anchor); SwFormatFrameSize size(ATT_MIN_SIZE, 1000, 1000); flySet.Put(size); // set a size, else we get 1 char per line... SwFrameFormat const* pFly = pWrtShell->NewFlyFrame(flySet, /*bAnchValid=*/true); CPPUNIT_ASSERT(pFly != nullptr); pWrtShell->SttEndDoc(false); SwInsertTableOptions tableOpt(SwInsertTableFlags::DefaultBorder, 0); const SwTable& rTable = pWrtShell->InsertTable(tableOpt, 1, 1); pWrtShell->StartOfSection(false); SwPaM pam(*pWrtShell->GetCursor()->GetPoint()); pam.SetMark(); pam.GetPoint()->nNode = *rTable.GetTableNode(); pam.GetPoint()->nContent.Assign(nullptr, 0); pam.Exchange(); // same selection direction as in doc compare... // this used to assert/crash with m_pAnchoredFlys mismatch because the // fly was not deleted but its anchor was moved to the SwTableNode pDoc->getIDocumentContentOperations().DeleteRange(pam); CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); rUndoManager.Undo(); CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); rUndoManager.Redo(); CPPUNIT_ASSERT_EQUAL(size_t(0), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); rUndoManager.Undo(); CPPUNIT_ASSERT_EQUAL(size_t(1), pWrtShell->GetFlyCount(FLYCNTTYPE_FRM)); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf64242_optimizeTable) { SwDoc* pDoc = createDoc("tdf64242_optimizeTable.odt"); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); uno::Reference xTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xModel(mxComponent, uno::UNO_QUERY); uno::Reference xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); uno::Reference xTextTable(xTables->getByIndex(0), uno::UNO_QUERY); uno::Reference xTableRows(xTextTable->getRows(), uno::UNO_QUERY); double origWidth = getProperty(xTextTable, "Width"); sal_Int32 nToleranceW = origWidth * .01; CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Table Width", double(17013), origWidth, nToleranceW); pWrtShell->SelTable(); //select the whole table lcl_dispatchCommand(mxComponent, ".uno:SetOptimalColumnWidth", {}); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Table Width: optimize", origWidth, getProperty(xTextTable, "Width"), nToleranceW); lcl_dispatchCommand(mxComponent, ".uno:SetMinimalColumnWidth", {}); CPPUNIT_ASSERT_MESSAGE("Table Width: minimized", (origWidth - nToleranceW) > getProperty(xTextTable, "Width")); double origRowHeight = getProperty(xTableRows->getByIndex(2), "Height"); sal_Int32 nToleranceH = origRowHeight * .01; CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Row Height", double(3441), origRowHeight, nToleranceH); lcl_dispatchCommand(mxComponent, ".uno:SetOptimalRowHeight", {}); double optimalRowHeight = getProperty(xTableRows->getByIndex(2), "Height"); CPPUNIT_ASSERT_MESSAGE("Row Height: optimized", (origRowHeight - nToleranceH) > optimalRowHeight); lcl_dispatchCommand(mxComponent, ".uno:SetMinimalRowHeight", {}); double minimalRowHeight = getProperty(xTableRows->getByIndex(2), "Height"); CPPUNIT_ASSERT_MESSAGE("Row Height: minimized", (optimalRowHeight - nToleranceH) > minimalRowHeight); CPPUNIT_ASSERT_EQUAL_MESSAGE("Row set to auto-height", double(0), minimalRowHeight); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf108687_tabstop) { SwDoc* pDoc = createDoc("tdf108687_tabstop.odt"); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); sal_Int32 nStartIndex = pWrtShell->GetCursor()->GetNode().GetIndex(); CPPUNIT_ASSERT_EQUAL(sal_Int32(9), nStartIndex); // Now pressing 'tab' should jump to the radio buttons. SwXTextDocument* pXTextDocument = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pXTextDocument); pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB); pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB); Scheduler::ProcessEventsToIdle(); //sal_Int32 nEndIndex = pWrtShell->GetCursor()->GetNode().GetIndex(); //CPPUNIT_ASSERT_EQUAL(sal_Int32(11), nEndIndex); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf119571) { load(DATA_DIRECTORY, "tdf54819.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(1), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); //turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE( "redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // join paragraphs by removing the end of the first one with paragraph break SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // second paragraph changes its style in "Show changes" mode CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(1), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf119019) { // check handling of overlapping redlines load(DATA_DIRECTORY, "tdf119019.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."), getParagraph(2)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(2), 1)->getString()); // second paragraph has got a tracked paragraph formatting at this point CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(2), 1), "RedlineType")); // delete last word of the second paragraph to remove tracked paragraph formatting // of this paragraph to track and show word deletion correctly. SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/false); pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 7, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // check tracked text deletion CPPUNIT_ASSERT_EQUAL(OUString("tellus."), getRun(getParagraph(2), 3)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(2), 2)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(2), 2), "RedlineType")); // make sure that the tracked paragraph formatting is removed CPPUNIT_ASSERT(!hasProperty(getRun(getParagraph(2), 1), "RedlineType")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf119824) { // check handling of overlapping redlines with Redo SwDoc* pDoc = createDoc("tdf119019.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Pellentesque habitant morbi tristique senectus " "et netus et malesuada fames ac turpis egestas. " "Proin pharetra nonummy pede. Mauris et orci."), getParagraph(3)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 1)->getString()); // third paragraph has got a tracked paragraph formatting at this point CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 1), "RedlineType")); // and a tracked text deletion at the beginning of the paragraph CPPUNIT_ASSERT_EQUAL(OUString("Pellentesque habitant morbi tristique senectus "), getRun(getParagraph(3), 3)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 2)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 2), "RedlineType")); // delete last word of the third paragraph to remove tracked paragraph formatting // of this paragraph to track and show word deletion correctly. SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/false); pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 5, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // check tracking of the new text deletion CPPUNIT_ASSERT_EQUAL(OUString("orci."), getRun(getParagraph(3), 7)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 6)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 6), "RedlineType")); // make sure that the tracked paragraph formatting is removed (tracked deletion is in the second run) CPPUNIT_ASSERT_EQUAL(OUString("Pellentesque habitant morbi tristique senectus "), getRun(getParagraph(3), 2)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 1)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 1), "RedlineType")); // tdf#119824 check redo sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); rUndoManager.Undo(); rUndoManager.Undo(); rUndoManager.Redo(); rUndoManager.Redo(); // check again the first tracked text deletion (we lost this before the redo fix) CPPUNIT_ASSERT_EQUAL(OUString("Pellentesque habitant morbi tristique senectus "), getRun(getParagraph(3), 2)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 1)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 1), "RedlineType")); // check redo of the new tracked text deletion CPPUNIT_ASSERT_EQUAL(OUString("orci."), getRun(getParagraph(3), 7)->getString()); CPPUNIT_ASSERT_EQUAL(OUString(""), getRun(getParagraph(3), 6)->getString()); CPPUNIT_ASSERT(hasProperty(getRun(getParagraph(3), 6), "RedlineType")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf105413) { load(DATA_DIRECTORY, "tdf105413.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // all paragraphs have got Standard paragraph style for (int i = 1; i < 4; ++i) { CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(i), "ParaStyleName")); } // turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE( "redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // Set Heading 1 paragraph style in the 3th paragraph. // Because of the tracked deleted region between them, // this sets also the same style in the first paragraph automatically // to keep the changed paragraph style at hiding tracked changes or saving the document SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/false); uno::Sequence aPropertyValues = comphelper::InitPropertySequence({ { "Style", uno::makeAny(OUString("Heading 1")) }, { "FamilyName", uno::makeAny(OUString("ParagraphStyles")) }, }); lcl_dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(3), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); // first paragraph gets the same heading style CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(1), "ParaStyleName")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testUnfloatButtonSmallTable) { // The floating table in the test document is too small, so we don't provide an unfloat button load(FLOATING_TABLE_DATA_DIRECTORY, "small_floating_table.odt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT(pWrtShell); const SwSortedObjs* pAnchored = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); CPPUNIT_ASSERT(pAnchored); CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnchored->size()); SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; SwFlyFrame* pFlyFrame = dynamic_cast(pAnchoredObj); CPPUNIT_ASSERT(pFlyFrame); CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); CPPUNIT_ASSERT(pObj); pWrtShell->SelectObj(Point(), 0, pObj); CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testUnfloatButton) { // Different use cases where unfloat button should be visible const std::vector aTestFiles = { "unfloatable_floating_table.odt", // Typical use case of multipage floating table "unfloatable_floating_table.docx", // Need to test the DOCX import whether we detect the floating table correctly "unfloatable_floating_table.doc", // Also the DOC import "unfloatable_small_floating_table.docx" // Atypical use case, when the table is small, but because of it's position is it broken to two pages }; for (const OUString& aTestFile : aTestFiles) { OString sTestFileName = OUStringToOString(aTestFile, RTL_TEXTENCODING_UTF8); OString sFailureMessage = OString("Failure in the test file: ") + sTestFileName; load(FLOATING_TABLE_DATA_DIRECTORY, sTestFileName.getStr()); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pTextDoc); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pWrtShell); const SwSortedObjs* pAnchored; if (sTestFileName == "unfloatable_small_floating_table.docx") pAnchored = pWrtShell->GetLayout() ->GetLower() ->GetLower() ->GetLower() ->GetNext() ->GetDrawObjs(); else pAnchored = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pAnchored); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailureMessage.getStr(), static_cast(1), pAnchored->size()); SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; // The unfloat button is not visible until it gets selected SwFlyFrame* pFlyFrame = dynamic_cast(pAnchoredObj); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), !pFlyFrame->IsShowUnfloatButton(pWrtShell)); SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pObj); pWrtShell->SelectObj(Point(), 0, pObj); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame->IsShowUnfloatButton(pWrtShell)); } } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testUnfloatButtonReadOnlyMode) { // In read only mode we don't show the unfloat button even if we have a multipage floating table load(FLOATING_TABLE_DATA_DIRECTORY, "unfloatable_floating_table.odt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT(pWrtShell); pWrtShell->SetReadonlyOption(true); const SwSortedObjs* pAnchored = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); CPPUNIT_ASSERT(pAnchored); CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnchored->size()); SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; SwFlyFrame* pFlyFrame = dynamic_cast(pAnchoredObj); CPPUNIT_ASSERT(pFlyFrame); CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); CPPUNIT_ASSERT(pObj); pWrtShell->SelectObj(Point(), 0, pObj); CPPUNIT_ASSERT(!pFlyFrame->IsShowUnfloatButton(pWrtShell)); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testUnfloating) { // Test unfloating with tables imported from different file formats const std::vector aTestFiles = { "unfloatable_floating_table.odt", "unfloatable_floating_table.docx", "unfloatable_floating_table.doc", }; for (const OUString& aTestFile : aTestFiles) { OString sTestFileName = OUStringToOString(aTestFile, RTL_TEXTENCODING_UTF8); OString sFailureMessage = OString("Failure in the test file: ") + sTestFileName; // Test what happens when pushing the unfloat button load(FLOATING_TABLE_DATA_DIRECTORY, "unfloatable_floating_table.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pTextDoc); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pWrtShell); SwFlyFrame* pFlyFrame; // Before unfloating we have only one page with a fly frame { CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailureMessage.getStr(), SwFrameType::Page, pWrtShell->GetLayout()->GetLower()->GetType()); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), !pWrtShell->GetLayout()->GetLower()->GetNext()); CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailureMessage.getStr(), SwFrameType::Txt, pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetType()); const SwSortedObjs* pAnchored = pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetDrawObjs(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pAnchored); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailureMessage.getStr(), static_cast(1), pAnchored->size()); SwAnchoredObject* pAnchoredObj = (*pAnchored)[0]; pFlyFrame = dynamic_cast(pAnchoredObj); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame); } // Select the floating table SdrObject* pObj = pFlyFrame->GetFormat()->FindRealSdrObject(); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pObj); pWrtShell->SelectObj(Point(), 0, pObj); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pFlyFrame->IsShowUnfloatButton(pWrtShell)); // Push the unfloat button pFlyFrame->ActiveUnfloatButton(pWrtShell); Scheduler::ProcessEventsToIdle(); // After unfloating we have two pages with one table frame on each page CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), pWrtShell->GetLayout()->GetLower()->GetNext()); CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailureMessage.getStr(), SwFrameType::Page, pWrtShell->GetLayout()->GetLower()->GetNext()->GetType()); CPPUNIT_ASSERT_MESSAGE(sFailureMessage.getStr(), !pWrtShell->GetLayout()->GetLower()->GetNext()->GetNext()); CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailureMessage.getStr(), SwFrameType::Tab, pWrtShell->GetLayout()->GetLower()->GetLower()->GetLower()->GetType()); CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailureMessage.getStr(), SwFrameType::Tab, pWrtShell->GetLayout()->GetLower()->GetNext()->GetLower()->GetLower()->GetType()); } } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRTLparaStyle_LocaleArabic) { // New documents, created in RTL locales, were not round-tripping the paragraph style as RTL. // Set the locale to "ar" for this test - see preTest() at the top of this file. std::unique_ptr const pChanges(preTest("LocaleArabic")); createDoc(); // new, empty doc - everything defaults to RTL with Arabic locale // Save it and load it back. reload("Office Open XML Text", "tdf116404_paraStyleFrameDir.docx"); uno::Reference xPageStyle( getStyles("ParagraphStyles")->getByName("Default Style"), uno::UNO_QUERY_THROW); // Test the text Direction value for the -none- based paragraph styles CPPUNIT_ASSERT_EQUAL_MESSAGE("RTL Writing Mode", sal_Int32(1), getProperty(xPageStyle, "WritingMode")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf122893) { load(DATA_DIRECTORY, "tdf105413.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // all paragraphs are left-aligned with preset single line spacing for (int i = 1; i < 4; ++i) { CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(i), "ParaAdjust")); lcl_dispatchCommand(mxComponent, ".uno:SpacePara1", {}); } // turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE( "redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // Set center-aligned paragraph with preset double line spacing in the 3th paragraph. // Because of the tracked deleted region between them, // this sets also the same formatting in the first paragraph automatically // to keep the changed paragraph formatting at hiding tracked changes or saving the document SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/false); lcl_dispatchCommand(mxComponent, ".uno:CenterPara", {}); lcl_dispatchCommand(mxComponent, ".uno:SpacePara2", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getProperty(getParagraph(3), "ParaAdjust")); // center-aligned CPPUNIT_ASSERT_EQUAL(sal_Int16(200), getProperty(getParagraph(3), "ParaLineSpacing") .Height); // double line spacing CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaAdjust")); // left-aligned CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty(getParagraph(2), "ParaLineSpacing") .Height); // single line spacing // first paragraph is also center-aligned with double line spacing CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getProperty(getParagraph(1), "ParaAdjust")); CPPUNIT_ASSERT_EQUAL( sal_Int16(200), getProperty(getParagraph(1), "ParaLineSpacing").Height); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf122901) { load(DATA_DIRECTORY, "tdf105413.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // all paragraphs with zero borders for (int i = 1; i < 4; ++i) { CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(i), "ParaTopMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(i), "ParaBottomMargin")); } // turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE( "redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // Increase paragraph borders in the 3th paragraph, similar to the default icon of the UI // "Increase Paragraph Spacing". Because of the tracked deleted region between them, // this sets also the same formatting in the first paragraph automatically // to keep the changed paragraph formatting at hiding tracked changes or saving the document SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->EndPara(/*bSelect=*/false); lcl_dispatchCommand(mxComponent, ".uno:ParaspaceIncrease", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(101), getProperty(getParagraph(3), "ParaTopMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(101), getProperty(getParagraph(3), "ParaBottomMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaTopMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaBottomMargin")); // first paragraph is also center-aligned with double line spacing CPPUNIT_ASSERT_EQUAL(sal_Int32(101), getProperty(getParagraph(1), "ParaTopMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(101), getProperty(getParagraph(1), "ParaBottomMargin")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf122942) { load(DATA_DIRECTORY, "tdf122942.odt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); // Do the moral equivalent of mouse button down, move and up. // Start creating a custom shape that overlaps with the rounded rectangle // already present in the document. Point aStartPos(8000, 3000); pWrtShell->BeginCreate(static_cast(OBJ_CUSTOMSHAPE), aStartPos); // Set its size. Point aMovePos(10000, 5000); pWrtShell->MoveCreate(aMovePos); // Finish creation. pWrtShell->EndCreate(SdrCreateCmd::ForceEnd); // Make sure that the shape is inserted. SwDoc* pDoc = pWrtShell->GetDoc(); const SwFrameFormats& rFormats = *pDoc->GetSpzFrameFormats(); CPPUNIT_ASSERT_EQUAL(static_cast(2), rFormats.size()); reload("writer8", "tdf122942.odt"); pTextDoc = dynamic_cast(mxComponent.get()); pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pDoc = pWrtShell->GetDoc(); const SwFrameFormats& rFormats2 = *pDoc->GetSpzFrameFormats(); CPPUNIT_ASSERT_EQUAL(static_cast(2), rFormats2.size()); // Make sure the top of the inserted shape does not move outside the existing shape, even after // reload. SdrObject* pObject1 = rFormats2[0]->FindSdrObject(); CPPUNIT_ASSERT(pObject1); const tools::Rectangle& rOutRect1 = pObject1->GetLastBoundRect(); SdrObject* pObject2 = rFormats2[1]->FindSdrObject(); CPPUNIT_ASSERT(pObject2); const tools::Rectangle& rOutRect2 = pObject2->GetLastBoundRect(); CPPUNIT_ASSERT(rOutRect2.Top() > rOutRect1.Top() && rOutRect2.Top() < rOutRect1.Bottom()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf52391) { load(DATA_DIRECTORY, "tdf52391.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); lcl_dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {}); const uno::Reference xRun = getRun(getParagraph(1), 1); // this was "Portion1", because the tracked background color of Portion1 was // accepted for "Reject All". Now rejection clears formatting of the text // in format-only changes, concatenating the text portions in the first paragraph. CPPUNIT_ASSERT_EQUAL(OUString("Portion1Portion2"), xRun->getString()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf126206) { load(DATA_DIRECTORY, "tdf126206.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // normal text (it was bold) auto xText = getParagraph(1)->getText(); CPPUNIT_ASSERT(xText.is()); { auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2))); CPPUNIT_ASSERT(xCursor.is()); CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty(xCursor, "CharWeight")); } // reject tracked changes lcl_dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {}); // bold text again xText = getParagraph(1)->getText(); CPPUNIT_ASSERT(xText.is()); { auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2))); CPPUNIT_ASSERT(xCursor.is()); CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty(xCursor, "CharWeight")); } } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf101873) { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); SwDocShell* pDocShell = pDoc->GetDocShell(); CPPUNIT_ASSERT(pDocShell); SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); CPPUNIT_ASSERT(pWrtShell); // Insert some content. pWrtShell->Insert("something"); // Search for something which does not exist, twice. uno::Sequence aFirst(comphelper::InitPropertySequence({ { "SearchItem.SearchString", uno::makeAny(OUString("fig")) }, { "SearchItem.Backward", uno::makeAny(false) }, })); lcl_dispatchCommand(mxComponent, ".uno:ExecuteSearch", aFirst); lcl_dispatchCommand(mxComponent, ".uno:ExecuteSearch", aFirst); uno::Sequence aSecond(comphelper::InitPropertySequence({ { "SearchItem.SearchString", uno::makeAny(OUString("something")) }, { "SearchItem.Backward", uno::makeAny(false) }, })); lcl_dispatchCommand(mxComponent, ".uno:ExecuteSearch", aSecond); // Without the accompanying fix in place, this test would have failed with "Expected: something; // Actual:", i.e. searching for "something" failed, even if it was inserted above. SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); CPPUNIT_ASSERT_EQUAL(OUString("something"), pShellCursor->GetText()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTableWidth) { load(DATA_DIRECTORY, "frame_size_export.docx"); uno::Reference xStorable(mxComponent, uno::UNO_QUERY); utl::MediaDescriptor aMediaDescriptor; aMediaDescriptor["FilterName"] <<= OUString("Office Open XML Text"); xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); // after exporting: table width was overwritten in the doc model uno::Reference xTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty(xTables->getByIndex(0), "RelativeWidth")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTextFormFieldInsertion) { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); CPPUNIT_ASSERT(pMarkAccess); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Insert a text form field lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); // Check whether the fieldmark is created auto aIter = pMarkAccess->getAllMarksBegin(); CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter); CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMTEXT), pFieldmark->GetFieldname()); // The text form field has the placeholder text in it uno::Reference xPara = getParagraph(1); sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 }; CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString()); // Undo insertion lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); xPara.set(getParagraph(1)); CPPUNIT_ASSERT(xPara->getString().isEmpty()); // Redo insertion lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); xPara.set(getParagraph(1)); CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testCheckboxFormFieldInsertion) { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); CPPUNIT_ASSERT(pMarkAccess); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Insert a checkbox form field lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); // Check whether the fieldmark is created auto aIter = pMarkAccess->getAllMarksBegin(); CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter); CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname()); // The checkbox is not checked by default ::sw::mark::ICheckboxFieldmark* pCheckBox = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(pFieldmark); CPPUNIT_ASSERT(pCheckBox); CPPUNIT_ASSERT(!pCheckBox->IsChecked()); // Undo insertion lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Redo insertion lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); aIter = pMarkAccess->getAllMarksBegin(); CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter); CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDropDownFormFieldInsertion) { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); CPPUNIT_ASSERT(pMarkAccess); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Insert a drop-down form field lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); // Check whether the fieldmark is created auto aIter = pMarkAccess->getAllMarksBegin(); CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter); CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname()); // Check drop down field's parameters. By default these params are not set const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters(); auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY); CPPUNIT_ASSERT(bool(pListEntries == pParameters->end())); auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT); CPPUNIT_ASSERT(bool(pResult == pParameters->end())); // Undo insertion lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Redo insertion lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); aIter = pMarkAccess->getAllMarksBegin(); CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd()); pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter); CPPUNIT_ASSERT(pFieldmark); CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testMixedFormFieldInsertion) { SwDoc* pDoc = createDoc(); CPPUNIT_ASSERT(pDoc); IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); CPPUNIT_ASSERT(pMarkAccess); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Insert fields lcl_dispatchCommand(mxComponent, ".uno:TextFormField", {}); lcl_dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {}); lcl_dispatchCommand(mxComponent, ".uno:DropDownFormField", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount()); // Undo insertion lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); lcl_dispatchCommand(mxComponent, ".uno:Undo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount()); // Redo insertion lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); lcl_dispatchCommand(mxComponent, ".uno:Redo", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf124261) { #if !defined(WNT) // Make sure that pressing a key in a btlr cell frame causes an immediate, correct repaint. SwDoc* pDoc = createDoc("tdf124261.docx"); SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); SwFrame* pPageFrame = pLayout->GetLower(); CPPUNIT_ASSERT(pPageFrame->IsPageFrame()); SwFrame* pBodyFrame = pPageFrame->GetLower(); CPPUNIT_ASSERT(pBodyFrame->IsBodyFrame()); SwFrame* pTabFrame = pBodyFrame->GetLower(); CPPUNIT_ASSERT(pTabFrame->IsTabFrame()); SwFrame* pRowFrame = pTabFrame->GetLower(); CPPUNIT_ASSERT(pRowFrame->IsRowFrame()); SwFrame* pCellFrame = pRowFrame->GetLower(); CPPUNIT_ASSERT(pCellFrame->IsCellFrame()); SwFrame* pFrame = pCellFrame->GetLower(); CPPUNIT_ASSERT(pFrame->IsTextFrame()); // Make sure that the text frame's area and the paint rectangle match. // Without the accompanying fix in place, this test would have failed with 'Expected: 1721; // Actual: 1547', i.e. an area other than the text frame was invalidated for a single-line // paragraph. SwTextFrame* pTextFrame = static_cast(pFrame); SwRect aRect = pTextFrame->GetPaintSwRect(); CPPUNIT_ASSERT_EQUAL(pTextFrame->getFrameArea().Top(), aRect.Top()); #endif } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testDocxAttributeTableExport) { createDoc("floating-table-position.docx"); // get the table frame, set new values and dismiss the references { uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xDrawPage(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY); uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); // change the properties // 8133 -> 8000 xShape->setPropertyValue("VertOrientPosition", uno::makeAny(static_cast(8000))); // 5964 -> 5000 xShape->setPropertyValue("HoriOrientPosition", uno::makeAny(static_cast(5000))); // 0 (frame) -> 8 (page print area) xShape->setPropertyValue("VertOrientRelation", uno::makeAny(static_cast(8))); // 8 (page print area) -> 0 (frame) xShape->setPropertyValue("HoriOrientRelation", uno::makeAny(static_cast(0))); } // save it to docx reload("Office Open XML Text", "floating-table-position.docx"); uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xDrawPage(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY); uno::Reference xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY); // test the new values sal_Int32 nValue = getProperty(xShape, "VertOrientPosition"); CPPUNIT_ASSERT(sal_Int32(7999) <= nValue && nValue <= sal_Int32(8001)); nValue = getProperty(xShape, "HoriOrientPosition"); CPPUNIT_ASSERT(sal_Int32(4999) <= nValue && nValue <= sal_Int32(5001)); CPPUNIT_ASSERT_EQUAL(sal_Int16(8), getProperty(xShape, "VertOrientRelation")); CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty(xShape, "HoriOrientRelation")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf118699_redline_numbering) { load(DATA_DIRECTORY, "tdf118699.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.AcceptAllRedline(true); uno::Reference xProps(getParagraph(2), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering", !xProps->getPropertyValue("NumberingRules").hasValue()); CPPUNIT_ASSERT_MESSAGE( "first paragraph after the second deletion: missing numbering", getProperty>(getParagraph(5), "NumberingRules") .is()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf125881_redline_list_level) { load(DATA_DIRECTORY, "tdf125881.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); // deleted paragraph gets the numbering of the next paragraph uno::Reference xProps(getParagraph(8), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: missing numbering", xProps->getPropertyValue("NumberingRules").hasValue()); // check numbering level at deletion (1 instead of 0) CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty(getParagraph(8), "NumberingLevel")); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf125916_redline_restart_numbering) { load(DATA_DIRECTORY, "tdf125916.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.AcceptAllRedline(true); // check unnecessary numbering uno::Reference xProps(getParagraph(3), uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering", !xProps->getPropertyValue("NumberingRules").hasValue()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf125310) { load(DATA_DIRECTORY, "tdf125310.fodt"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(1), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(1, getPages()); // turn on red-lining and show changes SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); CPPUNIT_ASSERT_MESSAGE( "redlines should be visible", IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); // paragraph join SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); pWrtShell->EndPara(/*bSelect=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); rtl::Reference pTransfer = new SwTransferable(*pWrtShell); pTransfer->Cut(); // copied paragraph style CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(2), "ParaStyleName")); // without copying the page break CPPUNIT_ASSERT_EQUAL(1, getPages()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf125310b) { SwDoc* pDoc = createDoc("tdf125310b.fodt"); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(2), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), getProperty(getParagraph(3), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(2, getPages()); // turn on red-lining and show changes pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert); CPPUNIT_ASSERT_MESSAGE("redlining should be on", pDoc->getIDocumentRedlineAccess().IsRedlineOn()); // remove second paragraph with the page break pWrtShell->Down(/*bSelect=*/false); pWrtShell->Down(/*bSelect=*/false); pWrtShell->Up(/*bSelect=*/true); pWrtShell->DelLeft(); IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess()); rIDRA.AcceptAllRedline(true); // losing the page break, as without redlining CPPUNIT_ASSERT_EQUAL(1, getPages()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testImageComment) { // Load a document with an as-char image in it. SwDoc* pDoc = createDoc("image-comment.odt"); SwView* pView = pDoc->GetDocShell()->GetView(); // Test document has "beforeafter", remove the content before the image. SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); pWrtShell->SttEndDoc(/*bStart=*/true); pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 6, /*bBasicCall=*/false); pWrtShell->Delete(); // Select the image. pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); // Insert a comment while the image is selected. pView->GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON); // Verify that the comment is around the image. // Without the accompanying fix in place, this test would have failed, as FN_POSTIT was disabled // in the frame shell. // Then this test would have failed, as in case the as-char anchored image was at the start of // the paragraph, the comment of the image covered the character after the image, not the image. uno::Reference xPara = getParagraph(1); CPPUNIT_ASSERT_EQUAL(OUString("Annotation"), getProperty(getRun(xPara, 1), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Frame"), getProperty(getRun(xPara, 2), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"), getProperty(getRun(xPara, 3), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Text"), getProperty(getRun(xPara, 4), "TextPortionType")); // Insert content to the comment, and select the image again. SfxStringItem aItem(FN_INSERT_STRING, "x"); pView->GetViewFrame()->GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON, { &aItem }); pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); // Now delete the image. pView->GetViewFrame()->GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON); // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual: // 1', i.e. the comment of the image was not deleted when the image was deleted. CPPUNIT_ASSERT_EQUAL(static_cast(0), pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testImageCommentAtChar) { // Load a document with an at-char image in it. SwDoc* pDoc = createDoc("image-comment-at-char.odt"); SwView* pView = pDoc->GetDocShell()->GetView(); // Select the image. pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); // Insert a comment while the image is selected. pView->GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON); // Verify that the comment is around the image. // Without the accompanying fix in place, this test would have failed, as the comment was // anchored at the end of the paragraph, it was not around the image. uno::Reference xPara = getParagraph(1); CPPUNIT_ASSERT_EQUAL(OUString("Text"), getProperty(getRun(xPara, 1), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Annotation"), getProperty(getRun(xPara, 2), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Frame"), getProperty(getRun(xPara, 3), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"), getProperty(getRun(xPara, 4), "TextPortionType")); CPPUNIT_ASSERT_EQUAL(OUString("Text"), getProperty(getRun(xPara, 5), "TextPortionType")); // Insert content to the comment, and select the image again. SfxStringItem aItem(FN_INSERT_STRING, "x"); pView->GetViewFrame()->GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON, { &aItem }); pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); // Now delete the image. pView->GetViewFrame()->GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON); // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual: // 1', i.e. the comment of the image was not deleted when the image was deleted. CPPUNIT_ASSERT_EQUAL(static_cast(0), pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount()); } CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf120338) { load(DATA_DIRECTORY, "tdf120338.docx"); SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty(getParagraph(2), "ParaAdjust")); // right CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty(getParagraph(3), "ParaAdjust")); // right CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(4), "ParaAdjust")); // left CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty(getParagraph(5), "ParaAdjust")); // right CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"), getProperty(getParagraph(10), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"), getProperty(getParagraph(11), "ParaStyleName")); // reject tracked paragraph adjustments lcl_dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {}); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaAdjust")); // left CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getProperty(getParagraph(3), "ParaAdjust")); // center CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getProperty(getParagraph(4), "ParaAdjust")); // center CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(5), "ParaAdjust")); // left // tdf#126243 revert paragraph styles CPPUNIT_ASSERT_EQUAL(OUString("Standard"), getProperty(getParagraph(10), "ParaStyleName")); CPPUNIT_ASSERT_EQUAL(OUString("Heading 3"), getProperty(getParagraph(11), "ParaStyleName")); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */