4085 lines
174 KiB
C++
4085 lines
174 KiB
C++
/* -*- 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 <swmodeltestbase.hxx>
|
||
|
||
#include <boost/property_tree/json_parser.hpp>
|
||
|
||
#include <com/sun/star/awt/FontSlant.hpp>
|
||
#include <com/sun/star/awt/FontUnderline.hpp>
|
||
#include <com/sun/star/awt/FontWeight.hpp>
|
||
#include <com/sun/star/chart/XChartDocument.hpp>
|
||
#include <com/sun/star/chart2/XChartDocument.hpp>
|
||
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
|
||
#include <com/sun/star/view/XSelectionSupplier.hpp>
|
||
#include <com/sun/star/text/XTextTable.hpp>
|
||
#include <comphelper/propertysequence.hxx>
|
||
#include <comphelper/propertyvalue.hxx>
|
||
#include <comphelper/configuration.hxx>
|
||
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
|
||
#include <vcl/scheduler.hxx>
|
||
#include <vcl/settings.hxx>
|
||
#include <ndtxt.hxx>
|
||
#include <swdtflvr.hxx>
|
||
#include <wrtsh.hxx>
|
||
#include <IDocumentRedlineAccess.hxx>
|
||
#include <flyfrm.hxx>
|
||
#include <fmtanchr.hxx>
|
||
#include <UndoManager.hxx>
|
||
#include <sortedobjs.hxx>
|
||
#include <xmloff/odffields.hxx>
|
||
#include <sfx2/viewfrm.hxx>
|
||
#include <sfx2/dispatch.hxx>
|
||
#include <comphelper/lok.hxx>
|
||
#include <txtfrm.hxx>
|
||
#include <tabfrm.hxx>
|
||
#include <view.hxx>
|
||
#include <cmdid.h>
|
||
#include <AnnotationWin.hxx>
|
||
#include <PostItMgr.hxx>
|
||
#include <fmtcntnt.hxx>
|
||
#include <frameformats.hxx>
|
||
#include <shellio.hxx>
|
||
#include <editeng/fontitem.hxx>
|
||
#include <tools/json_writer.hxx>
|
||
#include <unotxdoc.hxx>
|
||
#include <IDocumentLayoutAccess.hxx>
|
||
#include <rootfrm.hxx>
|
||
#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
|
||
#include <redline.hxx>
|
||
|
||
/// 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)
|
||
{
|
||
}
|
||
|
||
protected:
|
||
AllSettings m_aSavedSettings;
|
||
};
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf139127)
|
||
{
|
||
createSwDoc("tdf139127.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// switch on "Show changes in margin" mode
|
||
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsShowChangesInMargin());
|
||
|
||
// 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());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138479)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* const pDoc = getSwDoc();
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
pWrtShell->Insert(u"Lorem"_ustr);
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, getParagraph(1)->getString());
|
||
|
||
//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, {});
|
||
|
||
// delete "r" in "Lorem"
|
||
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 3, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(u"Loem"_ustr, getParagraph(1)->getString());
|
||
|
||
// delete "oe" in "Loem"
|
||
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 2, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(u"Lm"_ustr, getParagraph(1)->getString());
|
||
|
||
// test embedded Undo in ChangesInMargin mode
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(u"Loem"_ustr, getParagraph(1)->getString());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, getParagraph(1)->getString());
|
||
|
||
// this would crash due to bad redline range
|
||
for (int i = 0; i < 5; ++i)
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// switch off "Show changes in margin" mode
|
||
dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
|
||
CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138666)
|
||
{
|
||
createSwDoc("tdf39721.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
//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());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf140982)
|
||
{
|
||
createSwDoc("tdf115815.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
//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;
|
||
else if (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);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126206)
|
||
{
|
||
createSwDoc("tdf126206.docx");
|
||
|
||
// 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));
|
||
}
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
// bold text again
|
||
xText = getParagraph(1)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 3)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
|
||
getProperty<float>(xCursor, u"CharWeight"_ustr));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447)
|
||
{
|
||
createSwDoc("tdf126206.docx");
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
// 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));
|
||
}
|
||
|
||
// remove bold formatting with change tracking
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
|
||
|
||
xText = getParagraph(1)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
|
||
getProperty<float>(xCursor, u"CharWeight"_ustr));
|
||
}
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_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));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143918)
|
||
{
|
||
createSwDoc("tdf126206.docx");
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
// 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));
|
||
}
|
||
|
||
// remove bold formatting with change tracking and after that, apply underline, too
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Underline"_ustr, {});
|
||
|
||
xText = getParagraph(1)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
|
||
getProperty<float>(xCursor, u"CharWeight"_ustr));
|
||
}
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_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));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143938)
|
||
{
|
||
createSwDoc("tdf54819.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
// 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()));
|
||
|
||
// apply italic with change tracking
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Italic"_ustr, {});
|
||
|
||
xText = getParagraph(1)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
// (first empty run is associated to the redline)
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
|
||
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_ITALIC,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
}
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
// 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));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143939)
|
||
{
|
||
createSwDoc("tdf126206.docx");
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
// 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, {});
|
||
|
||
xText = getParagraph(1)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
|
||
getProperty<float>(xCursor, u"CharWeight"_ustr));
|
||
}
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_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));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447_keep_hints)
|
||
{
|
||
createSwDoc("tdf50447.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// first paragraph (_Lorem_ /ipsum/)
|
||
|
||
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(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));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u" "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
}
|
||
|
||
// second paragraph (_dolor_ sit /amet/.)
|
||
|
||
xText = getParagraph(2)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"dolor"_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));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u" sit "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"amet"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
|
||
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()));
|
||
|
||
// modify character formatting of the all the text
|
||
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SuperScript"_ustr, {});
|
||
|
||
// 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());
|
||
|
||
// reject tracked changes
|
||
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
// all hints and text portions between them got back the original 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"_ustr, xCursor->getString());
|
||
// This was NONE
|
||
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));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u" "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
// This was NONE
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
}
|
||
|
||
// second paragraph (_dolor_ sit /amet/.)
|
||
|
||
xText = getParagraph(2)->getText();
|
||
CPPUNIT_ASSERT(xText.is());
|
||
{
|
||
auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"dolor"_ustr, xCursor->getString());
|
||
// This was NONE
|
||
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));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u" sit "_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
|
||
xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
|
||
CPPUNIT_ASSERT(xCursor.is());
|
||
CPPUNIT_ASSERT_EQUAL(u"amet"_ustr, xCursor->getString());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
|
||
getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
|
||
// This was NONE
|
||
CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
|
||
getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144272)
|
||
{
|
||
createSwDoc("tdf50447.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
// 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
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
|
||
// modify with track changes: Standard and Heading 2
|
||
|
||
uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
|
||
{ "Style", uno::Any(u"Standard"_ustr) },
|
||
{ "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
|
||
});
|
||
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
aPropertyValues = comphelper::InitPropertySequence({
|
||
{ "Style", uno::Any(u"Heading 2"_ustr) },
|
||
{ "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
|
||
});
|
||
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
|
||
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
|
||
// reject tracked changes
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
// 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));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf101873)
|
||
{
|
||
createSwDoc();
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
// Insert some content.
|
||
pWrtShell->Insert(u"something"_ustr);
|
||
|
||
// Search for something which does not exist, twice.
|
||
uno::Sequence<beans::PropertyValue> aFirst(comphelper::InitPropertySequence({
|
||
{ "SearchItem.SearchString", uno::Any(u"fig"_ustr) },
|
||
{ "SearchItem.Backward", uno::Any(false) },
|
||
}));
|
||
dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aFirst);
|
||
dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aFirst);
|
||
|
||
uno::Sequence<beans::PropertyValue> aSecond(comphelper::InitPropertySequence({
|
||
{ "SearchItem.SearchString", uno::Any(u"something"_ustr) },
|
||
{ "SearchItem.Backward", uno::Any(false) },
|
||
}));
|
||
dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, 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(u"something"_ustr, pShellCursor->GetText());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTextFormFieldInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// 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());
|
||
|
||
// Undo insertion
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
xPara.set(getParagraph(1));
|
||
CPPUNIT_ASSERT(xPara->getString().isEmpty());
|
||
|
||
// Redo insertion
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
|
||
xPara.set(getParagraph(1));
|
||
CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testCheckboxFormFieldInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// 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());
|
||
|
||
// Undo insertion
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Redo insertion
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
|
||
aIter = pMarkAccess->getAllMarksBegin();
|
||
CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
|
||
pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMCHECKBOX, pFieldmark->GetFieldname());
|
||
|
||
// tdf#147008 this would crash
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->StartOfSection(false);
|
||
pWrtShell->SplitNode();
|
||
CPPUNIT_ASSERT_EQUAL(pFieldmark->GetMarkPos().GetNodeIndex(),
|
||
pFieldmark->GetOtherMarkPos().GetNodeIndex());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(pFieldmark->GetMarkPos().GetContentIndex() + 1),
|
||
pFieldmark->GetOtherMarkPos().GetContentIndex());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDropDownFormFieldInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// 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()));
|
||
|
||
// Undo insertion
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Redo insertion
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
|
||
aIter = pMarkAccess->getAllMarksBegin();
|
||
CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
|
||
pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMDROPDOWN, pFieldmark->GetFieldname());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testMixedFormFieldInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Insert fields
|
||
dispatchCommand(mxComponent, u".uno:TextFormField"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:CheckBoxFormField"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:DropDownFormField"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
|
||
|
||
// Undo insertion
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Redo insertion
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147723)
|
||
{
|
||
createSwDoc("tdf147723.docx");
|
||
SwDoc* const pDoc = getSwDoc();
|
||
|
||
IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
|
||
|
||
// 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());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147006)
|
||
{
|
||
createSwDoc("tdf147006.rtf");
|
||
SwDoc* const pDoc = getSwDoc();
|
||
|
||
IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getFieldmarksCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
// this crashed
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
|
||
CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDocxAttributeTableExport)
|
||
{
|
||
createSwDoc("floating-table-position.docx");
|
||
|
||
// get the table frame, set new values and dismiss the references
|
||
{
|
||
uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
|
||
|
||
// change the properties
|
||
// 8133 -> 8000
|
||
xShape->setPropertyValue(u"VertOrientPosition"_ustr,
|
||
uno::Any(static_cast<sal_Int32>(8000)));
|
||
// 5964 -> 5000
|
||
xShape->setPropertyValue(u"HoriOrientPosition"_ustr,
|
||
uno::Any(static_cast<sal_Int32>(5000)));
|
||
// 0 (frame) -> 8 (page print area)
|
||
xShape->setPropertyValue(u"VertOrientRelation"_ustr, uno::Any(static_cast<sal_Int16>(8)));
|
||
// 8 (page print area) -> 0 (frame)
|
||
xShape->setPropertyValue(u"HoriOrientRelation"_ustr, uno::Any(static_cast<sal_Int16>(0)));
|
||
}
|
||
// save it to docx
|
||
saveAndReload(u"Office Open XML Text"_ustr);
|
||
|
||
uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
|
||
|
||
// test the new values
|
||
sal_Int32 nValue = getProperty<sal_Int32>(xShape, u"VertOrientPosition"_ustr);
|
||
CPPUNIT_ASSERT(sal_Int32(7999) <= nValue);
|
||
CPPUNIT_ASSERT(nValue <= sal_Int32(8001));
|
||
nValue = getProperty<sal_Int32>(xShape, u"HoriOrientPosition"_ustr);
|
||
CPPUNIT_ASSERT(sal_Int32(4999) <= nValue);
|
||
CPPUNIT_ASSERT(nValue <= sal_Int32(5001));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(8), getProperty<sal_Int16>(xShape, u"VertOrientRelation"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape, u"HoriOrientRelation"_ustr));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118699_redline_numbering)
|
||
{
|
||
createSwDoc("tdf118699.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(true);
|
||
|
||
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());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125881_redline_list_level)
|
||
{
|
||
createSwDoc("tdf125881.docx");
|
||
|
||
uno::Reference<beans::XPropertySet> xProps(getParagraph(8), uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT_MESSAGE("deleted paragraph: erroneous numbering",
|
||
!xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
|
||
|
||
// 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));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125916_redline_restart_numbering)
|
||
{
|
||
createSwDoc("tdf125916.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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);
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(true);
|
||
|
||
// check unnecessary numbering
|
||
uno::Reference<beans::XPropertySet> xProps(getParagraph(3), uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
|
||
!xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310)
|
||
{
|
||
createSwDoc("tdf125310.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(1, 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());
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"redlines should be visible",
|
||
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
// paragraph join
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
pWrtShell->EndPara(/*bSelect=*/true);
|
||
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
|
||
|
||
// copied paragraph style
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
|
||
// without copying the page break
|
||
CPPUNIT_ASSERT_EQUAL(1, getPages());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310b)
|
||
{
|
||
createSwDoc("tdf125310b.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
|
||
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(SwUiWriterTest5, testTdf120336)
|
||
{
|
||
createSwDoc("tdf120336.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(2, getPages());
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(true);
|
||
|
||
// keep page break, as without redlining
|
||
CPPUNIT_ASSERT_EQUAL(2, getPages());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf106843)
|
||
{
|
||
createSwDoc("tdf106843.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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);
|
||
|
||
#if !defined(MACOSX)
|
||
// Calc the left edge of the as-char frame.
|
||
SwRootFrame* pLayout = pWrtShell->GetLayout();
|
||
SwFrame* pPage = pLayout->GetLower();
|
||
SwFrame* pBody = pPage->GetLower();
|
||
SwFrame* pTextFrame = pBody->GetLower();
|
||
CPPUNIT_ASSERT(pTextFrame->GetDrawObjs());
|
||
const SwSortedObjs& rAnchored = *pTextFrame->GetDrawObjs();
|
||
CPPUNIT_ASSERT_GREATER(static_cast<size_t>(0), rAnchored.size());
|
||
SwAnchoredObject* pObject = rAnchored[0];
|
||
tools::Long nFrameLeft = pObject->GetObjRect().Left();
|
||
tools::Long nFrameTop = pObject->GetObjRect().Top();
|
||
|
||
// 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 (const auto& 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));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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_TEST_FIXTURE(SwUiWriterTest5, testTdf120338)
|
||
{
|
||
createSwDoc("tdf120338.docx");
|
||
|
||
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(u""_ustr,
|
||
getProperty<OUString>(getParagraph(7), u"NumberingStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"WWNum2"_ustr,
|
||
getProperty<OUString>(getParagraph(8), u"NumberingStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
|
||
getProperty<OUString>(getParagraph(10), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
|
||
getProperty<OUString>(getParagraph(11), u"ParaStyleName"_ustr));
|
||
|
||
// reject tracked paragraph adjustments
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
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
|
||
|
||
// tdf#126245 revert numbering changes
|
||
CPPUNIT_ASSERT_EQUAL(u"WWNum2"_ustr,
|
||
getProperty<OUString>(getParagraph(7), u"NumberingStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u""_ustr,
|
||
getProperty<OUString>(getParagraph(8), u"NumberingStyleName"_ustr));
|
||
|
||
// tdf#126243 revert paragraph styles
|
||
CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
|
||
getProperty<OUString>(getParagraph(10), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 3"_ustr,
|
||
getProperty<OUString>(getParagraph(11), u"ParaStyleName"_ustr));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120338_multiple_paragraph_join)
|
||
{
|
||
createSwDoc("redline-para-join.docx");
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
|
||
|
||
// reject tracked paragraph styles
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
|
||
getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
|
||
CPPUNIT_ASSERT_EQUAL(u"Heading 3"_ustr,
|
||
getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
|
||
}
|
||
|
||
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());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldInsertion)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Insert a date form field
|
||
dispatchCommand(mxComponent, u".uno:DatePickerFormField"_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_FORMDATE, pFieldmark->GetFieldname());
|
||
|
||
// The date form field has the placeholder text in it
|
||
uno::Reference<text::XTextRange> xPara = getParagraph(1);
|
||
CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
|
||
|
||
// Undo insertion
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Redo insertion
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
aIter = pMarkAccess->getAllMarksBegin();
|
||
CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
|
||
pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldContentOperations)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Insert a date form field
|
||
dispatchCommand(mxComponent, u".uno:DatePickerFormField"_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::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
||
|
||
// Check the default content added by insertion
|
||
uno::Reference<text::XTextRange> xPara = getParagraph(1);
|
||
CPPUNIT_ASSERT_EQUAL(vEnSpaces, pFieldmark->GetContent());
|
||
|
||
// Set content to empty string
|
||
pFieldmark->ReplaceContent(u""_ustr);
|
||
CPPUNIT_ASSERT_EQUAL(u""_ustr, pFieldmark->GetContent());
|
||
|
||
// Replace empty string with a valid content
|
||
pFieldmark->ReplaceContent(u"2019-10-23"_ustr);
|
||
CPPUNIT_ASSERT_EQUAL(u"2019-10-23"_ustr, pFieldmark->GetContent());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateHandling)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Insert a date form field
|
||
dispatchCommand(mxComponent, u".uno:DatePickerFormField"_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::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
||
|
||
// The default content is not a valid date
|
||
uno::Reference<text::XTextRange> xPara = getParagraph(1);
|
||
CPPUNIT_ASSERT_EQUAL(vEnSpaces, pFieldmark->GetContent());
|
||
std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
|
||
CPPUNIT_ASSERT(!aResult.first);
|
||
|
||
// Check empty string
|
||
pFieldmark->ReplaceContent(u""_ustr);
|
||
aResult = pFieldmark->GetCurrentDate();
|
||
CPPUNIT_ASSERT(!aResult.first);
|
||
|
||
// Check valid date
|
||
// Set date format first
|
||
sw::mark::Fieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
|
||
(*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= u"YYYY/MM/DD"_ustr;
|
||
(*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= u"en-US"_ustr;
|
||
|
||
// Set date value and check whether the content is formatted correctly
|
||
pFieldmark->SetCurrentDate(48000.0);
|
||
aResult = pFieldmark->GetCurrentDate();
|
||
CPPUNIT_ASSERT(aResult.first);
|
||
CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
|
||
CPPUNIT_ASSERT_EQUAL(u"2031/06/01"_ustr, pFieldmark->GetContent());
|
||
// Current date param contains date in a "standard format"
|
||
OUString sCurrentDate;
|
||
auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
|
||
if (pResult != pParameters->end())
|
||
{
|
||
pResult->second >>= sCurrentDate;
|
||
}
|
||
CPPUNIT_ASSERT_EQUAL(u"2031-06-01"_ustr, sCurrentDate);
|
||
}
|
||
|
||
#if !defined(_WIN32)
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateInvalidation)
|
||
{
|
||
createSwDoc();
|
||
SwDoc* pDoc = getSwDoc();
|
||
IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
|
||
CPPUNIT_ASSERT(pMarkAccess);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
|
||
|
||
// Insert a date form field
|
||
dispatchCommand(mxComponent, u".uno:DatePickerFormField"_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::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
|
||
CPPUNIT_ASSERT(pFieldmark);
|
||
CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
|
||
|
||
// Set a date first
|
||
sw::mark::Fieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
|
||
pFieldmark->SetCurrentDate(48000.0);
|
||
std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
|
||
CPPUNIT_ASSERT(aResult.first);
|
||
CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
|
||
|
||
// Do the layouting to trigger invalidation
|
||
// Since we have the current date consistent with the field content
|
||
// This invalidation won't change anything
|
||
calcLayout();
|
||
Scheduler::ProcessEventsToIdle();
|
||
|
||
// Current date param contains date in a "standard format"
|
||
OUString sCurrentDate;
|
||
auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
|
||
if (pResult != pParameters->end())
|
||
{
|
||
pResult->second >>= sCurrentDate;
|
||
}
|
||
// We have the current date parameter set
|
||
CPPUNIT_ASSERT_EQUAL(u"2031-06-01"_ustr, sCurrentDate);
|
||
|
||
// Now change the content of the field
|
||
pFieldmark->ReplaceContent(u"[select date]"_ustr);
|
||
// Do the layouting to trigger invalidation
|
||
calcLayout();
|
||
Scheduler::ProcessEventsToIdle();
|
||
|
||
sCurrentDate.clear();
|
||
pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
|
||
if (pResult != pParameters->end())
|
||
{
|
||
pResult->second >>= sCurrentDate;
|
||
}
|
||
CPPUNIT_ASSERT_EQUAL(u""_ustr, sCurrentDate);
|
||
}
|
||
#endif
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testOleSaveWhileEdit)
|
||
{
|
||
// Enable LOK mode, otherwise OCommonEmbeddedObject::SwitchStateTo_Impl() will throw when it
|
||
// finds out that the test runs headless.
|
||
comphelper::LibreOfficeKit::setActive();
|
||
|
||
// Load a document with a Draw doc in it.
|
||
createSwDoc("ole-save-while-edit.odt");
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
|
||
selectShape(1);
|
||
|
||
// Start editing the OLE object.
|
||
pWrtShell->LaunchOLEObj();
|
||
|
||
// Save the document without existing the OLE edit.
|
||
uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
|
||
xStorable->storeToURL(maTempFile.GetURL(), {});
|
||
|
||
uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
|
||
= packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
|
||
maTempFile.GetURL());
|
||
// Without the accompanying fix in place, this test would have failed: the OLE object lost its
|
||
// replacement on save if the edit was active while saving.
|
||
CPPUNIT_ASSERT(xNameAccess->hasByName(u"ObjectReplacements/Object 1"_ustr));
|
||
|
||
// Dispose the document while LOK is still active to avoid leaks.
|
||
mxComponent->dispose();
|
||
mxComponent.clear();
|
||
comphelper::LibreOfficeKit::setActive(false);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf105330)
|
||
{
|
||
createSwDoc("tdf105330.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
SwView* pView = getSwDocShell()->GetView();
|
||
SfxUInt16Item aRows(SID_ATTR_TABLE_ROW, 1);
|
||
SfxUInt16Item aColumns(SID_ATTR_TABLE_COLUMN, 1);
|
||
pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_TABLE, SfxCallMode::SYNCHRON,
|
||
{ &aRows, &aColumns });
|
||
|
||
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
||
rUndoManager.Undo();
|
||
|
||
// Without the accompanying fix in place, height was only 1 twips (practically invisible).
|
||
// Require at least 12pt height (font size under the cursor), in twips.
|
||
CPPUNIT_ASSERT_GREATEREQUAL(
|
||
static_cast<tools::Long>(240),
|
||
pWrtShell->GetVisibleCursor()->GetTextCursor().GetSize().getHeight());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118311)
|
||
{
|
||
createSwDoc("tdf118311.fodt");
|
||
|
||
// Jump to the first cell, selecting its content
|
||
uno::Sequence<beans::PropertyValue> aSearch(comphelper::InitPropertySequence({
|
||
{ "SearchItem.SearchString", uno::Any(u"a"_ustr) },
|
||
{ "SearchItem.Backward", uno::Any(false) },
|
||
}));
|
||
dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aSearch);
|
||
|
||
// .uno:Cut doesn't remove the table, only the selected content of the first cell
|
||
dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
|
||
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// .uno:SelectAll selects the whole table, and UNO command Cut cuts it
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletion)
|
||
{
|
||
// load a 1-row table, and delete the row with enabled change tracking:
|
||
// now the row is not deleted silently, but keeps the deleted cell contents,
|
||
// and only accepting all of them will result the deletion of the table row.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
// This was deleted without change tracking
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept the deletion of the content of the first cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept last redline
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row (and the 1-row table) was deleted finally
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
|
||
// Undo, and repeat the previous test, but only with deletion of the text content of the cells
|
||
// (HasTextChangesOnly property will be removed by Undo)
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// table exists again
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
dispatchCommand(mxComponent, u".uno:SelectRow"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
|
||
// Table row still exists
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept the deletion of the content of the first cell
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept last redline
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row (and the 1-row table) still exists
|
||
// (HasTextChangesOnly property wasn't set for table row deletion)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// Undo, and delete the row without change tracking
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// table exists again
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// disable change tracking
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
|
||
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
// delete table row without change tracking
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
// the table (row) was deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150976)
|
||
{
|
||
// load a 1-row table, and delete the row with track changes
|
||
createSwDoc("select-row.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// nested table in the last cell
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// deleted text content
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
// This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
|
||
|
||
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
||
SwFrame* pPage = pLayout->Lower();
|
||
SwFrame* pBody = pPage->GetLower();
|
||
SwFrame* pTable = pBody->GetLower();
|
||
CPPUNIT_ASSERT(pTable->IsTabFrame());
|
||
|
||
SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
|
||
|
||
// This was false (not deleted row)
|
||
CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
|
||
|
||
// accept all tracked changes
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
|
||
// tdf#151658 This was 1: not deleted table row (and table)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf151657)
|
||
{
|
||
// load a 1-row table, and delete the row with hidden track changes
|
||
createSwDoc("select-row.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// turn on red-lining and hide changes
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
|
||
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
|
||
!IDocumentRedlineAccess::IsShowChanges(
|
||
pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// nested table in the last cell
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// deleted text content
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
// This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
|
||
|
||
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
||
SwFrame* pPage = pLayout->Lower();
|
||
SwFrame* pBody = pPage->GetLower();
|
||
SwFrame* pTable = pBody->GetLower();
|
||
CPPUNIT_ASSERT(pTable->IsTabFrame());
|
||
|
||
SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
|
||
|
||
// This was false (not deleted row)
|
||
CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
|
||
|
||
// accept all tracked changes
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
|
||
// tdf#151658 This was 1: not deleted table row (and table)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testSelectRowWithNestedTable)
|
||
{
|
||
// load a 1-row table, and select the row
|
||
createSwDoc("select-row.fodt");
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// nested table in the last cell
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
|
||
|
||
// select table row
|
||
dispatchCommand(mxComponent, u".uno:EntireRow"_ustr, {});
|
||
// convert selected text content to uppercase
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[1]/txt",
|
||
u"NESTED-A1");
|
||
// This was "a1" (bad selection of the table row)
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[1]/txt[1]", u"A1");
|
||
// This was "nested-b1" (bad selection of the table row)
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[2]/txt",
|
||
u"NESTED-B1");
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_row)
|
||
{
|
||
// load a 2-row table, and select row 2 by clicking before it
|
||
createSwDoc("select-column.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
||
SwFrame* pPage = pLayout->Lower();
|
||
SwFrame* pBody = pPage->GetLower();
|
||
SwFrame* pTable = pBody->GetLower()->GetNext();
|
||
SwFrame* pRow2 = pTable->GetLower()->GetNext();
|
||
const SwRect& rRow2Rect = pRow2->getFrameArea();
|
||
Point ptRow(rRow2Rect.Left(), rRow2Rect.Top() + rRow2Rect.Height() / 2);
|
||
|
||
pWrtShell->SelectTableRowCol(ptRow);
|
||
|
||
// convert selected text content to uppercase
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
|
||
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", u"a1");
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", u"b1");
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
|
||
u"NESTED-A1");
|
||
// This was "a2" (bad selection of the table row)
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", u"A2");
|
||
// This was "nested-b1" (bad selection of the table row)
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
|
||
u"NESTED-B1");
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_column)
|
||
{
|
||
// load a 2-row table, and select column B by clicking before them
|
||
createSwDoc("select-column.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
// select table column by using the middle point of the top border of column B
|
||
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
|
||
SwFrame* pPage = pLayout->Lower();
|
||
SwFrame* pBody = pPage->GetLower();
|
||
SwFrame* pTable = pBody->GetLower()->GetNext();
|
||
SwFrame* pRow1 = pTable->GetLower();
|
||
SwFrame* pCellB1 = pRow1->GetLower()->GetNext();
|
||
const SwRect& rCellB1Rect = pCellB1->getFrameArea();
|
||
Point ptColumn(rCellB1Rect.Left() + rCellB1Rect.Width() / 2, rCellB1Rect.Top() - 5);
|
||
|
||
pWrtShell->SelectTableRowCol(ptColumn);
|
||
|
||
// convert selected text content to uppercase
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
|
||
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", u"a1");
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", u"a2");
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
|
||
u"NESTED-A1");
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
|
||
u"NESTED-B1");
|
||
// This was "b1" (bad selection of the table column)
|
||
assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", u"B1");
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithExport)
|
||
{
|
||
// load a 1-row table, and delete the row with enabled change tracking:
|
||
// now the row is not deleted silently, but keeps the deleted cell contents,
|
||
// and only accepting all of them will result the deletion of the table row.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
// Deleted text content with change tracking,
|
||
// but not table deletion
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// Save it and load it back.
|
||
saveAndReload(u"writer8"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// accept the deletion of the content of the first cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept last redline
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row (and the 1-row table) was deleted finally
|
||
// (working export/import of HasTextChangesOnly)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithDOCXExport)
|
||
{
|
||
// load a 1-row table, and delete the row with enabled change tracking:
|
||
// now the row is not deleted silently, but keeps the deleted cell contents,
|
||
// and only accepting all of them will result the deletion of the table row.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
// Deleted text content with change tracking,
|
||
// but not table deletion
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// Save it to a DOCX and load it back.
|
||
// Exporting change tracking of the row wasn't supported.
|
||
// Also Manage Changes for the import.
|
||
saveAndReload(u"Office Open XML Text"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// accept the deletion of the content of the first cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept last redline
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row (and the 1-row table) was deleted finally
|
||
// (working export/import of HasTextChangesOnly)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableInsertion)
|
||
{
|
||
// load a 3-row table inserted with change tracking by text to table conversion
|
||
createSwDoc("TC-table-converttotable.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// check table count (1)
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// reject the text insertions of the table cells (also reject deletion of the tabulated
|
||
// text source of the table, which was used by the tracked text to table conversion)
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
|
||
while (pEditShell->GetRedlineCount())
|
||
pEditShell->RejectRedline(0);
|
||
|
||
// rejecting all text insertions must undo the table insertion
|
||
// This was 1 (remaining empty table after rejecting all table text insertions)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableMoveToFrame)
|
||
{
|
||
// load a table with tracked drag & drop: Table1 is the moveFrom,
|
||
// Table2 is the moveTo - and framed - table
|
||
createSwDoc("TC-table-DnD-move.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
uno::Reference<container::XNameAccess> xTableNames = xTextTablesSupplier->getTextTables();
|
||
// check table count (2)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
|
||
|
||
// accept tracked table moving, remaining table is Table2
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(true);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
CPPUNIT_ASSERT(xTableNames->hasByName(u"Table2"_ustr));
|
||
CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table1"_ustr));
|
||
|
||
// Undo and reject tracked table moving, remaining table is Table1
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
rIDRA.AcceptAllRedline(false);
|
||
// This was 2 (not deleted Table2 – framed)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
CPPUNIT_ASSERT(xTableNames->hasByName(u"Table1"_ustr));
|
||
CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table2"_ustr));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_AcceptInsertRedlineCutWithDeletion)
|
||
{
|
||
createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
|
||
|
||
// Accept the insert that splitted into 3 parts .. accept all 3 of them
|
||
pEditShell->AcceptRedline(6);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
|
||
// The middle had a delete too, rejecting the delete will remove that redline too.
|
||
pEditShell->RejectRedline(6);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());
|
||
|
||
// Accept insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
|
||
// It will accept only 2 parts, that is not separated. It leave the deletion.
|
||
pEditShell->AcceptRedline(0);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(5), pEditShell->GetRedlineCount());
|
||
// Accepting the delete will remove that redline.
|
||
// (only that one, as its other half is separated from it with an insert)
|
||
pEditShell->AcceptRedline(0);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_RejectInsertRedlineCutWithDeletion)
|
||
{
|
||
createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
|
||
|
||
// Reject the insert that splitted into 3 parts. reject all 3 of them
|
||
// it even remove the deletion, that was on the 2. insert...
|
||
pEditShell->RejectRedline(6);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());
|
||
|
||
// Reject insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
|
||
// It will reject only 2 parts, that is not separated. It remove the deletion.
|
||
pEditShell->RejectRedline(0);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157663_RedlineMoveRecognition)
|
||
{
|
||
createSwDoc("tdf157663_redlineMove.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());
|
||
|
||
// Check if move redlines are recognised as moved, during import
|
||
SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
|
||
bool vMovedRedlines[23]
|
||
= { false, true, true, true, true, true, true, true, true, true, true, true,
|
||
true, false, true, false, true, false, false, false, false, false, false };
|
||
// 20. and 22. redline is a delete/insert redline with the same text "three".
|
||
// they are not recognised as a move, because 22. redline is not a whole paragraph.
|
||
// Note: delete/insert redlines that are just a part of a paragraph decided to be part of
|
||
// a move, only if it is at least 6 character long and contain a space "" character.
|
||
for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
|
||
{
|
||
CPPUNIT_ASSERT_EQUAL(vMovedRedlines[i], rTable[i]->GetMoved() > 0);
|
||
}
|
||
|
||
// Check if accepting move redlines accept its pairs as well.
|
||
pEditShell->AcceptRedline(3); // "9 3/4"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->AcceptRedline(1); // "sqrt(10)"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(17), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->AcceptRedline(1); // "four"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(13), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->AcceptRedline(3); // "six"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(11), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->AcceptRedline(4); // "sqrt(17)"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
|
||
|
||
// Undo back all the 5 redline accepts
|
||
for (int i = 0; i < 5; i++)
|
||
{
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
}
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());
|
||
|
||
// Check if rejecting redlines reject its pairs as well.
|
||
pEditShell->RejectRedline(3); // "9 3/4"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(20), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->RejectRedline(2); // "sqrt(10)"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(18), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->RejectRedline(2); // "four"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->RejectRedline(2); // "sqrt(17)"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
|
||
|
||
pEditShell->RejectRedline(2); // "six"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());
|
||
|
||
const sal_uInt32 nZeroID = 0;
|
||
|
||
// Check if there are no more move redlines
|
||
for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
|
||
{
|
||
CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[i]->GetMoved());
|
||
}
|
||
|
||
// Check if moving paragraphs generate redline moves
|
||
|
||
// move a paragraph that has delete redlines inside of it
|
||
// original text: "Seve ent teen"
|
||
// deleted texts: "e " and " t"
|
||
// moved new text: "Seventeen"
|
||
pEditShell->GotoRedline(6, true);
|
||
pEditShell->UpdateCursor();
|
||
pEditShell->MoveParagraph(SwNodeOffset(1));
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());
|
||
|
||
sal_uInt32 nMovedID = rTable[6]->GetMoved();
|
||
//moved text from here
|
||
CPPUNIT_ASSERT(nMovedID > 0); // "Sev"
|
||
CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[7]->GetMoved()); // "e " deleted text not moved
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[8]->GetMoved()); // "ent"
|
||
CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[9]->GetMoved()); // " t"
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[10]->GetMoved()); // "teen"
|
||
// moved text to here
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[11]->GetMoved()); // "Seventeen"
|
||
|
||
// move paragraph that has an insert redline inside of it
|
||
// original text: "Eigen"
|
||
// inserted text: "hte"
|
||
// moved new text :"Eighteen"
|
||
pEditShell->GotoRedline(12, true);
|
||
pEditShell->UpdateCursor();
|
||
pEditShell->MoveParagraph(SwNodeOffset(-2));
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
|
||
|
||
nMovedID = rTable[12]->GetMoved();
|
||
// moved text to here
|
||
CPPUNIT_ASSERT(nMovedID > 0); // "Eighteen"
|
||
// moved text from here
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[13]->GetMoved()); // "Eigen"
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[14]->GetMoved()); // "hte"
|
||
CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[15]->GetMoved()); // "en"
|
||
|
||
//Check if accept work on both side of the redlines made by manual move paragraphs
|
||
pEditShell->AcceptRedline(13); // "Eigen"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(11); // "Seventeen"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
|
||
|
||
//undo back the last 2 accept
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
|
||
|
||
//Check if reject work on both side of the redlines made by manual move paragraphs
|
||
pEditShell->RejectRedline(13); // "Eigen"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());
|
||
pEditShell->RejectRedline(11); // "Seventeen"
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143215)
|
||
{
|
||
// load a table with tracked insertion of an empty row
|
||
createSwDoc("TC-table-rowadd.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
// check table count
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// reject insertion of the empty table row
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(false);
|
||
// This was 4 (remained empty row)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
|
||
|
||
// Undo and accept insertion of the table row
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
rIDRA.AcceptAllRedline(true);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// delete it with change tracking, and accept the deletion
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
rIDRA.AcceptAllRedline(true);
|
||
// This was 4 (remained empty row)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
|
||
{
|
||
// load a table with tracked insertion of an empty row
|
||
createSwDoc("TC-table-rowadd.docx");
|
||
|
||
// check table count
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// select the second row (tracked table row insertion)
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
|
||
// delete it, and accept all tracked changes
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
// This was 4 (it was not possible to delete only the tracked row insertions)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
|
||
|
||
// insert a new table row with track changes
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// select and delete it
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
// This was 4 (it was not possible to delete own tracked row insertions)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666_regression)
|
||
{
|
||
// load a table with tracked insertion of an empty row
|
||
createSwDoc("TC-table-rowadd.docx");
|
||
|
||
// check table count
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// select the second row (tracked table row insertion)
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
|
||
// insert a new table row with track changes
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
|
||
// This was 4 (the inserted table row wasn't tracked)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
|
||
{
|
||
// load a table with an empty row, and an empty line before the table
|
||
// (to allow the easy selection of the full text with the table)
|
||
createSwDoc("tdf144748.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
// there is a table in the text
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// delete full text with the table and check Undo
|
||
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
// this crashed LibreOffice
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// redo and check redline usage
|
||
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
// This was 2 (bad extra redline for the empty row of the deleted table)
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
|
||
// accept deletion of the text, including the table with the empty row
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(true);
|
||
|
||
// no table left in the text
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180)
|
||
{
|
||
// load a tracked table insertion (single redline)
|
||
createSwDoc("tdf147180.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
// there is a table in the text
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// insert a character in the first cell with change tracking
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Insert(u"x"_ustr);
|
||
|
||
// reject all the changes, including table insertion
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(/*bAccept=*/false);
|
||
|
||
// no table left in the text
|
||
|
||
// This was 1 (lost tracking of the table after modifying its text content)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows)
|
||
{
|
||
// load a tracked table insertion (single redline) with empty rows
|
||
createSwDoc("tdf150824.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
// there is a table in the text
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// insert a character in the first cell with change tracking
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Insert(u"x"_ustr);
|
||
|
||
// reject all the changes, including table insertion
|
||
|
||
IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
|
||
rIDRA.AcceptAllRedline(/*bAccept=*/false);
|
||
|
||
// no table left in the text
|
||
|
||
// This was 1 (lost tracking of the empty rows after modifying table text content)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletion)
|
||
{
|
||
// load a table, and delete the first column with enabled change tracking:
|
||
// now the column is not deleted silently, but keeps the deleted cell content,
|
||
// and only accepting it will result the deletion of the table column.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// This was 1 (deleted cell without change tracking)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// accept the deletion
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// deleted column
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
|
||
|
||
// Undo, and repeat the previous test, but only with deletion of the text content of the cells
|
||
// (HasTextChangesOnly property will be removed by Undo)
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// first column exists again
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// delete table column with enabled change tracking
|
||
dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
|
||
// Table column still exists
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// accept the deletion of the content of the first cell
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table column was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// Undo, and delete the column without change tracking
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// table exists again
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// disable change tracking
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
|
||
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
// delete table column without change tracking
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// the table column was deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156474)
|
||
{
|
||
// load a table, and insert a column with change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
|
||
// there is a table in the text with two columns
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
|
||
|
||
// insert table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});
|
||
|
||
// 3 columns
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
|
||
|
||
// accept tracked changes: remove HasTextChangesOnly = false of the inserted cells
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
// still 3 columns
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
|
||
|
||
// delete the text content (dummy character of the previous text change) of the newly
|
||
// inserted cell, and accept tracked changes
|
||
SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
// This was 2 columns (not removed HasTextChangesOnly = false resulted column deletion
|
||
// instead of deleting only content of the cell)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, tdf156475)
|
||
{
|
||
// load a table, and insert a row without change tracking,
|
||
// and delete the first column with the empty cell in the second row with change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// turn off red-lining and show changes
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
|
||
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"redlines should be visible",
|
||
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
// insert table row
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 2);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 2);
|
||
|
||
// turn on red-lining
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
|
||
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// go down to the empty cell
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
|
||
// Without the fix in place, this couldn't work
|
||
dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 1);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 1);
|
||
|
||
// test Undo/Redo
|
||
for (sal_Int32 i = 0; i < 4; ++i)
|
||
{
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
}
|
||
|
||
for (sal_Int32 i = 0; i < 4; ++i)
|
||
{
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
}
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155747)
|
||
{
|
||
// load a table, and delete the first column with enabled change tracking:
|
||
// now the column is not deleted silently, but keeps the deleted cell content,
|
||
// and only accepting it will result the deletion of the table column.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// select table
|
||
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
|
||
|
||
// Without the fix in place, this test would have crashed here
|
||
dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
|
||
|
||
// check removed column
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156544)
|
||
{
|
||
// load a table, and insert a column without change tracking,
|
||
// and delete the first column with the empty cell in the second row with change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// turn off red-lining and show changes
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be off",
|
||
!pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"redlines should be visible",
|
||
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
// insert table column without change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 3);
|
||
|
||
// turn on red-lining
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
|
||
| RedlineFlags::ShowInsert);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
|
||
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
|
||
// go to the empty column
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
|
||
// This was 2 (deleted column)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
|
||
|
||
// accept the deletion of the empty column
|
||
dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// test Undo/Redo
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
|
||
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156487)
|
||
{
|
||
// load a table, and delete a column in Hide Changes mode
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// turn on red-lining and hide changes
|
||
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()));
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// Dump the rendering of the first page as an XML file.
|
||
SwDocShell* pShell = getSwDocShell();
|
||
std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
|
||
MetafileXmlDump dumper;
|
||
xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
|
||
CPPUNIT_ASSERT(pXmlDoc);
|
||
|
||
// This would be 2 without hiding the first cell
|
||
assertXPath(pXmlDoc, "/metafile/push/push/push/textarray/text", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
|
||
{
|
||
// load a table, and delete the first column with enabled change tracking:
|
||
// now the column is not deleted silently, but keeps the deleted cell content,
|
||
// and only accepting it will result the deletion of the table column.
|
||
createSwDoc("tdf149498.docx");
|
||
|
||
// select table, copy, paste and Undo
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
|
||
|
||
// this would crash due to bookmark over cell boundary
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150673_RedlineTableColumnDeletionWithExport)
|
||
{
|
||
// load a table, and delete the first column with enabled change tracking:
|
||
// now the column is not deleted silently, but keeps the deleted cell contents,
|
||
// and only accepting all of them will result the deletion of the table column.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// Deleted text content with change tracking,
|
||
// but not table deletion
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// Save it and load it back.
|
||
saveAndReload(u"writer8"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// accept the deletion of the content of the first cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// first table column was deleted finally
|
||
// (working export/import of HasTextChangesOnly)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
|
||
|
||
// check removing HasTextChangesOnly at acceptance of the deletion
|
||
|
||
// Undo, and delete the column without change tracking
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// table column exists again
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// reject deletion, setting HasTextChangesOnly to TRUE
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->RejectRedline(0);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
|
||
|
||
// delete table column with enabled change tracking
|
||
dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
|
||
// Table column still exists
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// reject the deletion of the content of the first cell
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table column is still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletionWithDOCXExport)
|
||
{
|
||
// load a 1-row table, and delete the first column with enabled change tracking:
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// delete first table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
|
||
|
||
// Deleted text content with change tracking,
|
||
// but not table deletion
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
|
||
// Save it to a DOCX and load it back.
|
||
// Exporting change tracking of the cell wasn't supported.
|
||
// Also Manage Changes for the import.
|
||
saveAndReload(u"Office Open XML Text"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// accept the deletion of the content of the first cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table column was deleted
|
||
// (working export/import of HasTextChangesOnly of table cells)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155341_RedlineTableColumnInsertionWithExport)
|
||
{
|
||
// load a table, and insert a new column with enabled change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// insert table column with enabled change tracking
|
||
// (HasTextChangesOnly property of the cell will be false)
|
||
dispatchCommand(mxComponent, u".uno:InsertColumnsAfter"_ustr, {});
|
||
|
||
// text content with change tracking (dummy redline)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
|
||
|
||
// Save it and load it back.
|
||
saveAndReload(u"writer8"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// reject the insertion of the hidden content of the cell
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
|
||
pEditShell->RejectRedline(0);
|
||
|
||
// inserted table column was deleted
|
||
// (working export/import of HasTextChangesOnly)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
|
||
{
|
||
// Load the bugdoc, which has 3 textboxes.
|
||
createSwDoc("tdf128335.odt");
|
||
|
||
// Select the 3rd textbox.
|
||
SwView* pView = getSwDocShell()->GetView();
|
||
selectShape(1);
|
||
SwXTextDocument* pTextDoc = getSwTextDoc();
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
|
||
Scheduler::ProcessEventsToIdle();
|
||
|
||
// Cut it.
|
||
pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
|
||
|
||
// Paste it: this makes the 3rd textbox anchored in the 2nd one.
|
||
pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
|
||
|
||
selectShape(1);
|
||
|
||
// Cut them.
|
||
// Without the accompanying fix in place, this test would have crashed as the textboxes were
|
||
// deleted in an incorrect order.
|
||
pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithReject)
|
||
{
|
||
// load a 1-row table, and delete the row with enabled change tracking:
|
||
// now the row is not deleted silently, but keeps the deleted cell contents,
|
||
// and only accepting all of them will result the deletion of the table row.
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// delete table row with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false)
|
||
dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
|
||
|
||
// Deleted text content with change tracking,
|
||
// but not table deletion
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// Save it and load it back.
|
||
saveAndReload(u"writer8"_ustr);
|
||
pDoc = getSwDoc();
|
||
|
||
// reject the deletion of the content of the first cell
|
||
// HasTextChangesOnly property of the table row will be true
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->RejectRedline(0);
|
||
|
||
// Select and delete the content of the first cell
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
|
||
// table row was still not deleted
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// accept all redlines
|
||
while (pEditShell->GetRedlineCount())
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// This was table row deletion instead of remaining the empty row
|
||
// (HasTextChangesOnly was false)
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// restore HasTextChangesOnly = false
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
// accept all redlines
|
||
while (pEditShell->GetRedlineCount())
|
||
pEditShell->AcceptRedline(0);
|
||
|
||
// table row (and the 1-row table) was deleted finally
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowInsertionWithReject)
|
||
{
|
||
// load a 1-row table, and insert a row with enabled change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table and its single row
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
|
||
// insert rows before and after with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false, and
|
||
// add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsBefore"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
// This was 0 (not tracked row insertion)
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
|
||
|
||
// reject redlines
|
||
pEditShell->RejectRedline(0);
|
||
pEditShell->RejectRedline(0);
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
// This was 3 (not rejected row insertion)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145089_RedlineTableRowInsertionDOCX)
|
||
{
|
||
// load a 1-row table, and insert a row with enabled change tracking
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table and its single row
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
|
||
// insert rows before and after with enabled change tracking
|
||
// (HasTextChangesOnly property of the row will be false, and
|
||
// add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsBefore"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
|
||
// save it to DOCX
|
||
saveAndReload(u"Office Open XML Text"_ustr);
|
||
SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
|
||
pViewShell->Reformat();
|
||
pXmlDoc = parseLayoutDump();
|
||
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
|
||
|
||
// reject redlines
|
||
SwDoc* pDOCXDoc(getSwDoc());
|
||
SwEditShell* const pEditShell(pDOCXDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
|
||
pEditShell->RejectRedline(0);
|
||
pEditShell->RejectRedline(0);
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
|
||
// This was 3 (not rejected row insertion)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRow)
|
||
{
|
||
// load a 1-row table
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// check table count
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
|
||
|
||
// copy table row and paste it by Paste Special->Rows Above
|
||
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
|
||
|
||
// 2-row table
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
|
||
|
||
// This was 2 (inserted as a nested table in the first cell of the new row)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// Is it a tracked row insertion? Its rejection results the original 1-row table
|
||
dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRowInHideChangesMode)
|
||
{
|
||
// load a 1-row table
|
||
createSwDoc("tdf118311.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// turn on red-lining and show changes
|
||
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
|
||
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
|
||
!IDocumentRedlineAccess::IsShowChanges(
|
||
pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
// check table count
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
|
||
|
||
// copy table row and paste it by Paste Special->Rows Above
|
||
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
|
||
|
||
// This resulted freezing
|
||
dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
|
||
|
||
// 2-row table
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
|
||
|
||
// This was 2 (inserted as a nested table in the first cell of the new row)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf146966)
|
||
{
|
||
// load a 4-row table, select more than 1 row and copy them
|
||
// to check insertion of unnecessary empty rows
|
||
createSwDoc("tdf144748.fodt");
|
||
|
||
// check table row count
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
|
||
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
// copy table row and paste it by Paste Special->Rows Above
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
pWrtShell->Down(/*bSelect=*/false);
|
||
dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
|
||
|
||
// This was 35 (extra empty rows)
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
|
||
// dispatchCommand(mxComponent, ".uno:Redo", {}); // FIXME assert
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145091)
|
||
{
|
||
// load a deleted table, reject them, and delete only its text and export to DOCX
|
||
createSwDoc("tdf145091.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// 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()));
|
||
|
||
// reject all redlines
|
||
SwEditShell* const pEditShell(pDoc->GetEditShell());
|
||
CPPUNIT_ASSERT(pEditShell);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
|
||
while (pEditShell->GetRedlineCount() > 0)
|
||
pEditShell->RejectRedline(0);
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
|
||
|
||
// delete only table text, but not table
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
||
CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
|
||
|
||
// save it to DOCX
|
||
saveAndReload(u"Office Open XML Text"_ustr);
|
||
SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
|
||
pViewShell->Reformat();
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
|
||
|
||
// accept all redlines
|
||
dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
|
||
|
||
pXmlDoc = parseLayoutDump();
|
||
// This was false (deleted table with accepting deletions)
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab");
|
||
assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128603)
|
||
{
|
||
// Load the bugdoc, which has 3 textboxes.
|
||
createSwDoc("tdf128603.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
// Select the 3rd textbox.
|
||
SwView* pView = getSwDocShell()->GetView();
|
||
selectShape(1);
|
||
SwXTextDocument* pTextDoc = getSwTextDoc();
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
|
||
pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
|
||
Scheduler::ProcessEventsToIdle();
|
||
|
||
// Cut it.
|
||
pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
|
||
|
||
// Paste it: this makes the 3rd textbox anchored in the 2nd one.
|
||
pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
|
||
|
||
// Undo all of this.
|
||
sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
|
||
rUndoManager.Undo();
|
||
rUndoManager.Undo();
|
||
|
||
// Make sure the content indexes still match.
|
||
const auto& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
|
||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), rSpzFrameFormats.size());
|
||
const SwNodeIndex* pIndex4 = rSpzFrameFormats[4]->GetContent().GetContentIdx();
|
||
CPPUNIT_ASSERT(pIndex4);
|
||
const SwNodeIndex* pIndex5 = rSpzFrameFormats[5]->GetContent().GetContentIdx();
|
||
CPPUNIT_ASSERT(pIndex5);
|
||
// Without the accompanying fix in place, this test would have failed with:
|
||
// - Expected: 11
|
||
// - Actual : 14
|
||
// i.e. the shape content index and the frame content index did not match after undo, even if
|
||
// their "other text box format" pointers pointed to each other.
|
||
CPPUNIT_ASSERT_EQUAL(pIndex4->GetIndex(), pIndex5->GetIndex());
|
||
}
|
||
|
||
// only care that it doesn't assert/crash
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testOfz18563)
|
||
{
|
||
OUString sURL(m_directories.getURLFromSrc(u"/sw/qa/extras/uiwriter/data/ofz18563.docx"));
|
||
SvFileStream aFileStream(sURL, StreamMode::READ);
|
||
TestImportDOCX(aFileStream);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143904)
|
||
{
|
||
createSwDoc("tdf143904.odt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
|
||
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
pWrtShell->Down(false);
|
||
pWrtShell->Insert(u"foo"_ustr);
|
||
|
||
SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
|
||
CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
|
||
nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
|
||
SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
|
||
CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTextNodeA2->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(false, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
|
||
OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
|
||
CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr, sFontName);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf90069)
|
||
{
|
||
createSwDoc("tdf90069.docx");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
|
||
|
||
dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
|
||
pWrtShell->Down(false);
|
||
pWrtShell->Insert(u"foo"_ustr);
|
||
|
||
SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
|
||
CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
|
||
nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
|
||
SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
|
||
CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTextNodeA2->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(true, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
|
||
OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
|
||
CPPUNIT_ASSERT_EQUAL(u"Lohit Devanagari"_ustr, sFontName);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf109266)
|
||
{
|
||
// transliteration with redlining
|
||
createSwDoc("lorem.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
|
||
CPPUNIT_ASSERT(pWrtShell);
|
||
|
||
SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
|
||
SwTextNode* pTextNode = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum..."_ustr, pTextNode->GetRedlineText());
|
||
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToTitleCase"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetRedlineText());
|
||
|
||
//turn on red-lining and show changes
|
||
RedlineFlags const mode(pWrtShell->GetRedlineFlags() | RedlineFlags::On);
|
||
CPPUNIT_ASSERT(mode & (RedlineFlags::ShowDelete | RedlineFlags::ShowInsert));
|
||
pWrtShell->SetRedlineFlags(mode);
|
||
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
|
||
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"redlines should be visible",
|
||
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToTitleCase"_ustr, {});
|
||
|
||
// This was "Lorem Ipsum..." (missing redlining)
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsumIpsum..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetRedlineText());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
|
||
|
||
// This was "LOREM IPSUM..." (missing redlining)
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...LOREM IPSUM..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"LOREM IPSUM..."_ustr, pTextNode->GetRedlineText());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToLower"_ustr, {});
|
||
|
||
// This was "lorem ipsum..." (missing redlining)
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...lorem ipsum..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"lorem ipsum..."_ustr, pTextNode->GetRedlineText());
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
||
dispatchCommand(mxComponent, u".uno:ChangeCaseToToggleCase"_ustr, {});
|
||
|
||
// This was "lOREM IPSUM..." (missing redlining)
|
||
CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...lOREM IPSUM..."_ustr, pTextNode->GetText());
|
||
CPPUNIT_ASSERT_EQUAL(u"lOREM IPSUM..."_ustr, pTextNode->GetRedlineText());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf129655)
|
||
{
|
||
createSwDoc("tdf129655-vtextbox.odt");
|
||
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
|
||
assertXPath(pXmlDoc, "//anchored/fly/txt[@WritingMode='Vertical']", 1);
|
||
}
|
||
|
||
static uno::Reference<text::XTextRange> getAssociatedTextRange(uno::Any object)
|
||
{
|
||
// possible cases:
|
||
// 1. a container of other objects - e.g. selection of 0 to n text portions, or 1 to n drawing objects
|
||
try
|
||
{
|
||
uno::Reference<container::XIndexAccess> xIndexAccess(object, uno::UNO_QUERY_THROW);
|
||
if (xIndexAccess.is() && xIndexAccess->getCount() > 0)
|
||
{
|
||
for (int i = 0; i < xIndexAccess->getCount(); ++i)
|
||
{
|
||
uno::Reference<text::XTextRange> xRange
|
||
= getAssociatedTextRange(xIndexAccess->getByIndex(i));
|
||
if (xRange.is())
|
||
return xRange;
|
||
}
|
||
}
|
||
}
|
||
catch (const uno::Exception&)
|
||
{
|
||
}
|
||
|
||
// 2. another TextContent, having an anchor we can use
|
||
try
|
||
{
|
||
uno::Reference<text::XTextContent> xTextContent(object, uno::UNO_QUERY_THROW);
|
||
if (xTextContent.is())
|
||
{
|
||
uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
|
||
if (xRange.is())
|
||
return xRange;
|
||
}
|
||
}
|
||
catch (const uno::Exception&)
|
||
{
|
||
}
|
||
|
||
// an object which supports XTextRange directly
|
||
try
|
||
{
|
||
uno::Reference<text::XTextRange> xRange(object, uno::UNO_QUERY_THROW);
|
||
if (xRange.is())
|
||
return xRange;
|
||
}
|
||
catch (const uno::Exception&)
|
||
{
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf123218)
|
||
{
|
||
struct ReverseXAxisOrientationDoughnutChart
|
||
: public comphelper::ConfigurationProperty<ReverseXAxisOrientationDoughnutChart, bool>
|
||
{
|
||
static OUString path()
|
||
{
|
||
return u"/org.openoffice.Office.Compatibility/View/ReverseXAxisOrientationDoughnutChart"_ustr;
|
||
}
|
||
~ReverseXAxisOrientationDoughnutChart() = delete;
|
||
};
|
||
|
||
struct ClockwisePieChartDirection
|
||
: public comphelper::ConfigurationProperty<ClockwisePieChartDirection, bool>
|
||
{
|
||
static OUString path()
|
||
{
|
||
return u"/org.openoffice.Office.Compatibility/View/ClockwisePieChartDirection"_ustr;
|
||
}
|
||
~ClockwisePieChartDirection() = delete;
|
||
};
|
||
auto batch = comphelper::ConfigurationChanges::create();
|
||
|
||
ReverseXAxisOrientationDoughnutChart::set(false, batch);
|
||
ClockwisePieChartDirection::set(true, batch);
|
||
batch->commit();
|
||
|
||
createSwDoc();
|
||
|
||
// create an OLE shape in the document
|
||
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT(xMSF);
|
||
uno::Reference<beans::XPropertySet> xShapeProps(
|
||
xMSF->createInstance(u"com.sun.star.text.TextEmbeddedObject"_ustr), uno::UNO_QUERY);
|
||
xShapeProps->setPropertyValue(u"CLSID"_ustr,
|
||
uno::Any(u"12dcae26-281f-416f-a234-c3086127382e"_ustr));
|
||
uno::Reference<drawing::XShape> xShape(xShapeProps, uno::UNO_QUERY_THROW);
|
||
xShape->setSize(awt::Size(16000, 9000));
|
||
uno::Reference<text::XTextContent> chartTextContent(xShapeProps, uno::UNO_QUERY_THROW);
|
||
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
|
||
uno::UNO_QUERY_THROW);
|
||
uno::Any aSelection = xSelSupplier->getSelection();
|
||
uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
|
||
CPPUNIT_ASSERT(xTextRange);
|
||
xTextRange->getText()->insertTextContent(xTextRange, chartTextContent, false);
|
||
|
||
// insert a doughnut chart
|
||
uno::Reference<frame::XModel> xDocModel;
|
||
xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
|
||
CPPUNIT_ASSERT(xDocModel);
|
||
uno::Reference<chart::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT(xChartDoc);
|
||
uno::Reference<lang::XMultiServiceFactory> xChartMSF(xChartDoc, uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT(xChartMSF);
|
||
uno::Reference<chart::XDiagram> xDiagram(
|
||
xChartMSF->createInstance(u"com.sun.star.chart.DonutDiagram"_ustr), uno::UNO_QUERY);
|
||
xChartDoc->setDiagram(xDiagram);
|
||
|
||
// test primary X axis Orientation value
|
||
uno::Reference<chart2::XChartDocument> xChartDoc2(xChartDoc, uno::UNO_QUERY_THROW);
|
||
CPPUNIT_ASSERT(xChartDoc2);
|
||
uno::Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(
|
||
xChartDoc2->getFirstDiagram(), uno::UNO_QUERY_THROW);
|
||
uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence
|
||
= xCooSysContainer->getCoordinateSystems();
|
||
uno::Reference<chart2::XCoordinateSystem> xCoord = xCooSysSequence[0];
|
||
CPPUNIT_ASSERT(xCoord.is());
|
||
uno::Reference<chart2::XAxis> xAxis = xCoord->getAxisByDimension(0, 0);
|
||
CPPUNIT_ASSERT(xAxis.is());
|
||
chart2::ScaleData aScaleData = xAxis->getScaleData();
|
||
CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_MATHEMATICAL, aScaleData.Orientation);
|
||
|
||
// tdf#108059 test primary Y axis Orientation value
|
||
uno::Reference<chart2::XAxis> xYAxis = xCoord->getAxisByDimension(1, 0);
|
||
CPPUNIT_ASSERT(xYAxis.is());
|
||
aScaleData = xYAxis->getScaleData();
|
||
CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_REVERSE, aScaleData.Orientation);
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf93747)
|
||
{
|
||
createSwDoc();
|
||
SwWrtShell* pWrtSh = getSwDocShell()->GetWrtShell();
|
||
|
||
uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
|
||
{ { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
|
||
|
||
dispatchCommand(mxComponent, u".uno:InsertTable"_ustr, aArgs);
|
||
|
||
pWrtSh->Insert(u"Col1"_ustr);
|
||
|
||
// Move the cursor to B1
|
||
pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
|
||
pWrtSh->Insert(u"Col2"_ustr);
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
|
||
|
||
uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(u"Col1"_ustr, xCellA1->getString());
|
||
|
||
uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(u"Col2"_ustr, xCellB1->getString());
|
||
|
||
// Select backwards B1 and A1
|
||
pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
|
||
|
||
// Just select the whole B1
|
||
pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
|
||
uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
|
||
{ "Style", uno::Any(u"Heading 1"_ustr) },
|
||
{ "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
|
||
});
|
||
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
|
||
|
||
// Without the fix in place, this test would have failed with
|
||
// - Expected: Table Contents
|
||
// - Actual : Heading 1
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Table Contents"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
// Now select A1 again
|
||
pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
|
||
dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Table Contents"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Heading 1"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Table Contents"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
|
||
|
||
CPPUNIT_ASSERT_EQUAL(
|
||
u"Table Contents"_ustr,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145151)
|
||
{
|
||
createSwDoc();
|
||
SwWrtShell* pWrtSh = getSwDocShell()->GetWrtShell();
|
||
|
||
uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
|
||
{ { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
|
||
|
||
dispatchCommand(mxComponent, u".uno:InsertTable"_ustr, aArgs);
|
||
|
||
pWrtSh->Insert(u"Col1"_ustr);
|
||
|
||
// Move the cursor to B1
|
||
pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
|
||
|
||
pWrtSh->Insert(u"Col2"_ustr);
|
||
|
||
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
|
||
uno::UNO_QUERY);
|
||
uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
|
||
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
|
||
|
||
uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(u"Col1"_ustr, xCellA1->getString());
|
||
|
||
uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY);
|
||
CPPUNIT_ASSERT_EQUAL(u"Col2"_ustr, xCellB1->getString());
|
||
|
||
// Select backwards B1 and A1 (select "2loC<cell>" which ends up selecting both cells)
|
||
pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
|
||
|
||
// Just select the whole B1
|
||
pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
|
||
dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
|
||
|
||
// B1 should now have a numbering style, but A1 should not be affected.
|
||
OUString sNumStyleB1 = getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
|
||
u"NumberingStyleName"_ustr);
|
||
CPPUNIT_ASSERT(!sNumStyleB1.isEmpty());
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"Only cell B1 was selected. A1 should not have any numbering.",
|
||
getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"NumberingStyleName"_ustr)
|
||
.isEmpty());
|
||
|
||
// Toggle it back off
|
||
dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT_MESSAGE(
|
||
"Cell B1 must be able to toggle numbering on and off.",
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"NumberingStyleName"_ustr)
|
||
.isEmpty());
|
||
|
||
// Now test removing numbering/bullets
|
||
// Add A1 to the current B1 selection
|
||
pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
|
||
// Toggle on bullet numbering
|
||
dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
|
||
|
||
// sanity check - both cells have bullets turned on.
|
||
OUString sNumStyleA1 = getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()),
|
||
u"NumberingStyleName"_ustr);
|
||
CPPUNIT_ASSERT(!sNumStyleA1.isEmpty());
|
||
CPPUNIT_ASSERT_EQUAL(sNumStyleA1,
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
|
||
u"NumberingStyleName"_ustr));
|
||
CPPUNIT_ASSERT(sNumStyleA1 != sNumStyleB1); // therefore B1 changed from numbering to bullets
|
||
|
||
// Just select cell B1
|
||
pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
|
||
|
||
// Toggle off bullet numbering
|
||
dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
|
||
|
||
// B1 should now have removed all numbering, while A1 should still have the bullet.
|
||
CPPUNIT_ASSERT(
|
||
getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"NumberingStyleName"_ustr)
|
||
.isEmpty());
|
||
CPPUNIT_ASSERT_MESSAGE("Only cell B1 was selected. A1 should still have bullets turned on.",
|
||
!getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()),
|
||
u"NumberingStyleName"_ustr)
|
||
.isEmpty());
|
||
|
||
// Toggle it back on
|
||
dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
|
||
|
||
CPPUNIT_ASSERT(!getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
|
||
u"NumberingStyleName"_ustr)
|
||
.isEmpty());
|
||
}
|
||
|
||
CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126735)
|
||
{
|
||
createSwDoc("tdf39721.fodt");
|
||
SwDoc* pDoc = getSwDoc();
|
||
|
||
//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()));
|
||
|
||
// check next selected tracked change
|
||
dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
|
||
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
|
||
uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
|
||
uno::UNO_QUERY_THROW);
|
||
uno::Any aSelection = xSelSupplier->getSelection();
|
||
uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
|
||
CPPUNIT_ASSERT(xTextRange);
|
||
CPPUNIT_ASSERT_EQUAL(u" ipsu"_ustr, xTextRange->getString());
|
||
|
||
// check next selected tracked change
|
||
dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
|
||
aSelection = xSelSupplier->getSelection();
|
||
xTextRange = getAssociatedTextRange(aSelection);
|
||
CPPUNIT_ASSERT(xTextRange);
|
||
CPPUNIT_ASSERT_EQUAL(u"or "_ustr, xTextRange->getString());
|
||
|
||
// check next selected tracked change at the end of the document:
|
||
// select the first tracked change of the document
|
||
dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
|
||
aSelection = xSelSupplier->getSelection();
|
||
xTextRange = getAssociatedTextRange(aSelection);
|
||
CPPUNIT_ASSERT(xTextRange);
|
||
// This was empty (collapsing at the end of the last tracked change)
|
||
CPPUNIT_ASSERT_EQUAL(u" ipsu"_ustr, xTextRange->getString());
|
||
|
||
// check the previous tracked change at the start of the document:
|
||
// select the last tracked change of the document
|
||
dispatchCommand(mxComponent, u".uno:PreviousTrackedChange"_ustr, {});
|
||
aSelection = xSelSupplier->getSelection();
|
||
xTextRange = getAssociatedTextRange(aSelection);
|
||
CPPUNIT_ASSERT(xTextRange);
|
||
// This was empty (collapsing at the start of the last tracked change)
|
||
CPPUNIT_ASSERT_EQUAL(u"or "_ustr, xTextRange->getString());
|
||
}
|
||
|
||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||
|
||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|