summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorSkyler Grey <skyler.grey@collabora.com>2023-09-14 08:48:16 +0000
committerMiklos Vajna <vmiklos@collabora.com>2023-10-20 08:53:34 +0200
commit32c588dd1164aa2fc4c8120ddb74bd510cc082f9 (patch)
tree080aeedb6ead986f54080c75c9edad53cd452c9f /writerfilter
parentd52982f4b3ba3f54adf21a9f185c726fb1a3db9a (diff)
tdf#86790: Add support for a word-style styleref
STYLEREF is a field type in Word which changes its content based on nearby paragraphs. For example, upon creating a styleref referencing "Heading 1" you will see the text of the nearest "Heading 1"-styled paragraph that is above the field. This patch implements STYLEREF in Writer as a cross-reference. By using "insert>cross-reference>styles" you'll be presented with a list of styles. Selecting one and clicking "insert" will create a field which has text from the "most relevant" instance of the style. To find the most relevant instance we first search up for paragraphs with the style, and if there are any we take the closest. If there weren't any, we search down for paragraphs with the style. This patch also updates our use of STYLEREF for chapters exported to docx by using it for all chapters not only those in headers and footers. This allows us to approximate more chapter field functionality even when moving between Writer and Word. Finally, this patch adds some tests for STYLEREF: - testTdf86790 tests that the "sample file with STYLEREF" document from tdf#86790 has the correct fields - testStyleRefSearchUp tests that the STYLEREF searches up when there are bits of text both above and below it - testStyleRefSearchDown tests that the STYLEREF searches down when there are bits of text below it only - testMarginalStyleRef tests that the STYLEREF searches from the page top when it is placed in a footer - testFootnotetyleRef tests that the STYLEREF searches from the reference mark when it is placed in a footnote Still TODO: - [ ] Update documentation - [ ] Implement reverse-searching (\l) and nondelimiter suppression (\t) - Probably these 2 will be in a followup patch Change-Id: I25dd7a6940abee5651a784b9059fe23b32547d6c Signed-off-by: Skyler Grey <skyler.grey@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157456 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx55
-rw-r--r--writerfilter/source/dmapper/FieldTypes.hxx5
2 files changed, 50 insertions, 10 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 67fe56280c18..fd27e92510d5 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -5829,7 +5829,7 @@ static const FieldConversionMap_t & lcl_GetFieldConversion()
{"SEQ", {"SetExpression", FIELD_SEQ }},
{"SET", {"SetExpression", FIELD_SET }},
// {"SKIPIF", {"", FIELD_SKIPIF }},
-// {"STYLEREF", {"", FIELD_STYLEREF }},
+ {"STYLEREF", {"GetReference", FIELD_STYLEREF }},
{"SUBJECT", {"DocInfo.Subject", FIELD_SUBJECT }},
{"SYMBOL", {"", FIELD_SYMBOL }},
{"TEMPLATE", {"TemplateName", FIELD_TEMPLATE }},
@@ -7519,9 +7519,11 @@ void DomainMapper_Impl::CloseFieldCommand()
break;
case FIELD_PAGEREF:
case FIELD_REF:
+ case FIELD_STYLEREF:
if (xFieldProperties.is() && !IsInTOC())
{
bool bPageRef = aIt->second.eFieldId == FIELD_PAGEREF;
+ bool bStyleRef = aIt->second.eFieldId == FIELD_STYLEREF;
// Do we need a GetReference (default) or a GetExpression field?
uno::Reference< text::XTextFieldsSupplier > xFieldsSupplier( GetTextDocument(), uno::UNO_QUERY );
@@ -7531,12 +7533,50 @@ void DomainMapper_Impl::CloseFieldCommand()
"com.sun.star.text.FieldMaster.SetExpression."
+ sFirstParam))
{
- xFieldProperties->setPropertyValue(
- getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
- uno::Any( sal_Int16(text::ReferenceFieldSource::BOOKMARK)) );
- xFieldProperties->setPropertyValue(
- getPropertyName(PROP_SOURCE_NAME),
- uno::Any(sFirstParam) );
+ if (bStyleRef)
+ {
+ xFieldProperties->setPropertyValue(
+ getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
+ uno::Any(sal_Int16(text::ReferenceFieldSource::STYLE)));
+
+ OUString sStyleSheetName
+ = GetStyleSheetTable()->ConvertStyleName(sFirstParam, true);
+
+ uno::Any aStyleDisplayName;
+
+ uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(
+ GetTextDocument(), uno::UNO_QUERY_THROW);
+ uno::Reference<container::XNameAccess> xStyleFamilies
+ = xStylesSupplier->getStyleFamilies();
+ uno::Reference<container::XNameAccess> xStyles;
+ xStyleFamilies->getByName(getPropertyName(PROP_PARAGRAPH_STYLES))
+ >>= xStyles;
+ uno::Reference<css::beans::XPropertySet> xStyle;
+
+ try
+ {
+ xStyles->getByName(sStyleSheetName) >>= xStyle;
+ aStyleDisplayName = xStyle->getPropertyValue("DisplayName");
+ }
+ catch (css::container::NoSuchElementException)
+ {
+ aStyleDisplayName <<= sStyleSheetName;
+ }
+
+ xFieldProperties->setPropertyValue(
+ getPropertyName(PROP_SOURCE_NAME), aStyleDisplayName);
+ }
+ else
+ {
+ xFieldProperties->setPropertyValue(
+ getPropertyName(PROP_REFERENCE_FIELD_SOURCE),
+ uno::Any( sal_Int16(text::ReferenceFieldSource::BOOKMARK)) );
+
+ xFieldProperties->setPropertyValue(
+ getPropertyName(PROP_SOURCE_NAME),
+ uno::Any(sFirstParam));
+ }
+
sal_Int16 nFieldPart = (bPageRef ? text::ReferenceFieldPart::PAGE : text::ReferenceFieldPart::TEXT);
OUString sValue;
if( lcl_FindInCommand( pContext->GetCommand(), 'p', sValue ))
@@ -7631,7 +7671,6 @@ void DomainMapper_Impl::CloseFieldCommand()
handleFieldSet(pContext, xFieldInterface, xFieldProperties);
break;
case FIELD_SKIPIF : break;
- case FIELD_STYLEREF : break;
case FIELD_SUBJECT :
{
if (!sFirstParam.isEmpty())
diff --git a/writerfilter/source/dmapper/FieldTypes.hxx b/writerfilter/source/dmapper/FieldTypes.hxx
index a907a7af6c22..144d1efe1370 100644
--- a/writerfilter/source/dmapper/FieldTypes.hxx
+++ b/writerfilter/source/dmapper/FieldTypes.hxx
@@ -209,8 +209,9 @@ enum FieldId
*/
,FIELD_SKIPIF
/* STYLEREF stylename \* MERGEFORMAT ->
- not imported in old ww8 filter
- todo: add an equivalent field type
+ implemented using GetReference, but some switches are not implemented yet
+ \l isn't implemented
+ \t isn't implemented
*/
,FIELD_STYLEREF
/* SUBJECT subject \* Defaultswitch \* MERGEFORMAT ->