/* -*- 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/.
*/
/// Second set of tests asserting the behavior of Writer user interface shells. class SwUiWriterTest5 : public SwModelTestBase
{ public:
SwUiWriterTest5()
: SwModelTestBase(u"/sw/qa/extras/uiwriter/data/"_ustr)
{
}
// turn on red-lining and show changes
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()));
// two pages
CPPUNIT_ASSERT_EQUAL(2, getPages());
// delete the last two characters with a page break at the end of the document
dispatchCommand(mxComponent, u".uno:GoToEndOfDoc"_ustr, {});
dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
CPPUNIT_ASSERT_EQUAL(1, getPages());
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(u"First page"_ustr, xTextDocument->getText()->getString());
// Undo
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // this would crash due to bad redline range
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
CPPUNIT_ASSERT_EQUAL(2, getPages());
CPPUNIT_ASSERT_EQUAL(u"First page"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u"B"_ustr, getParagraph(2)->getString());
// switch off "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
}
//turn on red-lining and show changes
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()));
// switch on "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
//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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// show deletions inline
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u"dolor sit"_ustr, getParagraph(2)->getString());
// switch on "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
// show deletions in margin
CPPUNIT_ASSERT_EQUAL(u"Loremm"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u"dolsit"_ustr, getParagraph(2)->getString());
// switch off "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
// show deletions inline again
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, getParagraph(1)->getString());
CPPUNIT_ASSERT_EQUAL(u"dolor sit"_ustr, getParagraph(2)->getString());
}
//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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// show deletions inline
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum dolor sit amet..."_ustr, getParagraph(1)->getString());
// switch on "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
// show deletions in margin
CPPUNIT_ASSERT_EQUAL(u"Lorem amet..."_ustr, getParagraph(1)->getString());
// switch off "Show changes in margin" mode
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
// show deletions inline again
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum dolor sit amet..."_ustr, getParagraph(1)->getString());
// Save it and load it back.
saveAndReload(u"writer8"_ustr);
// Test comment range feature on tracked deletion.
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); bool bAnnotationStart = false; bool bBeforeAnnotation = true;
OUString sTextBeforeAnnotation; while (xRunEnum->hasMoreElements())
{
uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
OUString aType = getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr); // there is no AnnotationEnd with preceding AnnotationStart, // i.e. annotation with lost range
CPPUNIT_ASSERT(aType != "AnnotationEnd" || !bAnnotationStart);
bAnnotationStart = (aType == "Annotation");
// collect paragraph text before the first annotation if (bBeforeAnnotation)
{ if (bAnnotationStart)
bBeforeAnnotation = false; elseif (aType == "Text")
{
uno::Reference<text::XTextRange> xRun(xPropertySet, uno::UNO_QUERY);
sTextBeforeAnnotation += xRun->getString();
}
}
}
// This was "Lorem ipsum" (collapsed annotation range)
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, sTextBeforeAnnotation);
}
// normal text (it was bold) auto xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 4)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
getProperty<float>(xCursor, u"CharWeight"_ustr));
}
// bold text again
xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString()); // This was NORMAL
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(xCursor, u"CharWeight"_ustr));
}
}
// bold text again
xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString()); // This was NORMAL (only underlining was removed)
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(xCursor, u"CharWeight"_ustr));
}
}
// select first paragraph, add underline without change tracking
pWrtShell->EndPara(/*bSelect=*/true);
dispatchCommand(mxComponent, u".uno:Underline"_ustr, {});
auto xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, xCursor->getString());
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
}
// 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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// no italic, but still underline direct formatting
xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, xCursor->getString()); // This wasn't underlined (lost direct formatting)
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
}
}
// bold text auto xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(xCursor, u"CharWeight"_ustr));
}
// positionate the text cursor inside the first word
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false); // remove bold formatting with change tracking without selection
dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
// bold text again
xText = getParagraph(1)->getText();
CPPUNIT_ASSERT(xText.is());
{ auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
CPPUNIT_ASSERT(xCursor.is());
CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString()); // This was NORMAL
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
getProperty<float>(xCursor, u"CharWeight"_ustr));
}
}
// 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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// modify character formatting of the all the text
// multiple format redlines for the multiple hints
SwEditShell* const pEditShell(pDoc->GetEditShell());
CPPUNIT_ASSERT(pEditShell); // This was 1.
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
// 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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// paragraph style of the first paragraph: Heading 1, second paragraph: Standard
// This was Standard (missing reject)
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr)); // This was Heading 2 (missing reject)
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
}
// 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(u"something"_ustr, pShellCursor->GetText());
}
// Insert a text form field
dispatchCommand(mxComponent, u".uno:TextFormField"_ustr, {});
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::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
CPPUNIT_ASSERT(pFieldmark);
CPPUNIT_ASSERT_EQUAL(ODF_FORMTEXT, pFieldmark->GetFieldname());
// The text form field has the placeholder text in it
uno::Reference<text::XTextRange> xPara = getParagraph(1);
CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
// Insert a checkbox form field
dispatchCommand(mxComponent, u".uno:CheckBoxFormField"_ustr, {});
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::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
CPPUNIT_ASSERT(pFieldmark);
CPPUNIT_ASSERT_EQUAL(ODF_FORMCHECKBOX, pFieldmark->GetFieldname()); // The checkbox is not checked by default
::sw::mark::CheckboxFieldmark* pCheckBox
= dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark);
CPPUNIT_ASSERT(pCheckBox);
CPPUNIT_ASSERT(!pCheckBox->IsChecked());
// Insert a drop-down form field
dispatchCommand(mxComponent, u".uno:DropDownFormField"_ustr, {});
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::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
CPPUNIT_ASSERT(pFieldmark);
CPPUNIT_ASSERT_EQUAL(ODF_FORMDROPDOWN, pFieldmark->GetFieldname()); // Check drop down field's parameters. By default these params are not set const sw::mark::Fieldmark::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()));
// Without the fix in place, this test would have crashed here
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(6), rIDMA.getAllMarksCount());
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
}
uno::Reference<beans::XPropertySet> xProps(getParagraph(2), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
!xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
CPPUNIT_ASSERT_MESSAGE("first paragraph after the second deletion: missing numbering",
getProperty<uno::Reference<container::XIndexAccess>>(
getParagraph(5), u"NumberingRules"_ustr)
.is());
}
// deleted paragraph gets the numbering of the next paragraph
uno::Reference<beans::XPropertySet> xProps2(getParagraph(9), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: missing numbering",
xProps2->getPropertyValue(u"NumberingRules"_ustr).hasValue());
// check numbering level at deletion (1 instead of 0)
CPPUNIT_ASSERT_EQUAL(sal_Int16(1),
getProperty<sal_Int16>(getParagraph(9), u"NumberingLevel"_ustr));
}
// moveFrom/moveTo are imported as separated redlines from fixing tdf#145718. // Accept the first inline moveFrom redline before accepting the remaining ones // to leave a paragraph long deletion to test the fix for tdf#125916.
SwEditShell* const pEditShell(pDoc->GetEditShell());
CPPUNIT_ASSERT(pEditShell);
CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
pEditShell->AcceptRedline(0);
// 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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// 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();
// 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());
CPPUNIT_ASSERT_MESSAGE( "redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// try to turn off red-lining
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
// but the protection doesn't allow it
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageComment)
{ // Load a document with an as-char image in it.
createSwDoc("image-comment.odt");
SwDoc* pDoc = getSwDoc();
SwView* pView = getSwDocShell()->GetView();
// Test document has "before<image>after", remove the content before the image.
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
pWrtShell->SttEndDoc(/*bStart=*/true);
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
pWrtShell->Delete();
// Select the image.
selectShape(1);
// 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<text::XTextRange> xPara = getParagraph(1);
CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr,
getProperty<OUString>(getRun(xPara, 1), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr,
getProperty<OUString>(getRun(xPara, 2), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr,
getProperty<OUString>(getRun(xPara, 3), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
getProperty<OUString>(getRun(xPara, 4), u"TextPortionType"_ustr));
// Insert content to the comment, and select the image again.
SfxStringItem aItem(FN_INSERT_STRING, u"x"_ustr);
pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
{ &aItem });
selectShape(1);
// Make sure that the anchor points to the bottom left corner of the image. // Without the accompanying fix in place, this test would have failed with: // - Expected less or equal than: 1418 // - Actual: 2442 // The anchor pointed to the bottom right corner, so as-char and at-char was inconsistent.
Scheduler::ProcessEventsToIdle();
SwPostItMgr* pPostItMgr = pView->GetPostItMgr(); for (constauto& pItem : *pPostItMgr)
{ const SwRect& rAnchor = pItem->mpPostIt->GetAnchorRect();
CPPUNIT_ASSERT_EQUAL(nFrameLeft, rAnchor.Left());
}
// Test the comment anchor we expose via the LOK API. // Without the accompanying fix in place, this test would have failed with: // - Expected: 1418, 1418, 0, 0 // - Actual : 1418, 1418, 1024, 1024 // I.e. the anchor position had a non-empty size, which meant different rendering via tiled // rendering and on the desktop.
tools::JsonWriter aJsonWriter;
SwXTextDocument* pTextDoc = getSwTextDoc();
pTextDoc->getPostIts(aJsonWriter);
OString pChar = aJsonWriter.finishAndGetAsOString();
std::stringstream aStream((std::string(pChar)));
boost::property_tree::ptree aTree;
boost::property_tree::read_json(aStream, aTree); for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("comments"))
{ const boost::property_tree::ptree& rComment = rValue.second;
OString aAnchorPos(rComment.get<std::string>("anchorPos"));
OString aExpected
= OString::number(nFrameLeft) + ", " + OString::number(nFrameTop) + ", 0, 0";
CPPUNIT_ASSERT_EQUAL(aExpected, aAnchorPos);
}
#endif
// 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<sal_Int32>(0),
pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageCommentAtChar)
{ // Load a document with an at-char image in it.
createSwDoc("image-comment-at-char.odt");
SwDoc* pDoc = getSwDoc();
SwView* pView = getSwDocShell()->GetView();
// Select the image.
selectShape(1);
// 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<text::XTextRange> xPara = getParagraph(1);
CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
getProperty<OUString>(getRun(xPara, 1), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr,
getProperty<OUString>(getRun(xPara, 2), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr,
getProperty<OUString>(getRun(xPara, 3), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr,
getProperty<OUString>(getRun(xPara, 4), u"TextPortionType"_ustr));
CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
getProperty<OUString>(getRun(xPara, 5), u"TextPortionType"_ustr));
// Insert content to the comment, and select the image again.
SfxStringItem aItem(FN_INSERT_STRING, u"x"_ustr);
pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
{ &aItem });
selectShape(1); // 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<sal_Int32>(0),
pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
// Undo the deletion and move the image down, so the anchor changes.
pView->GetViewFrame().GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
Point aNewAnchor = pWrtShell->GetFlyRect().TopLeft();
aNewAnchor.Move(0, 600);
pWrtShell->SetFlyPos(aNewAnchor);
// Get the image anchor doc model position.
SwFlyFrame* pFly = pWrtShell->GetCurrFlyFrame(false);
CPPUNIT_ASSERT(pFly);
SwFrameFormat* pFlyFormat = pFly->GetFrameFormat(); const SwPosition* pImageAnchor = pFlyFormat->GetAnchor().GetContentAnchor();
CPPUNIT_ASSERT(pImageAnchor);
// Get the annotation mark doc model start. auto it = pDoc->getIDocumentMarkAccess()->getAnnotationMarksBegin();
CPPUNIT_ASSERT(it != pDoc->getIDocumentMarkAccess()->getAnnotationMarksEnd()); const sw::mark::MarkBase* pMark = *it; const SwPosition& rAnnotationMarkStart = pMark->GetMarkPos();
// Without the accompanying fix in place, this test would have failed with: // - Expected: SwPosition (node 14, offset 15) // - Actual : SwPosition (node 12, offset 3) // This means moving the image anchor did not move the comment anchor / annotation mark, so the // image and its comment got out of sync.
CPPUNIT_ASSERT_EQUAL(*pImageAnchor, rAnnotationMarkStart);
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageDeletion)
{ // load a document with an image anchored to paragraph in it
createSwDoc("image.odt");
SwDoc* pDoc = getSwDoc();
SwView* pView = getSwDocShell()->GetView();
// select the image
selectShape(1);
// turn on red-lining and show changes
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
rIDRA.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()));
// now delete the image with track changes
pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
const SwRedlineTable& rTable = rIDRA.GetRedlineTable(); // this was 0 (missing recording of deletion of images)
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY); // tdf#142701 this was AS_CHARACTER (convert AT_PARA to AT_CHAR to keep the layout)
CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
getProperty<text::TextContentAnchorType>(xShape, u"AnchorType"_ustr));
}
// turn on red-lining and show changes
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
rIDRA.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()));
// Insert an image with change tracking
uno::Sequence<beans::PropertyValue> aArgs = {
comphelper::makePropertyValue(u"FileName"_ustr, createFileURL(u"ole2.png")),
};
dispatchCommand(mxComponent, u".uno:InsertGraphic"_ustr, aArgs);
const SwRedlineTable& rTable = rIDRA.GetRedlineTable(); // this was 0 (missing recording of insertion of images)
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
}
CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
getProperty<sal_Int32>(getParagraph(2), u"ParaAdjust"_ustr)); // right
CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
getProperty<sal_Int32>(getParagraph(3), u"ParaAdjust"_ustr)); // right
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
getProperty<sal_Int32>(getParagraph(4), u"ParaAdjust"_ustr)); // left
CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
getProperty<sal_Int32>(getParagraph(5), u"ParaAdjust"_ustr)); // right
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
getProperty<sal_Int32>(getParagraph(2), u"ParaAdjust"_ustr)); // left
CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
getProperty<sal_Int32>(getParagraph(3), u"ParaAdjust"_ustr)); // center
CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
getProperty<sal_Int32>(getParagraph(4), u"ParaAdjust"_ustr)); // center
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
getProperty<sal_Int32>(getParagraph(5), u"ParaAdjust"_ustr)); // left
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testShapePageMove)
{ // Load a document with 2 pages, shape on the first page.
createSwDoc("shape-page-move.odt");
SwDoc* pDoc = getSwDoc();
SwView* pView = getSwDocShell()->GetView(); // Make sure that the 2nd page is below the 1st one.
pView->SetViewLayout(/*nColumns=*/1, /*bBookMode=*/false);
calcLayout();
// Select the shape.
selectShape(1);
// Move the shape down to the 2nd page.
SfxInt32Item aXItem(SID_ATTR_TRANSFORM_POS_X, 4000);
SfxInt32Item aYItem(SID_ATTR_TRANSFORM_POS_Y, 12000);
pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, SfxCallMode::SYNCHRON,
{ &aXItem, &aYItem });
// Check if the shape anchor was moved to the 2nd page as well. auto pShapeFormats = pDoc->GetSpzFrameFormats();
CPPUNIT_ASSERT(!pShapeFormats->empty()); auto it = pShapeFormats->begin(); auto pShapeFormat = *it; const SwPosition* pAnchor = pShapeFormat->GetAnchor().GetContentAnchor();
CPPUNIT_ASSERT(pAnchor);
// Find out the node index of the 1st para on the 2nd page.
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
SwFrame* pFirstPage = pLayout->Lower();
SwFrame* pSecondPage = pFirstPage->GetNext();
CPPUNIT_ASSERT(pSecondPage->IsLayoutFrame());
SwFrame* pBodyFrame = static_cast<SwLayoutFrame*>(pSecondPage)->GetLower();
CPPUNIT_ASSERT(pBodyFrame->IsLayoutFrame());
SwFrame* pTextFrame = static_cast<SwLayoutFrame*>(pBodyFrame)->GetLower();
CPPUNIT_ASSERT(pTextFrame->IsTextFrame());
SwNodeOffset nNodeIndex = static_cast<SwTextFrame*>(pTextFrame)->GetTextNodeFirst()->GetIndex();
// Without the accompanying fix in place, this test would have failed with "Expected: 13; // Actual: 12", i.e. the shape was anchored to the last paragraph of the 1st page, not to a // paragraph on the 2nd page.
CPPUNIT_ASSERT_EQUAL(nNodeIndex, pAnchor->GetNodeIndex());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.