2020-08-03 21:03:43 +02:00
|
|
|
/* -*- 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/.
|
|
|
|
*/
|
|
|
|
|
2022-11-03 11:42:17 +01:00
|
|
|
#include <test/unoapixml_test.hxx>
|
2020-08-03 21:03:43 +02:00
|
|
|
|
2023-08-14 08:10:51 +02:00
|
|
|
#include <com/sun/star/awt/FontWeight.hpp>
|
2021-01-15 11:57:50 +01:00
|
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
2022-05-09 10:14:29 +02:00
|
|
|
#include <com/sun/star/beans/PropertyValues.hpp>
|
2021-01-15 11:57:50 +01:00
|
|
|
#include <com/sun/star/frame/XStorable.hpp>
|
|
|
|
#include <com/sun/star/text/XTextDocument.hpp>
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
#include <com/sun/star/text/ControlCharacter.hpp>
|
2021-07-23 13:41:27 +02:00
|
|
|
#include <com/sun/star/text/BibliographyDataType.hpp>
|
2022-05-19 09:12:21 +02:00
|
|
|
#include <com/sun/star/text/TextContentAnchorType.hpp>
|
2021-09-02 16:39:26 +02:00
|
|
|
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
2023-01-28 18:43:51 +09:00
|
|
|
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
|
2023-03-03 18:04:46 +03:00
|
|
|
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
|
2023-02-23 08:21:46 +01:00
|
|
|
#include <com/sun/star/text/XTextFramesSupplier.hpp>
|
2021-01-15 11:57:50 +01:00
|
|
|
|
|
|
|
#include <comphelper/propertysequence.hxx>
|
2021-07-23 13:41:27 +02:00
|
|
|
#include <comphelper/propertyvalue.hxx>
|
|
|
|
#include <comphelper/sequenceashashmap.hxx>
|
2021-01-15 11:57:50 +01:00
|
|
|
#include <unotools/tempfile.hxx>
|
2023-01-28 18:43:51 +09:00
|
|
|
#include <docmodel/uno/UnoTheme.hxx>
|
2023-02-25 19:12:23 +09:00
|
|
|
#include <docmodel/theme/Theme.hxx>
|
2020-08-03 21:03:43 +02:00
|
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
|
|
|
/// Covers xmloff/source/text/ fixes.
|
2022-11-03 11:42:17 +01:00
|
|
|
class XmloffStyleTest : public UnoApiXmlTest
|
2020-08-03 21:03:43 +02:00
|
|
|
{
|
|
|
|
public:
|
2022-10-24 13:43:14 +02:00
|
|
|
XmloffStyleTest();
|
2020-08-03 21:03:43 +02:00
|
|
|
};
|
|
|
|
|
2022-10-24 13:43:14 +02:00
|
|
|
XmloffStyleTest::XmloffStyleTest()
|
2024-05-15 13:12:19 +02:00
|
|
|
: UnoApiXmlTest(u"/xmloff/qa/unit/data/"_ustr)
|
2021-09-03 16:42:46 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-08-03 21:03:43 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testMailMergeInEditeng)
|
|
|
|
{
|
|
|
|
// Without the accompanying fix in place, this test would have failed, as unexpected
|
2020-08-04 12:34:03 +02:00
|
|
|
// <text:database-display> in editeng text aborted the whole import process.
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"mail-merge-editeng.odt");
|
2020-08-03 21:03:43 +02:00
|
|
|
}
|
|
|
|
|
2023-09-01 09:49:53 +03:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testCommentProperty)
|
2021-01-15 11:57:50 +01:00
|
|
|
{
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2021-01-15 11:57:50 +01:00
|
|
|
uno::Sequence<beans::PropertyValue> aCommentProps = comphelper::InitPropertySequence({
|
2024-05-15 13:12:19 +02:00
|
|
|
{ "Text", uno::Any(u"comment"_ustr) },
|
2021-01-15 11:57:50 +01:00
|
|
|
});
|
2024-05-15 13:12:19 +02:00
|
|
|
dispatchCommand(mxComponent, u".uno:InsertAnnotation"_ustr, aCommentProps);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2021-01-15 11:57:50 +01:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xField(xPortion->getPropertyValue(u"TextField"_ustr),
|
2021-01-15 11:57:50 +01:00
|
|
|
uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xField->setPropertyValue(u"Resolved"_ustr, uno::Any(true));
|
|
|
|
xField->setPropertyValue(u"ParentName"_ustr, uno::Any(u"parent_comment_name"_ustr));
|
2021-01-15 11:57:50 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
saveAndReload(u"writer8"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
xTextDocument.set(mxComponent, uno::UNO_QUERY);
|
2021-01-15 11:57:50 +01:00
|
|
|
xParaEnumAccess.set(xTextDocument->getText(), uno::UNO_QUERY);
|
|
|
|
xParaEnum = xParaEnumAccess->createEnumeration();
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
xPortionEnum = xPara->createEnumeration();
|
|
|
|
xPortion.set(xPortionEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xField.set(xPortion->getPropertyValue(u"TextField"_ustr), uno::UNO_QUERY);
|
2021-01-15 11:57:50 +01:00
|
|
|
bool bResolved = false;
|
2024-05-15 13:12:19 +02:00
|
|
|
xField->getPropertyValue(u"Resolved"_ustr) >>= bResolved;
|
2023-09-01 09:49:53 +03:00
|
|
|
OUString parentName;
|
2024-05-15 13:12:19 +02:00
|
|
|
xField->getPropertyValue(u"ParentName"_ustr) >>= parentName;
|
2023-09-01 09:49:53 +03:00
|
|
|
CPPUNIT_ASSERT_EQUAL(
|
2024-05-15 13:12:19 +02:00
|
|
|
u"parent_comment_name"_ustr,
|
2023-09-01 09:49:53 +03:00
|
|
|
parentName); // Check if the parent comment name is written and read correctly.
|
2021-01-15 11:57:50 +01:00
|
|
|
// Without the accompanying fix in place, this test would have failed, as the resolved state was
|
|
|
|
// not saved for non-range comments.
|
|
|
|
CPPUNIT_ASSERT(bResolved);
|
|
|
|
}
|
|
|
|
|
2021-07-23 13:41:27 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testBibliographyLocalUrl)
|
|
|
|
{
|
|
|
|
// Given a document with a biblio field, with non-empty LocalURL:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
2021-07-23 13:41:27 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xField(
|
2024-05-15 13:12:19 +02:00
|
|
|
xFactory->createInstance(u"com.sun.star.text.TextField.Bibliography"_ustr), uno::UNO_QUERY);
|
2021-07-23 13:41:27 +02:00
|
|
|
uno::Sequence<beans::PropertyValue> aFields = {
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"BibiliographicType"_ustr, text::BibliographyDataType::WWW),
|
|
|
|
comphelper::makePropertyValue(u"Identifier"_ustr, u"AT"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"Author"_ustr, u"Author"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"Title"_ustr, u"Title"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"URL"_ustr, u"http://www.example.com/test.pdf#page=1"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"LocalURL"_ustr, u"file:///home/me/test.pdf"_ustr),
|
2021-07-23 13:41:27 +02:00
|
|
|
};
|
2024-05-15 13:12:19 +02:00
|
|
|
xField->setPropertyValue(u"Fields"_ustr, uno::Any(aFields));
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2021-07-23 13:41:27 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
uno::Reference<text::XTextContent> xContent(xField, uno::UNO_QUERY);
|
|
|
|
xText->insertTextContent(xCursor, xContent, /*bAbsorb=*/false);
|
|
|
|
|
|
|
|
// When invoking ODT export + import on it:
|
2024-05-15 13:12:19 +02:00
|
|
|
saveAndReload(u"writer8"_ustr);
|
2021-07-23 13:41:27 +02:00
|
|
|
// Without the accompanying fix in place, this test would have resulted in an assertion failure,
|
|
|
|
// as LocalURL was mapped to XML_TOKEN_INVALID.
|
|
|
|
|
|
|
|
// Then make sure that LocalURL is preserved:
|
2022-10-24 13:43:14 +02:00
|
|
|
xTextDocument.set(mxComponent, uno::UNO_QUERY);
|
2021-07-23 13:41:27 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xField.set(xPortion->getPropertyValue(u"TextField"_ustr), uno::UNO_QUERY);
|
|
|
|
comphelper::SequenceAsHashMap aMap(xField->getPropertyValue(u"Fields"_ustr));
|
|
|
|
CPPUNIT_ASSERT(aMap.contains(u"LocalURL"_ustr));
|
|
|
|
auto aActual = aMap[u"LocalURL"_ustr].get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"file:///home/me/test.pdf"_ustr, aActual);
|
2021-07-23 13:41:27 +02:00
|
|
|
}
|
|
|
|
|
2023-03-07 11:35:04 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testBibliographyTargetURL1)
|
|
|
|
{
|
|
|
|
// Given a document with a biblio field, with non-empty LocalURL:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2023-03-07 11:35:04 +01:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xField(
|
2024-05-15 13:12:19 +02:00
|
|
|
xFactory->createInstance(u"com.sun.star.text.TextField.Bibliography"_ustr), uno::UNO_QUERY);
|
2023-03-07 11:35:04 +01:00
|
|
|
uno::Sequence<beans::PropertyValue> aFields = {
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"Identifier"_ustr, u"AT"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"URL"_ustr, u"https://display.url/test1.pdf#page=1"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"TargetType"_ustr, u"1"_ustr),
|
|
|
|
comphelper::makePropertyValue(u"TargetURL"_ustr,
|
|
|
|
u"https://target.url/test2.pdf#page=2"_ustr),
|
2023-03-07 11:35:04 +01:00
|
|
|
};
|
2024-05-15 13:12:19 +02:00
|
|
|
xField->setPropertyValue(u"Fields"_ustr, uno::Any(aFields));
|
2023-03-07 11:35:04 +01:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
uno::Reference<text::XTextContent> xContent(xField, uno::UNO_QUERY);
|
|
|
|
xText->insertTextContent(xCursor, xContent, /*bAbsorb=*/false);
|
|
|
|
|
|
|
|
// When invoking ODT export + import on it:
|
2024-05-15 13:12:19 +02:00
|
|
|
saveAndReload(u"writer8"_ustr);
|
2023-03-07 11:35:04 +01:00
|
|
|
|
|
|
|
// Then make sure that URL, TargetURL and UseTargetURL are preserved and independent:
|
|
|
|
xTextDocument.set(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> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xField.set(xPortion->getPropertyValue(u"TextField"_ustr), uno::UNO_QUERY);
|
|
|
|
comphelper::SequenceAsHashMap aMap(xField->getPropertyValue(u"Fields"_ustr));
|
2023-03-07 11:35:04 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT(aMap.contains(u"URL"_ustr));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"https://display.url/test1.pdf#page=1"_ustr,
|
|
|
|
aMap[u"URL"_ustr].get<OUString>());
|
2023-03-07 11:35:04 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT(aMap.contains(u"TargetURL"_ustr));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"https://target.url/test2.pdf#page=2"_ustr,
|
|
|
|
aMap[u"TargetURL"_ustr].get<OUString>());
|
2023-03-07 11:35:04 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT(aMap.contains(u"TargetType"_ustr));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1"_ustr, aMap[u"TargetType"_ustr].get<OUString>());
|
2023-03-07 11:35:04 +01:00
|
|
|
}
|
|
|
|
|
2021-08-30 20:12:46 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testCommentTableBorder)
|
|
|
|
{
|
|
|
|
// Without the accompanying fix in place, this failed to load, as a comment that started in a
|
|
|
|
// table and ended outside a table aborted the whole importer.
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"comment-table-border.fodt");
|
2021-08-30 20:12:46 +02:00
|
|
|
}
|
|
|
|
|
2021-09-02 16:39:26 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testParaStyleListLevel)
|
|
|
|
{
|
|
|
|
// Given a document with style:list-level="...":
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"para-style-list-level.fodt");
|
2021-09-02 16:39:26 +02:00
|
|
|
|
|
|
|
// Then make sure we map that to the paragraph style's numbering level:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent,
|
2021-09-02 16:39:26 +02:00
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XNameAccess> xStyleFamilies
|
|
|
|
= xStyleFamiliesSupplier->getStyleFamilies();
|
|
|
|
uno::Reference<container::XNameAccess> xStyleFamily(
|
2024-05-15 13:12:19 +02:00
|
|
|
xStyleFamilies->getByName(u"ParagraphStyles"_ustr), uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xStyle(xStyleFamily->getByName(u"mystyle"_ustr),
|
|
|
|
uno::UNO_QUERY);
|
2021-09-02 16:39:26 +02:00
|
|
|
sal_Int16 nNumberingLevel{};
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT(xStyle->getPropertyValue(u"NumberingLevel"_ustr) >>= nNumberingLevel);
|
2021-12-13 17:42:00 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), nNumberingLevel);
|
2021-09-03 16:42:46 +02:00
|
|
|
|
|
|
|
// Test the export as well:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2021-09-03 16:42:46 +02:00
|
|
|
|
|
|
|
// Then make sure we save the style's numbering level:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
|
2021-09-03 16:42:46 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - XPath '/office:document-styles/office:styles/style:style[@style:name='mystyle']' no attribute 'list-level' exist
|
|
|
|
// i.e. a custom NumberingLevel was lost on save.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "/office:document-styles/office:styles/style:style[@style:name='mystyle']",
|
|
|
|
"list-level", u"2");
|
2021-09-02 16:39:26 +02:00
|
|
|
}
|
|
|
|
|
2022-02-24 16:43:19 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testContinueNumberingWord)
|
|
|
|
{
|
|
|
|
// Given a document, which is produced by Word and contains text:continue-numbering="true":
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"continue-numbering-word.odt");
|
2022-02-24 16:43:19 +01:00
|
|
|
|
|
|
|
// Then make sure that the numbering from the 1st para is continued on the 3rd para:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-02-24 16:43:19 +01:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
|
|
|
|
xParaEnum->nextElement();
|
|
|
|
xParaEnum->nextElement();
|
|
|
|
uno::Reference<beans::XPropertySet> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
auto aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
2022-02-24 16:43:19 +01:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - Expected: 2.
|
|
|
|
// - Actual : 1.
|
|
|
|
// i.e. the numbering was not continued, like in Word.
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2."_ustr, aActual);
|
2022-02-24 16:43:19 +01:00
|
|
|
}
|
|
|
|
|
2022-03-10 16:29:48 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListId)
|
|
|
|
{
|
|
|
|
// Given a document with a simple list (no continue-list="..." attribute):
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"list-id.fodt");
|
2022-03-10 16:29:48 +01:00
|
|
|
|
|
|
|
// When storing that document as ODF:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-03-10 16:29:48 +01:00
|
|
|
|
|
|
|
// Then make sure that unreferenced xml:id="..." attributes are not written:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-03-10 16:29:48 +01:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - XPath '//text:list' unexpected 'id' attribute
|
|
|
|
// i.e. xml:id="..." was written unconditionally, even when no other list needed it.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPathNoAttribute(pXmlDoc, "//text:list", "id");
|
2022-03-10 16:29:48 +01:00
|
|
|
}
|
|
|
|
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListId2)
|
|
|
|
{
|
|
|
|
// tdf#155823 Given a document with a list consisting of items having different list styles:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"differentListStylesInOneList.fodt");
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
auto xTextDocument(mxComponent.queryThrow<css::text::XTextDocument>());
|
|
|
|
auto xParaEnumAccess(xTextDocument->getText().queryThrow<css::container::XEnumerationAccess>());
|
|
|
|
auto xParaEnum(xParaEnumAccess->createEnumeration());
|
|
|
|
|
|
|
|
auto xPara(xParaEnum->nextElement().queryThrow<beans::XPropertySet>());
|
2024-05-15 13:12:19 +02:00
|
|
|
auto aActual(xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"3."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"4."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
// When storing that document as ODF:
|
|
|
|
// Without the fix in place, automatic validation would fail with:
|
|
|
|
// Error: "list123456789012345" is referenced by an IDREF, but not defined.
|
2024-05-15 13:12:19 +02:00
|
|
|
saveAndReload(u"writer8"_ustr);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
xTextDocument.set(mxComponent.queryThrow<css::text::XTextDocument>());
|
|
|
|
xParaEnumAccess.set(xTextDocument->getText().queryThrow<css::container::XEnumerationAccess>());
|
|
|
|
xParaEnum.set(xParaEnumAccess->createEnumeration());
|
|
|
|
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"3."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
|
|
|
|
// Check that the last item number is correct
|
|
|
|
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
// Without the fix in place, this would fail with:
|
|
|
|
// - Expected: 4.
|
|
|
|
// - Actual : 1.
|
|
|
|
// i.e. the numbering was not continued.
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"4."_ustr, aActual);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
// Then make sure that required xml:id="..." attributes is written when the style changes:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
CPPUNIT_ASSERT(pXmlDoc);
|
|
|
|
// Without the fix in place, this would fail,
|
|
|
|
// i.e. xml:id="..." was omitted, even though it was needed for the next item.
|
2024-10-03 11:40:13 +05:00
|
|
|
OUString id
|
|
|
|
= getXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:list[3]", "id");
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
CPPUNIT_ASSERT(!id.isEmpty());
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:list[4]",
|
|
|
|
"continue-list", id);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListIdState)
|
|
|
|
{
|
|
|
|
// tdf#149668: given a document with 3 paragraphs: an outer numbering on para 1 & 3, an inner
|
|
|
|
// numbering on para 2:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
auto xTextDocument(mxComponent.queryThrow<text::XTextDocument>());
|
|
|
|
auto xText(xTextDocument->getText());
|
|
|
|
xText->insertControlCharacter(xText->getEnd(), css::text::ControlCharacter::PARAGRAPH_BREAK,
|
|
|
|
false);
|
|
|
|
xText->insertControlCharacter(xText->getEnd(), css::text::ControlCharacter::PARAGRAPH_BREAK,
|
|
|
|
false);
|
|
|
|
|
|
|
|
auto paraEnumAccess(xText.queryThrow<container::XEnumerationAccess>());
|
|
|
|
auto paraEnum(paraEnumAccess->createEnumeration());
|
|
|
|
auto xParaProps(paraEnum->nextElement().queryThrow<beans::XPropertySet>());
|
2024-05-15 13:12:19 +02:00
|
|
|
xParaProps->setPropertyValue(u"NumberingStyleName"_ustr, css::uno::Any(u"Numbering ABC"_ustr));
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaProps.set(paraEnum->nextElement().queryThrow<beans::XPropertySet>());
|
2024-05-15 13:12:19 +02:00
|
|
|
xParaProps->setPropertyValue(u"NumberingStyleName"_ustr, css::uno::Any(u"Numbering 123"_ustr));
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
xParaProps.set(paraEnum->nextElement().queryThrow<beans::XPropertySet>());
|
2024-05-15 13:12:19 +02:00
|
|
|
xParaProps->setPropertyValue(u"NumberingStyleName"_ustr, css::uno::Any(u"Numbering ABC"_ustr));
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
// When storing that document as ODF:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
|
|
|
|
// Make sure that xml:id="..." gets written for para 1, as it'll be continued in para 3.
|
|
|
|
// Without the accompanying fix in place, this test would have failed,
|
|
|
|
// i.e. para 1 didn't write an xml:id="..." but para 3 referred to it using continue-list="...",
|
|
|
|
// which is inconsistent.
|
2024-10-03 11:40:13 +05:00
|
|
|
OUString id
|
|
|
|
= getXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:list[1]", "id");
|
tdf#155823: Improve the check if the list id is not required
The implementation introduced in commit 8f48f91009caa86d896f247059874242ed18bf39
(SwNumRule::HasContinueList) was a bit naive: it assumed that maTextNodeList is
sorted (it is not, and so, valid cases to avoid the id were missed); it assumed
that a given list can only consist of items of a single numbering style, and so
only tested the list of nodes referenced from maTextNodeList of given SwNumRule.
I.e., this implementation targeted a special case of a list style fully covering
a single continuous list.
This skipped ids for list items with list styles, in which maTextNodeList passed
the check in HasContinueList, but which were followed by items with a different
list style, continuing the same list. This constellation outputs continue-list
attribute in the following items (see XMLTextParagraphExport::exportListChange),
which references the skipped id. The resulting ODF is an invalid XML (an xml:id
is missing that is referenced), and also does not allow to continue such a list.
The change tries to fix this, using a list of nodes in XMLTextParagraphExport,
and analyzing if the list of the current paragraph has a continuation that needs
to reference this list id. Two new hidden properties introduced in SwXParagraph
and SwXTextDocument: "ODFExport_NodeIndex" and "ODFExport_ListNodes", resp. They
allow to pipe the data to the export. The previous special casing of property
state for "ListId", used in SwNumRule::HasContinueList, is removed together with
the mentioned function.
The intention is to have a logic allowing to detect 100% cases where the list id
is required, and where it's not required.
A related unit test for tdf#149668 was fixed to not rely on the mentioned ListId
property state workaround, and moved from sw/qa/core/unocore to xmloff/qa/unit.
Change-Id: If6a6ac7a3dfe0b2ea143229678a603875153eedb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153044
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-06-13 23:15:08 +03:00
|
|
|
CPPUNIT_ASSERT(!id.isEmpty());
|
|
|
|
}
|
|
|
|
|
2023-06-15 10:34:41 +03:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListIdOnRestart)
|
|
|
|
{
|
|
|
|
// Test that a restart of a continued list, by itself, does not introduce a unneeded xml:id
|
|
|
|
// and text:continue-list, but uses text:continue-numbering, and is imported correctly.
|
|
|
|
|
|
|
|
// Given a document with a list with a restart after break:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"listRestartAfterBreak.fodt");
|
2023-06-15 10:34:41 +03:00
|
|
|
|
|
|
|
auto xTextDocument(mxComponent.queryThrow<css::text::XTextDocument>());
|
|
|
|
auto xParaEnumAccess(xTextDocument->getText().queryThrow<css::container::XEnumerationAccess>());
|
|
|
|
auto xParaEnum(xParaEnumAccess->createEnumeration());
|
|
|
|
|
|
|
|
auto xPara(xParaEnum->nextElement().queryThrow<beans::XPropertySet>());
|
2024-05-15 13:12:19 +02:00
|
|
|
auto aActual(xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
|
|
|
OUString list_id = xPara->getPropertyValue(u"ListId"_ustr).get<OUString>();
|
2023-06-15 10:34:41 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2."_ustr, aActual);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue(u"ListId"_ustr).get<OUString>());
|
2023-06-15 10:34:41 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
2023-06-15 10:34:41 +03:00
|
|
|
// Check that restart was applied correctly, with simple 'text:continue-numbering="true"'
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue(u"ListId"_ustr).get<OUString>());
|
2023-06-15 10:34:41 +03:00
|
|
|
|
|
|
|
// When storing that document as ODF:
|
2024-05-15 13:12:19 +02:00
|
|
|
saveAndReload(u"writer8"_ustr);
|
2023-06-15 10:34:41 +03:00
|
|
|
|
|
|
|
xTextDocument.set(mxComponent, uno::UNO_QUERY_THROW);
|
|
|
|
xParaEnumAccess.set(xTextDocument->getText(), uno::UNO_QUERY_THROW);
|
|
|
|
xParaEnum.set(xParaEnumAccess->createEnumeration());
|
|
|
|
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
|
|
|
list_id = xPara->getPropertyValue(u"ListId"_ustr).get<OUString>();
|
2023-06-15 10:34:41 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2."_ustr, aActual);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue(u"ListId"_ustr).get<OUString>());
|
2023-06-15 10:34:41 +03:00
|
|
|
xParaEnum->nextElement(); // Skip empty intermediate paragraph
|
|
|
|
xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW);
|
2024-05-15 13:12:19 +02:00
|
|
|
aActual = xPara->getPropertyValue(u"ListLabelString"_ustr).get<OUString>();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"1."_ustr, aActual);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue(u"ListId"_ustr).get<OUString>());
|
2023-06-15 10:34:41 +03:00
|
|
|
|
|
|
|
// Then make sure that no xml:id="..." attribute is written, even in restarted case:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2023-06-15 10:34:41 +03:00
|
|
|
CPPUNIT_ASSERT(pXmlDoc);
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//text:list", 3);
|
|
|
|
assertXPathNoAttribute(pXmlDoc, "//text:list[1]", "id");
|
|
|
|
assertXPathNoAttribute(pXmlDoc, "//text:list[2]", "id");
|
|
|
|
assertXPathNoAttribute(pXmlDoc, "//text:list[3]", "id");
|
|
|
|
assertXPathNoAttribute(pXmlDoc, "//text:list[3]", "continue-list");
|
|
|
|
assertXPath(pXmlDoc, "//text:list[3]", "continue-numbering", u"true");
|
2023-06-15 10:34:41 +03:00
|
|
|
}
|
|
|
|
|
2022-03-11 12:29:30 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testClearingBreakExport)
|
|
|
|
{
|
|
|
|
// Given a document with a clearing break:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-03-11 12:29:30 +01:00
|
|
|
uno::Reference<text::XTextContent> xLineBreak(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.LineBreak"_ustr), uno::UNO_QUERY);
|
2022-03-11 12:29:30 +01:00
|
|
|
uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
|
|
|
|
// SwLineBreakClear::ALL;
|
|
|
|
sal_Int16 eClear = 3;
|
2024-05-15 13:12:19 +02:00
|
|
|
xLineBreakProps->setPropertyValue(u"Clear"_ustr, uno::Any(eClear));
|
2022-03-11 12:29:30 +01:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
xText->insertTextContent(xCursor, xLineBreak, /*bAbsorb=*/false);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-03-11 12:29:30 +01:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-03-11 12:29:30 +01:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - XPath '//text:line-break' number of nodes is incorrect
|
|
|
|
// i.e. the clearing break was lost on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//text:line-break", "clear", u"all");
|
2022-03-11 12:29:30 +01:00
|
|
|
}
|
|
|
|
|
2022-03-16 09:40:48 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testClearingBreakImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a clearing break:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"clearing-break.fodt");
|
2022-03-16 09:40:48 +01:00
|
|
|
|
|
|
|
// Then make sure that the "clear" attribute is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-03-16 09:40:48 +01:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
// First portion is the image.
|
|
|
|
xPortions->nextElement();
|
|
|
|
// Second portion is "foo".
|
|
|
|
xPortions->nextElement();
|
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// An uncaught exception of type com.sun.star.container.NoSuchElementException
|
|
|
|
// i.e. the line break was a non-clearing one, so we only had 2 portions, not 4 (image, text,
|
|
|
|
// linebreak, text).
|
|
|
|
uno::Reference<beans::XPropertySet> xPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aTextPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aTextPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"LineBreak"_ustr, aTextPortionType);
|
2022-03-16 09:40:48 +01:00
|
|
|
uno::Reference<text::XTextContent> xLineBreak;
|
2024-05-15 13:12:19 +02:00
|
|
|
xPortion->getPropertyValue(u"LineBreak"_ustr) >>= xLineBreak;
|
2022-03-16 09:40:48 +01:00
|
|
|
uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
|
|
|
|
sal_Int16 eClear{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xLineBreakProps->getPropertyValue(u"Clear"_ustr) >>= eClear;
|
2022-03-16 09:40:48 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3), eClear);
|
|
|
|
}
|
|
|
|
|
2022-03-16 15:35:50 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testRelativeWidth)
|
|
|
|
{
|
|
|
|
// Given a document with an 50% wide text frame:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent,
|
2022-03-16 15:35:50 +01:00
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XNameAccess> xStyleFamilies
|
|
|
|
= xStyleFamiliesSupplier->getStyleFamilies();
|
2024-05-15 13:12:19 +02:00
|
|
|
uno::Reference<container::XNameAccess> xStyleFamily(
|
|
|
|
xStyleFamilies->getByName(u"PageStyles"_ustr), uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xStyle(xStyleFamily->getByName(u"Standard"_ustr),
|
|
|
|
uno::UNO_QUERY);
|
2022-03-16 15:35:50 +01:00
|
|
|
// Body frame width is 6cm (2+2cm margin).
|
2024-05-15 13:12:19 +02:00
|
|
|
xStyle->setPropertyValue(u"Width"_ustr, uno::Any(static_cast<sal_Int32>(10000)));
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-03-16 15:35:50 +01:00
|
|
|
uno::Reference<text::XTextContent> xTextFrame(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.TextFrame"_ustr), uno::UNO_QUERY);
|
2022-03-16 15:35:50 +01:00
|
|
|
uno::Reference<beans::XPropertySet> xTextFrameProps(xTextFrame, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextFrameProps->setPropertyValue(u"RelativeWidth"_ustr, uno::Any(static_cast<sal_Int16>(50)));
|
2022-03-16 15:35:50 +01:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
xText->insertTextContent(xCursor, xTextFrame, /*bAbsorb=*/false);
|
|
|
|
// Body frame width is 16cm.
|
2024-05-15 13:12:19 +02:00
|
|
|
xStyle->setPropertyValue(u"Width"_ustr, uno::Any(static_cast<sal_Int32>(20000)));
|
2022-03-16 15:35:50 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-03-16 15:35:50 +01:00
|
|
|
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-03-16 15:35:50 +01:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
Related: tdf#145972 sw images: fix rounding error in relative size calculation
Open the bugdoc, see that the image is roughly half of the page width,
right click, properties, UI shows that the width of the image is 5% of
the width of the entire page. This only happens if tools -> options ->
writer -> general sets the UI units to points, the default cm case is
fine.
This went wrong with commit 9e8712ed6f9fb5dbd971e352a5709bd45fadc74f (sw
image dialog: fix fallback width/height for images with relative sizes,
2022-03-17), because the layout size started to matter more after that
commit. This lead to the nWidth !=
m_xWidthED->get_value(FieldUnit::TWIP) check in SwFramePage::Init() to
be true, because 11906 * 0.48 is 5714.88, so you got 5714 in the layout,
but got 5715 with rounding in SwFramePage::Reset() (which tries to calc
the page width based on the 48% and the fly width). And once we had that
mismatch, we went down the wrong path.
Fix the problem by using rtl::math::round() in SwFlyFrame::CalcRel(), so
the relative width twips value is 5715 everywhere: once we have
consisteny, the UI value is correct, too.
Note that the original bugdoc needs more fixing, this just fixes the
bugdoc where KeepRatio is false.
Change-Id: I1e8782c95a0cf9d97375c36d41134735c01f3e46
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167916
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
2024-05-22 08:47:32 +02:00
|
|
|
// - Expected: 3.15in (8cm)
|
2022-03-16 15:35:50 +01:00
|
|
|
// - Actual : 0.0161in (0.04 cm)
|
|
|
|
// i.e. the fallback width value wasn't the expected half of the body frame width, but a smaller
|
|
|
|
// value.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//draw:frame", "width", u"3.15in");
|
2022-03-16 15:35:50 +01:00
|
|
|
}
|
|
|
|
|
2022-09-20 09:10:25 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testScaleWidthAndHeight)
|
|
|
|
{
|
|
|
|
// Given a broken document where both IsSyncHeightToWidth and IsSyncWidthToHeight are set to
|
|
|
|
// true:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-09-20 09:10:25 +02:00
|
|
|
uno::Reference<text::XTextContent> xTextFrame(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.TextFrame"_ustr), uno::UNO_QUERY);
|
2022-09-20 09:10:25 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xTextFrameProps(xTextFrame, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextFrameProps->setPropertyValue(u"Width"_ustr, uno::Any(static_cast<sal_Int16>(2000)));
|
|
|
|
xTextFrameProps->setPropertyValue(u"Height"_ustr, uno::Any(static_cast<sal_Int16>(1000)));
|
|
|
|
xTextFrameProps->setPropertyValue(u"IsSyncHeightToWidth"_ustr, uno::Any(true));
|
|
|
|
xTextFrameProps->setPropertyValue(u"IsSyncWidthToHeight"_ustr, uno::Any(true));
|
2022-09-20 09:10:25 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
xText->insertTextContent(xCursor, xTextFrame, /*bAbsorb=*/false);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-09-20 09:10:25 +02:00
|
|
|
|
|
|
|
// Then make sure that we still export a non-zero size:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-09-20 09:10:25 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - Expected: 0.7874in
|
|
|
|
// - Actual : 0in
|
|
|
|
// i.e. the exported size was 0, not 2000 mm100 in inches.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//draw:frame", "width", u"0.7874in");
|
2022-09-20 09:10:25 +02:00
|
|
|
}
|
|
|
|
|
2022-04-08 11:32:22 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a content control around one or more text portions:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-04-08 11:32:22 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"test"_ustr, /*bAbsorb=*/false);
|
2022-04-08 11:32:22 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-04-08 11:32:22 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"ShowingPlaceHolder"_ustr, uno::Any(true));
|
2022-04-08 11:32:22 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-04-08 11:32:22 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-04-08 11:32:22 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - XPath '//loext:content-control' number of nodes is incorrect
|
|
|
|
// i.e. the content control was lost on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "showing-place-holder", u"true");
|
2022-04-08 11:32:22 +02:00
|
|
|
}
|
|
|
|
|
2022-04-11 11:27:13 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control.fodt");
|
2022-04-11 11:27:13 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-04-11 11:27:13 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
2022-04-11 11:27:13 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - Expected: ContentControl
|
|
|
|
// - Actual : Text
|
|
|
|
// i.e. the content control was lost on import.
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-04-11 11:27:13 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-04-11 11:27:13 +02:00
|
|
|
uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XText> xText = xContentControlRange->getText();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"test"_ustr, xContent->getString());
|
2022-04-11 11:27:13 +02:00
|
|
|
}
|
|
|
|
|
2022-04-27 08:53:13 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testCheckboxContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a checkbox content control around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2023-10-06 09:42:38 +02:00
|
|
|
xText->insertString(xCursor, u"☐"_ustr, /*bAbsorb=*/false);
|
2022-04-27 08:53:13 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"Checkbox"_ustr, uno::Any(true));
|
|
|
|
xContentControlProps->setPropertyValue(u"Checked"_ustr, uno::Any(true));
|
|
|
|
xContentControlProps->setPropertyValue(u"CheckedState"_ustr, uno::Any(u"☒"_ustr));
|
|
|
|
xContentControlProps->setPropertyValue(u"UncheckedState"_ustr, uno::Any(u"☐"_ustr));
|
2022-04-27 08:53:13 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-04-27 08:53:13 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "checkbox", u"true");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "checked", u"true");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "checked-state", u"☒");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "unchecked-state", u"☐");
|
2022-04-27 08:53:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testCheckboxContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a checkbox content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-checkbox.fodt");
|
2022-04-27 08:53:13 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
bool bCheckbox{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Checkbox"_ustr) >>= bCheckbox;
|
2022-04-27 08:53:13 +02:00
|
|
|
// Without the accompanying fix in place, this failed, as the checkbox-related attributes were
|
|
|
|
// ignored on import.
|
|
|
|
CPPUNIT_ASSERT(bCheckbox);
|
|
|
|
bool bChecked{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Checked"_ustr) >>= bChecked;
|
2022-04-27 08:53:13 +02:00
|
|
|
CPPUNIT_ASSERT(bChecked);
|
|
|
|
OUString aCheckedState;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"CheckedState"_ustr) >>= aCheckedState;
|
2023-10-06 09:42:38 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"☒"_ustr, aCheckedState);
|
2022-04-27 08:53:13 +02:00
|
|
|
OUString aUncheckedState;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"UncheckedState"_ustr) >>= aUncheckedState;
|
2023-10-06 09:42:38 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"☐"_ustr, aUncheckedState);
|
2022-04-27 08:53:13 +02:00
|
|
|
uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XText> xText = xContentControlRange->getText();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
|
2023-10-06 09:42:38 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"☒"_ustr, xContent->getString());
|
2022-04-27 08:53:13 +02:00
|
|
|
}
|
|
|
|
|
2022-05-09 10:14:29 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testDropdownContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a dropdown content control around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"choose an item"_ustr, /*bAbsorb=*/false);
|
2022-05-09 10:14:29 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
{
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"DropDown"_ustr, uno::Any(true));
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Sequence<beans::PropertyValues> aListItems = {
|
|
|
|
{
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"DisplayText"_ustr, uno::Any(u"red"_ustr)),
|
|
|
|
comphelper::makePropertyValue(u"Value"_ustr, uno::Any(u"R"_ustr)),
|
2022-05-09 10:14:29 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"DisplayText"_ustr, uno::Any(u"green"_ustr)),
|
|
|
|
comphelper::makePropertyValue(u"Value"_ustr, uno::Any(u"G"_ustr)),
|
2022-05-09 10:14:29 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"DisplayText"_ustr, uno::Any(u"blue"_ustr)),
|
|
|
|
comphelper::makePropertyValue(u"Value"_ustr, uno::Any(u"B"_ustr)),
|
2022-05-09 10:14:29 +02:00
|
|
|
},
|
|
|
|
};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"ListItems"_ustr, uno::Any(aListItems));
|
2022-05-09 10:14:29 +02:00
|
|
|
}
|
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-05-09 10:14:29 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "dropdown", u"true");
|
2022-05-09 10:14:29 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - Expected: 1
|
|
|
|
// - Actual : 0
|
|
|
|
// - XPath '//loext:content-control/loext:list-item[1]' number of nodes is incorrect
|
|
|
|
// i.e. the list items were lost on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[1]", "display-text", u"red");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[1]", "value", u"R");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[2]", "display-text", u"green");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[2]", "value", u"G");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[3]", "display-text", u"blue");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control/loext:list-item[3]", "value", u"B");
|
2022-05-09 10:14:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testDropdownContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a dropdown content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-dropdown.fodt");
|
2022-05-09 10:14:29 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
uno::Sequence<beans::PropertyValues> aListItems;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"ListItems"_ustr) >>= aListItems;
|
2022-05-09 10:14:29 +02:00
|
|
|
// Without the accompanying fix in place, this failed with:
|
|
|
|
// - Expected: 3
|
|
|
|
// - Actual : 0
|
|
|
|
// i.e. the list items were lost on import.
|
|
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aListItems.getLength());
|
|
|
|
comphelper::SequenceAsHashMap aMap0(aListItems[0]);
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"red"_ustr, aMap0[u"DisplayText"_ustr].get<OUString>());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"R"_ustr, aMap0[u"Value"_ustr].get<OUString>());
|
2022-05-09 10:14:29 +02:00
|
|
|
comphelper::SequenceAsHashMap aMap1(aListItems[1]);
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"green"_ustr, aMap1[u"DisplayText"_ustr].get<OUString>());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"G"_ustr, aMap1[u"Value"_ustr].get<OUString>());
|
2022-05-09 10:14:29 +02:00
|
|
|
comphelper::SequenceAsHashMap aMap2(aListItems[2]);
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"blue"_ustr, aMap2[u"DisplayText"_ustr].get<OUString>());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"B"_ustr, aMap2[u"Value"_ustr].get<OUString>());
|
2022-05-09 10:14:29 +02:00
|
|
|
uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XText> xText = xContentControlRange->getText();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"choose a color"_ustr, xContent->getString());
|
2022-05-09 10:14:29 +02:00
|
|
|
}
|
|
|
|
|
2022-05-19 09:12:21 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testPictureContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a picture content control around an as-char image:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextGraphic(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.TextGraphicObject"_ustr), uno::UNO_QUERY);
|
|
|
|
xTextGraphic->setPropertyValue(u"AnchorType"_ustr,
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Any(text::TextContentAnchorType_AS_CHARACTER));
|
|
|
|
uno::Reference<text::XTextContent> xTextContent(xTextGraphic, uno::UNO_QUERY);
|
|
|
|
xText->insertTextContent(xCursor, xTextContent, false);
|
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"Picture"_ustr, uno::Any(true));
|
2022-05-19 09:12:21 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-05-19 09:12:21 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-05-19 09:12:21 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - XPath '//loext:content-control' no attribute 'picture' exist
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "picture", u"true");
|
2022-05-19 09:12:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testPictureContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a picture content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-picture.fodt");
|
2022-05-19 09:12:21 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-05-19 09:12:21 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
bool bPicture{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Picture"_ustr) >>= bPicture;
|
2022-05-19 09:12:21 +02:00
|
|
|
// Without the accompanying fix in place, this failed, as the picture attribute was ignored on
|
|
|
|
// import.
|
|
|
|
CPPUNIT_ASSERT(bPicture);
|
|
|
|
}
|
|
|
|
|
2022-05-26 08:25:50 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testDateContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a date content control around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-26 08:25:50 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"choose a date"_ustr, /*bAbsorb=*/false);
|
2022-05-26 08:25:50 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-05-26 08:25:50 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"Date"_ustr, uno::Any(true));
|
|
|
|
xContentControlProps->setPropertyValue(u"DateFormat"_ustr, uno::Any(u"YYYY-MM-DD"_ustr));
|
|
|
|
xContentControlProps->setPropertyValue(u"DateLanguage"_ustr, uno::Any(u"en-US"_ustr));
|
|
|
|
xContentControlProps->setPropertyValue(u"CurrentDate"_ustr,
|
|
|
|
uno::Any(u"2022-05-25T00:00:00Z"_ustr));
|
2022-05-26 08:25:50 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-05-26 08:25:50 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-05-26 08:25:50 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - XPath '//loext:content-control' no attribute 'date' exist
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "date", u"true");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "date-format", u"YYYY-MM-DD");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "date-rfc-language-tag", u"en-US");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "current-date", u"2022-05-25T00:00:00Z");
|
2022-05-26 08:25:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testDateContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a date content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-date.fodt");
|
2022-05-26 08:25:50 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-05-26 08:25:50 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-05-26 08:25:50 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-05-26 08:25:50 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
bool bDate{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Date"_ustr) >>= bDate;
|
2022-05-26 08:25:50 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed, the content control was
|
|
|
|
// imported as a default rich text one.
|
|
|
|
CPPUNIT_ASSERT(bDate);
|
|
|
|
OUString aDateFormat;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"DateFormat"_ustr) >>= aDateFormat;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"YYYY-MM-DD"_ustr, aDateFormat);
|
2022-05-26 08:25:50 +02:00
|
|
|
OUString aDateLanguage;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"DateLanguage"_ustr) >>= aDateLanguage;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"en-US"_ustr, aDateLanguage);
|
2022-05-27 11:38:42 +02:00
|
|
|
OUString aCurrentDate;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"CurrentDate"_ustr) >>= aCurrentDate;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"2022-05-25T00:00:00Z"_ustr, aCurrentDate);
|
2022-05-26 08:25:50 +02:00
|
|
|
}
|
|
|
|
|
2022-07-22 08:35:10 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testPlainTextContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a plain text content control around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-07-22 08:35:10 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"test"_ustr, /*bAbsorb=*/false);
|
2022-07-22 08:35:10 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-07-22 08:35:10 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"PlainText"_ustr, uno::Any(true));
|
2022-07-22 08:35:10 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-07-22 08:35:10 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-07-22 08:35:10 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - XPath '//loext:content-control' no attribute 'plain-text' exist
|
|
|
|
// i.e. the plain text content control was turned into a rich text one on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "plain-text", u"true");
|
2022-07-22 08:35:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testPlainTextContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a plain-text content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-plain-text.fodt");
|
2022-07-22 08:35:10 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-07-22 08:35:10 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-07-22 08:35:10 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-07-22 08:35:10 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
bool bPlainText{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"PlainText"_ustr) >>= bPlainText;
|
2022-07-22 08:35:10 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed, the import result was a
|
|
|
|
// rich text content control (not a plain text one).
|
|
|
|
CPPUNIT_ASSERT(bPlainText);
|
|
|
|
}
|
|
|
|
|
2022-09-22 08:36:51 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testComboBoxContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a combo box content control around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-09-22 08:36:51 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"test"_ustr, /*bAbsorb=*/false);
|
2022-09-22 08:36:51 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-09-22 08:36:51 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"ComboBox"_ustr, uno::Any(true));
|
2022-09-22 08:36:51 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-09-22 08:36:51 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-09-22 08:36:51 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - XPath '//loext:content-control' no attribute 'combobox' exist
|
|
|
|
// i.e. the combo box content control was turned into a drop-down one on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "combobox", u"true");
|
2022-09-22 08:36:51 +02:00
|
|
|
}
|
|
|
|
|
2022-10-18 11:33:20 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlExport)
|
|
|
|
{
|
|
|
|
// Given a document with a content control and its alias around a text portion:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-10-18 11:33:20 +02:00
|
|
|
uno::Reference<text::XText> xText = xTextDocument->getText();
|
|
|
|
uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
|
2024-05-15 13:12:19 +02:00
|
|
|
xText->insertString(xCursor, u"test"_ustr, /*bAbsorb=*/false);
|
2022-10-18 11:33:20 +02:00
|
|
|
xCursor->gotoStart(/*bExpand=*/false);
|
|
|
|
xCursor->gotoEnd(/*bExpand=*/true);
|
|
|
|
uno::Reference<text::XTextContent> xContentControl(
|
2024-05-15 13:12:19 +02:00
|
|
|
xMSF->createInstance(u"com.sun.star.text.ContentControl"_ustr), uno::UNO_QUERY);
|
2022-10-18 11:33:20 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->setPropertyValue(u"Alias"_ustr, uno::Any(u"my alias"_ustr));
|
|
|
|
xContentControlProps->setPropertyValue(u"Tag"_ustr, uno::Any(u"my tag"_ustr));
|
|
|
|
xContentControlProps->setPropertyValue(u"Id"_ustr,
|
|
|
|
uno::Any(static_cast<sal_Int32>(-2147483648)));
|
|
|
|
xContentControlProps->setPropertyValue(u"TabIndex"_ustr, uno::Any(sal_uInt32(3)));
|
|
|
|
xContentControlProps->setPropertyValue(u"Lock"_ustr, uno::Any(u"unlocked"_ustr));
|
2022-10-18 11:33:20 +02:00
|
|
|
xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
|
|
|
|
|
|
|
|
// When exporting to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2022-10-18 11:33:20 +02:00
|
|
|
|
|
|
|
// Then make sure the expected markup is used:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2022-10-18 11:33:20 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - Expression: prop
|
|
|
|
// - XPath '//loext:content-control' no attribute 'alias' exist
|
|
|
|
// i.e. alias was lost on export.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "alias", u"my alias");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "tag", u"my tag");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "id", u"-2147483648");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "tab-index", u"3");
|
|
|
|
assertXPath(pXmlDoc, "//loext:content-control", "lock", u"unlocked");
|
2022-10-18 11:33:20 +02:00
|
|
|
}
|
|
|
|
|
2022-09-22 08:36:51 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testComboBoxContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a plain-text content control:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-combo-box.fodt");
|
2022-09-22 08:36:51 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-09-22 08:36:51 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-09-22 08:36:51 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-09-22 08:36:51 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
bool bComboBox{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"ComboBox"_ustr) >>= bComboBox;
|
2022-09-22 08:36:51 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed, the import result was a
|
|
|
|
// drop-down content control (not a combo box one).
|
|
|
|
CPPUNIT_ASSERT(bComboBox);
|
|
|
|
}
|
|
|
|
|
2022-10-18 11:33:20 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testAliasContentControlImport)
|
|
|
|
{
|
|
|
|
// Given an ODF document with a content control and its alias/tag:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-alias.fodt");
|
2022-10-18 11:33:20 +02:00
|
|
|
|
|
|
|
// Then make sure that the content control is not lost on import:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
2022-10-18 11:33:20 +02:00
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
OUString aPortionType;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
|
2022-10-18 11:33:20 +02:00
|
|
|
uno::Reference<text::XTextContent> xContentControl;
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
|
2022-10-18 11:33:20 +02:00
|
|
|
uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
|
|
|
|
OUString aAlias;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Alias"_ustr) >>= aAlias;
|
2022-10-18 11:33:20 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - Expected: my alias
|
|
|
|
// - Actual :
|
|
|
|
// i.e. the alias was lost on import.
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(u"my alias"_ustr, aAlias);
|
2022-10-18 11:33:20 +02:00
|
|
|
OUString aTag;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Tag"_ustr) >>= aTag;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"my tag"_ustr, aTag);
|
2022-11-16 21:56:51 -05:00
|
|
|
sal_Int32 nId = 0;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Id"_ustr) >>= nId;
|
2022-11-16 21:56:51 -05:00
|
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2147483647), nId);
|
2022-12-02 10:48:46 -05:00
|
|
|
sal_uInt32 nTabIndex;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"TabIndex"_ustr) >>= nTabIndex;
|
2022-12-02 10:48:46 -05:00
|
|
|
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(4), nTabIndex);
|
2022-11-30 13:09:07 -05:00
|
|
|
OUString aLock;
|
2024-05-15 13:12:19 +02:00
|
|
|
xContentControlProps->getPropertyValue(u"Lock"_ustr) >>= aLock;
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"sdtContentLocked"_ustr, aLock);
|
2022-10-18 11:33:20 +02:00
|
|
|
}
|
|
|
|
|
2022-07-26 08:50:03 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testDropdownContentControlAutostyleExport)
|
|
|
|
{
|
|
|
|
// Given a document with a dropdown content control, and formatting that forms an autostyle in
|
|
|
|
// ODT:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"content-control-dropdown.docx");
|
2022-07-26 08:50:03 +02:00
|
|
|
|
|
|
|
// When saving that document to ODT, then make sure no assertion failure happens:
|
2022-10-24 13:43:14 +02:00
|
|
|
uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
|
2022-07-26 08:50:03 +02:00
|
|
|
uno::Sequence<beans::PropertyValue> aStoreProps = comphelper::InitPropertySequence({
|
2024-05-15 13:12:19 +02:00
|
|
|
{ "FilterName", uno::Any(u"writer8"_ustr) },
|
2022-07-26 08:50:03 +02:00
|
|
|
});
|
|
|
|
// Without the accompanying fix in place, this test would have failed, we had duplicated XML
|
|
|
|
// attributes.
|
2022-11-04 17:31:55 +01:00
|
|
|
xStorable->storeToURL(maTempFile.GetURL(), aStoreProps);
|
2022-07-26 08:50:03 +02:00
|
|
|
}
|
|
|
|
|
2023-01-23 20:10:30 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testScaleWidthRedline)
|
|
|
|
{
|
|
|
|
// Given a document with change tracking enabled, one image is part of a delete redline:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"scale-width-redline.fodt");
|
2024-05-15 13:12:19 +02:00
|
|
|
dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
|
|
|
|
dispatchCommand(mxComponent, u".uno:GoToEndOfLine"_ustr, {});
|
|
|
|
dispatchCommand(mxComponent, u".uno:EndOfParaSel"_ustr, {});
|
|
|
|
dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
|
2023-01-23 20:10:30 +01:00
|
|
|
|
|
|
|
// When saving to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2023-01-23 20:10:30 +01:00
|
|
|
|
|
|
|
// Then make sure that a non-zero size is written to the output:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2023-01-23 20:10:30 +01:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - Expected: 6.1728in
|
|
|
|
// - Actual : 0in
|
|
|
|
// i.e. the deleted image had zero size, which is incorrect.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//draw:frame[@draw:name='Image45']", "width", u"6.1728in");
|
2023-01-23 20:10:30 +01:00
|
|
|
}
|
|
|
|
|
2023-01-28 18:43:51 +09:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testThemeExport)
|
|
|
|
{
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2023-01-28 18:43:51 +09:00
|
|
|
|
|
|
|
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
|
|
|
|
uno::Reference<beans::XPropertySet> xPageProps(xDrawPage, uno::UNO_QUERY);
|
|
|
|
|
2023-02-25 19:12:23 +09:00
|
|
|
auto pTheme = std::make_shared<model::Theme>("My Theme");
|
2023-05-03 22:58:47 +09:00
|
|
|
auto pColorSet = std::make_shared<model::ColorSet>("My Color Scheme");
|
2023-01-28 18:43:51 +09:00
|
|
|
pColorSet->add(model::ThemeColorType::Dark1, 0x101010);
|
|
|
|
pColorSet->add(model::ThemeColorType::Light1, 0x202020);
|
|
|
|
pColorSet->add(model::ThemeColorType::Dark2, 0x303030);
|
|
|
|
pColorSet->add(model::ThemeColorType::Light2, 0x404040);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent1, 0x505050);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent2, 0x606060);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent3, 0x707070);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent4, 0x808080);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent5, 0x909090);
|
|
|
|
pColorSet->add(model::ThemeColorType::Accent6, 0xa0a0a0);
|
|
|
|
pColorSet->add(model::ThemeColorType::Hyperlink, 0xb0b0b0);
|
|
|
|
pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0xc0c0c0);
|
2023-05-03 22:58:47 +09:00
|
|
|
pTheme->setColorSet(pColorSet);
|
2023-01-28 18:43:51 +09:00
|
|
|
|
2023-02-25 19:12:23 +09:00
|
|
|
uno::Reference<util::XTheme> xTheme = model::theme::createXTheme(pTheme);
|
2024-05-15 13:12:19 +02:00
|
|
|
xPageProps->setPropertyValue(u"Theme"_ustr, uno::Any(xTheme));
|
2023-01-28 18:43:51 +09:00
|
|
|
|
|
|
|
// Export to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2023-01-28 18:43:51 +09:00
|
|
|
|
|
|
|
// Check if the 12 colors are written in the XML:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
|
2023-11-19 13:21:42 +01:00
|
|
|
OString aThemePath = "//office:styles/loext:theme/loext:theme-colors/loext:color"_ostr;
|
2023-05-25 13:15:41 +09:00
|
|
|
assertXPath(pXmlDoc, aThemePath, 12);
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, aThemePath + "[1]", "name", u"dark1");
|
|
|
|
assertXPath(pXmlDoc, aThemePath + "[1]", "color", u"#101010");
|
|
|
|
assertXPath(pXmlDoc, aThemePath + "[2]", "name", u"light1");
|
|
|
|
assertXPath(pXmlDoc, aThemePath + "[2]", "color", u"#202020");
|
|
|
|
assertXPath(pXmlDoc, aThemePath + "[12]", "name", u"followed-hyperlink");
|
|
|
|
assertXPath(pXmlDoc, aThemePath + "[12]", "color", u"#c0c0c0");
|
2023-01-28 18:43:51 +09:00
|
|
|
}
|
|
|
|
|
2023-02-23 08:21:46 +01:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testFloatingTableExport)
|
|
|
|
{
|
|
|
|
// Given a document with a floating table:
|
2024-10-28 14:36:38 +01:00
|
|
|
loadFromURL(u"private:factory/swriter"_ustr);
|
2023-02-23 08:21:46 +01:00
|
|
|
// Insert a table:
|
|
|
|
uno::Sequence<beans::PropertyValue> aArgs = {
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"Rows"_ustr, static_cast<sal_Int32>(1)),
|
|
|
|
comphelper::makePropertyValue(u"Columns"_ustr, static_cast<sal_Int32>(1)),
|
2023-02-23 08:21:46 +01:00
|
|
|
};
|
2024-05-15 13:12:19 +02:00
|
|
|
dispatchCommand(mxComponent, u".uno:InsertTable"_ustr, aArgs);
|
2023-02-23 08:21:46 +01:00
|
|
|
// Select it:
|
2024-05-15 13:12:19 +02:00
|
|
|
dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
|
2023-02-23 08:21:46 +01:00
|
|
|
// Wrap in a fly:
|
|
|
|
aArgs = {
|
2024-05-15 13:12:19 +02:00
|
|
|
comphelper::makePropertyValue(u"AnchorType"_ustr, static_cast<sal_uInt16>(0)),
|
2023-02-23 08:21:46 +01:00
|
|
|
};
|
2024-05-15 13:12:19 +02:00
|
|
|
dispatchCommand(mxComponent, u".uno:InsertFrame"_ustr, aArgs);
|
2023-02-23 08:21:46 +01:00
|
|
|
// Mark it as a floating table:
|
|
|
|
uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xFrame(
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextFramesSupplier->getTextFrames()->getByName(u"Frame1"_ustr), uno::UNO_QUERY);
|
|
|
|
xFrame->setPropertyValue(u"IsSplitAllowed"_ustr, uno::Any(true));
|
2023-02-23 08:21:46 +01:00
|
|
|
|
|
|
|
// When saving to ODT:
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"writer8"_ustr);
|
2023-02-23 08:21:46 +01:00
|
|
|
|
|
|
|
// Then make sure we write a floating table, not a textframe containing a table:
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2023-02-23 08:21:46 +01:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - XPath '//draw:frame' no attribute 'may-break-between-pages' exist
|
|
|
|
// i.e. no floating table was exported.
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//draw:frame", "may-break-between-pages", u"true");
|
2023-02-23 08:21:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testFloatingTableImport)
|
|
|
|
{
|
|
|
|
// Given a document with a floating table (loext:may-break-between-pages="true"), when importing
|
|
|
|
// that document:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"floattable.fodt");
|
2023-02-23 08:21:46 +01:00
|
|
|
|
|
|
|
// Then make sure that the matching text frame property is set:
|
|
|
|
uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xFrame(
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextFramesSupplier->getTextFrames()->getByName(u"Frame1"_ustr), uno::UNO_QUERY);
|
2023-02-23 08:21:46 +01:00
|
|
|
bool bIsSplitAllowed = false;
|
|
|
|
// Without the accompanying fix in place, this test would have failed, the property was false.
|
2024-05-15 13:12:19 +02:00
|
|
|
xFrame->getPropertyValue(u"IsSplitAllowed"_ustr) >>= bIsSplitAllowed;
|
2023-02-23 08:21:46 +01:00
|
|
|
CPPUNIT_ASSERT(bIsSplitAllowed);
|
|
|
|
}
|
|
|
|
|
2023-03-03 18:04:46 +03:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testParagraphScopedTabDistance)
|
|
|
|
{
|
|
|
|
// Given a document with paragraph scoped default tab stop distance (loext:tab-stop-distance="0.5cm")
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"paragraph-tab-stop-distance.fodp");
|
2023-03-03 18:04:46 +03:00
|
|
|
|
|
|
|
uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0),
|
|
|
|
uno::UNO_QUERY_THROW);
|
|
|
|
|
|
|
|
uno::Reference<beans::XPropertySet> xShape(xPage->getByIndex(0), uno::UNO_QUERY);
|
|
|
|
uno::Reference<text::XText> xText
|
|
|
|
= uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY_THROW)->getText();
|
|
|
|
|
|
|
|
uno::Reference<container::XEnumerationAccess> paraEnumAccess(xText, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> paraEnum(paraEnumAccess->createEnumeration());
|
|
|
|
uno::Reference<text::XTextRange> xParagraph(paraEnum->nextElement(), uno::UNO_QUERY_THROW);
|
|
|
|
|
|
|
|
uno::Reference<container::XEnumerationAccess> runEnumAccess(xParagraph, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> runEnum = runEnumAccess->createEnumeration();
|
|
|
|
uno::Reference<text::XTextRange> xRun(runEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);
|
|
|
|
|
|
|
|
// Make sure the tab stop default distance is imported correctly
|
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - Expected: 10000
|
|
|
|
// - Actual : 0
|
2024-05-15 13:12:19 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(
|
|
|
|
static_cast<sal_Int32>(10000),
|
|
|
|
xPropSet->getPropertyValue(u"ParaTabStopDefaultDistance"_ustr).get<sal_Int32>());
|
2023-03-03 18:04:46 +03:00
|
|
|
|
|
|
|
// Save the imported file to test the export too
|
2024-05-15 13:12:19 +02:00
|
|
|
save(u"impress8"_ustr);
|
2023-03-03 18:04:46 +03:00
|
|
|
|
|
|
|
// Then make sure we write the tab-stop-distance
|
2024-05-15 13:12:19 +02:00
|
|
|
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//style:style[@style:name='P1']/style:paragraph-properties",
|
|
|
|
"tab-stop-distance", u"10cm");
|
2023-03-03 18:04:46 +03:00
|
|
|
|
2024-10-03 11:40:13 +05:00
|
|
|
assertXPath(pXmlDoc, "//text:p[@text:style-name='P1']");
|
2023-03-03 18:04:46 +03:00
|
|
|
}
|
|
|
|
|
2023-08-14 08:10:51 +02:00
|
|
|
CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testNestedSpans)
|
|
|
|
{
|
|
|
|
// Given a document with a first paragraph that has a nested span, the outer span setting the
|
|
|
|
// boldness:
|
|
|
|
// When importing that document:
|
2024-01-03 11:49:02 +06:00
|
|
|
loadFromFile(u"nested-spans.odt");
|
2023-08-14 08:10:51 +02:00
|
|
|
|
|
|
|
// Then make sure the text portion is bold, not normal:
|
|
|
|
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xTextDocument->getText(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
|
|
|
|
uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
|
|
|
|
uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
|
|
|
|
float fWeight{};
|
2024-05-15 13:12:19 +02:00
|
|
|
xTextPortion->getPropertyValue(u"CharWeight"_ustr) >>= fWeight;
|
2023-08-14 08:10:51 +02:00
|
|
|
// Without the accompanying fix in place, this test would have failed with:
|
|
|
|
// - Expected: 150 (awt::FontWeight::BOLD)
|
|
|
|
// - Actual : 100 (awt::FontWeight::NORMAL)
|
|
|
|
// i.e. the boldness was lost on import.
|
|
|
|
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, fWeight);
|
|
|
|
}
|
|
|
|
|
2020-08-03 21:03:43 +02:00
|
|
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|