[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - 6 commits - include/sfx2 sc/source sfx2/source sw/qa sw/source writerfilter/source
Vasily Melenchuk
Vasily.Melenchuk at cib.de
Fri Nov 10 01:23:20 UTC 2017
Rebased ref, commits from common ancestor:
commit aad3a938f9bb929869ed50482c9e747079bbc69e
Author: Vasily Melenchuk <Vasily.Melenchuk at cib.de>
Date: Fri Aug 18 22:14:08 2017 +0300
tdf#43017: Support for DOCX hyperlinks character properties
Here goes a bunch of related changes:
1. Create new character style based on current character properties
2. Apply created style to hyperlink object
3. Fixes to predefined style names usage in w:rPr
4. Disable style usage for hyperlinks in TOC: they will receive later
anoter styles
Reviewed-on: https://gerrit.libreoffice.org/41784
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
(cherry picked from commit eaa9cf6a3069fba3d82c046f0041bfb537d9e648)
Conflicts:
sw/qa/extras/ooxmlimport/ooxmlimport.cxx
writerfilter/source/dmapper/DomainMapper_Impl.hxx
Change-Id: I1a228992eb7c1e259a6a811aa7f959debaae4f35
diff --git a/sw/qa/extras/ooxmlimport/data/tdf43017.docx b/sw/qa/extras/ooxmlimport/data/tdf43017.docx
new file mode 100644
index 000000000000..c3372e11a0c8
Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/tdf43017.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index b55b17c05053..a9be7f45cb75 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -3286,6 +3286,17 @@ DECLARE_OOXMLIMPORT_TEST(testTdf96218, "tdf96218.docx")
CPPUNIT_ASSERT(!getProperty<bool>(getShape(1), "IsFollowingTextFlow"));
}
+DECLARE_OOXMLIMPORT_TEST(testTdf43017, "tdf43017.docx")
+{
+ uno::Reference<text::XTextRange> xParagraph = getParagraph(1);
+ uno::Reference<text::XTextRange> xText = getRun(xParagraph, 2, "kick the bucket");
+
+ // Ensure that hyperlink text color is not blue (0x0000ff), but default (-1)
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Hyperlink color should be black!",
+ sal_Int32(-1), getProperty<sal_Int32>(xText, "CharColor"));
+}
+
+// tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 46aef6bf81c7..eec33d46246f 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2155,11 +2155,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
{
OUString sConvertedName( m_pImpl->GetStyleSheetTable()->ConvertStyleName( sStringValue, true ) );
// First check if the style exists in the document.
- StyleSheetEntryPtr pEntry = m_pImpl->GetStyleSheetTable( )->FindStyleSheetByStyleName( sConvertedName );
+ StyleSheetEntryPtr pEntry = m_pImpl->GetStyleSheetTable( )->FindStyleSheetByConvertedStyleName( sConvertedName );
bool bExists = pEntry.get( ) && ( pEntry->nStyleTypeCode == STYLE_TYPE_CHAR );
-
- // Add the property if the style exists
- if ( bExists && m_pImpl->GetTopContext() )
+ // Add the property if the style exists, but do not add it elements in TOC:
+ // they will receive later another style references from TOC
+ if ( bExists && m_pImpl->GetTopContext() && !m_pImpl->IsInTOC())
m_pImpl->GetTopContext()->Insert( PROP_CHAR_STYLE_NAME, uno::makeAny( sConvertedName ) );
}
break;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 19d6f1a82985..c5ca29a02510 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1283,7 +1283,18 @@ void DomainMapper_Impl::appendTextPortion( const OUString& rString, const Proper
}
}
else
+ {
+ if (IsOpenField() && GetTopFieldContext()->GetFieldId() == FIELD_HYPERLINK)
+ {
+ // It is content of hyperlink field. We need to create and remember
+ // character style for later applying to hyperlink
+ PropertyValueVector_t aProps = comphelper::sequenceToContainer< PropertyValueVector_t >(GetTopContext()->GetPropertyValues());
+ OUString sHyperlinkStyleName = GetStyleSheetTable()->getOrCreateCharStyle(aProps, /*bAlwaysCreate=*/false);
+ GetTopFieldContext()->SetHyperlinkStyle(sHyperlinkStyleName);
+ }
+
xTextRange = xTextAppend->appendTextPortion(rString, aValues);
+ }
}
CheckRedline( xTextRange );
@@ -3572,6 +3583,8 @@ void DomainMapper_Impl::CloseFieldCommand()
aFieldConversionMap.find(std::get<0>(field));
if(aIt != aFieldConversionMap.end())
{
+ pContext->SetFieldId(aIt->second.eFieldId);
+
bool bCreateEnhancedField = false;
uno::Reference< beans::XPropertySet > xFieldProperties;
bool bCreateField = true;
@@ -4547,6 +4560,14 @@ void DomainMapper_Impl::PopFieldContext()
xCrsrProperties->setPropertyValue("VisitedCharStyleName",uno::makeAny(sDisplayName));
xCrsrProperties->setPropertyValue("UnvisitedCharStyleName",uno::makeAny(sDisplayName));
}
+ else
+ {
+ if (!pContext->GetHyperlinkStyle().isEmpty())
+ {
+ xCrsrProperties->setPropertyValue("VisitedCharStyleName", uno::makeAny(pContext->GetHyperlinkStyle()));
+ xCrsrProperties->setPropertyValue("UnvisitedCharStyleName", uno::makeAny(pContext->GetHyperlinkStyle()));
+ }
+ }
}
else if(m_bStartGenericField)
{
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index ad96d4c77ef9..49b61d261b61 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -137,19 +137,21 @@ public:
* --------------------------------------------------*/
class FieldContext
{
- bool m_bFieldCommandCompleted;
+ bool m_bFieldCommandCompleted;
css::uno::Reference<css::text::XTextRange> m_xStartRange;
- OUString m_sCommand;
+ OUString m_sCommand;
OUString m_sResult;
+ boost::optional<FieldId> m_eFieldId;
bool m_bFieldLocked;
css::uno::Reference<css::text::XTextField> m_xTextField;
- css::uno::Reference<css::text::XFormField> m_xFormField;
+ css::uno::Reference<css::text::XFormField> m_xFormField;
css::uno::Reference<css::beans::XPropertySet> m_xTOC;
css::uno::Reference<css::beans::XPropertySet> m_xTC; // TOX entry
css::uno::Reference<css::beans::XPropertySet> m_xCustomField;
OUString m_sHyperlinkURL;
+ OUString m_sHyperlinkStyle;
FFDataHandler::Pointer_t m_pFFDataHandler;
FormControlHelper::Pointer_t m_pFormControlHelper;
/// (Character) properties of the field itself.
@@ -164,6 +166,9 @@ public:
void AppendCommand(const OUString& rPart);
const OUString& GetCommand() const {return m_sCommand; }
+ void SetFieldId(FieldId eFieldId ) { m_eFieldId = eFieldId; }
+ boost::optional<FieldId> GetFieldId() const { return m_eFieldId; }
+
void AppendResult(OUString const& rResult) { m_sResult += rResult; }
const OUString& GetResult() const { return m_sResult; }
@@ -188,6 +193,8 @@ public:
void SetHyperlinkURL( const OUString& rURL ) { m_sHyperlinkURL = rURL; }
const OUString& GetHyperlinkURL() { return m_sHyperlinkURL; }
+ void SetHyperlinkStyle(const OUString& rStyle) { m_sHyperlinkStyle = rStyle; }
+ const OUString& GetHyperlinkStyle() { return m_sHyperlinkStyle; }
void setFFDataHandler(FFDataHandler::Pointer_t pFFDataHandler) { m_pFFDataHandler = pFFDataHandler; }
const FFDataHandler::Pointer_t& getFFDataHandler() const { return m_pFFDataHandler; }
@@ -204,7 +211,7 @@ struct TextAppendContext
css::uno::Reference<css::text::XTextAppend> xTextAppend;
css::uno::Reference<css::text::XTextRange> xInsertPosition;
css::uno::Reference<css::text::XParagraphCursor> xCursor;
- ParagraphPropertiesPtr pLastParagraphProperties;
+ ParagraphPropertiesPtr pLastParagraphProperties;
TextAppendContext(const css::uno::Reference<css::text::XTextAppend>& xAppend, const css::uno::Reference<css::text::XTextCursor>& xCur)
: xTextAppend(xAppend)
@@ -679,6 +686,8 @@ public:
void PopPageHeaderFooter();
bool IsInHeaderFooter() const { return m_bInHeaderFooterImport; }
+ bool IsInTOC() const { return m_bStartTOC; }
+
void PushFootOrEndnote( bool bIsFootnote );
void PopFootOrEndnote();
bool IsInFootOrEndnote() const { return m_bInFootOrEndnote; }
commit 7d9938e315447629061dc1dbe057233e66579f91
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
Date: Thu Nov 9 17:55:14 2017 +0100
tdf#42346: DOC export of cross-references to objects
Same solution which was used for DOCX export:
98bc7215935f1eb2e0dc6f1db826d8e729430c13
Reviewed-on: https://gerrit.libreoffice.org/44502
Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>
Tested-by: Tamás Zolnai <tamas.zolnai at collabora.com>
(cherry picked from commit cbaa72d6e963847a4b98526430cd928bc7928fdd)
Change-Id: I8af46db003a6192c6adaae1a35dff58744919eee
Reviewed-on: https://gerrit.libreoffice.org/44560
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
diff --git a/sw/qa/extras/ww8export/data/object_cross_reference.odt b/sw/qa/extras/ww8export/data/object_cross_reference.odt
new file mode 100755
index 000000000000..9eaca352b68c
Binary files /dev/null and b/sw/qa/extras/ww8export/data/object_cross_reference.odt differ
diff --git a/sw/qa/extras/ww8export/data/table_cross_reference.odt b/sw/qa/extras/ww8export/data/table_cross_reference.odt
new file mode 100755
index 000000000000..95f33139c522
Binary files /dev/null and b/sw/qa/extras/ww8export/data/table_cross_reference.odt differ
diff --git a/sw/qa/extras/ww8export/data/table_cross_reference_custom_format.odt b/sw/qa/extras/ww8export/data/table_cross_reference_custom_format.odt
new file mode 100755
index 000000000000..1c41e364c6e5
Binary files /dev/null and b/sw/qa/extras/ww8export/data/table_cross_reference_custom_format.odt differ
diff --git a/sw/qa/extras/ww8export/ww8export.cxx b/sw/qa/extras/ww8export/ww8export.cxx
index f31bbda02a06..7985f479f0fa 100644
--- a/sw/qa/extras/ww8export/ww8export.cxx
+++ b/sw/qa/extras/ww8export/ww8export.cxx
@@ -726,6 +726,393 @@ DECLARE_WW8EXPORT_TEST(testTdf99474, "tdf99474.odt")
CPPUNIT_ASSERT_EQUAL(COL_AUTO, charColor);
}
+DECLARE_OOXMLEXPORT_TEST( testTableCrossReference, "table_cross_reference.odt" )
+{
+ // tdf#42346: Cross references to tables were not saved
+ // MSO uses simple bookmarks for referencing table caption, so we do the same by export
+ if (!mbExported)
+ return;
+
+ // Check whether we have all the neccessary bookmarks exported and imported back
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), xBookmarksByIdx->getCount());
+ uno::Reference<container::XNameAccess> xBookmarksByName(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_number_only"));
+
+ // Check bookmark text ranges
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 1: Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xRange->getString());
+ }
+
+ // Check reference fields
+ uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+
+ sal_uInt16 nIndex = 0;
+ while (xFields->hasMoreElements())
+ {
+ uno::Reference<lang::XServiceInfo> xServiceInfo(xFields->nextElement(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropertySet(xServiceInfo, uno::UNO_QUERY);
+ switch (nIndex)
+ {
+ // Full reference to table caption
+ case 0:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 1: Table caption"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_full"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Reference to table number
+ case 1:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_number_only"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Reference to caption only
+ case 2:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_caption_only"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Reference to category and number
+ case 3:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 1"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_label_and_number"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Reference to page of the table
+ case 4:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_full"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Page style reference / exported as simple page reference
+ case 5:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_full"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ // Above / bellow reference
+ case 6:
+ {
+ CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextField.GetReference"));
+ OUString sValue;
+ sal_Int16 nValue;
+ xPropertySet->getPropertyValue("CurrentPresentation") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("above"), sValue);
+ xPropertySet->getPropertyValue("SourceName") >>= sValue;
+ CPPUNIT_ASSERT_EQUAL(OUString("Ref_Table0_full"), sValue);
+ xPropertySet->getPropertyValue("SequenceNumber") >>= nValue;
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nValue);
+ break;
+ }
+ default:
+ break;
+ }
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), nIndex);
+}
+
+DECLARE_OOXMLEXPORT_TEST( testTableCrossReferenceCustomFormat, "table_cross_reference_custom_format.odt" )
+{
+ // tdf#42346: Cross references to tables were not saved
+ // Check also captions with custom formatting
+ if (!mbExported)
+ return;
+
+ // Check whether we have all the neccessary bookmarks exported and imported back
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(16), xBookmarksByIdx->getCount());
+ uno::Reference<container::XNameAccess> xBookmarksByName(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table0_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table1_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table1_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table1_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table1_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table2_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table2_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table2_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table2_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table3_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table3_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table3_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Table3_number_only"));
+
+ // Check bookmark text ranges
+ // First table's caption
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1. Table: Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1. Table"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table0_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xRange->getString());
+ }
+ // Second table's caption
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table1_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("2. TableTable caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table1_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("2. Table"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table1_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table1_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), xRange->getString());
+ }
+ // Third table's caption
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table2_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("3) Table Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table2_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("3) Table"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table2_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table2_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xRange->getString());
+ }
+ // Fourth table's caption
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table3_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 4- Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table3_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table 4"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table3_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table caption"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Table3_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("4"), xRange->getString());
+ }
+}
+
+DECLARE_OOXMLEXPORT_TEST( testObjectCrossReference, "object_cross_reference.odt" )
+{
+ // tdf#42346: Cross references to objects were not saved
+ // MSO uses simple bookmarks for referencing table caption, so we do the same by export
+ if (!mbExported)
+ return;
+
+ // Check whether we have all the neccessary bookmarks exported and imported back
+ uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(15), xBookmarksByIdx->getCount());
+ uno::Reference<container::XNameAccess> xBookmarksByName(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Drawing0_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Drawing0_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Drawing0_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Drawing0_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Drawing1_full"));
+
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Illustration0_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Illustration0_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Illustration0_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Illustration0_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Illustration1_caption_only"));
+
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Text0_full"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Text0_label_and_number"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Text0_caption_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Text0_number_only"));
+ CPPUNIT_ASSERT(xBookmarksByName->hasByName("Ref_Text1_label_and_number"));
+
+ // Check bookmark text ranges
+ // Cross references to shapes
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Drawing0_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Drawing 1: A rectangle"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Drawing0_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Drawing 1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Drawing0_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("A rectangle"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Drawing0_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Drawing1_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Drawing 2: a circle"), xRange->getString());
+ }
+
+ // Cross references to pictures
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Illustration0_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Illustration 1: A picture"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Illustration0_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Illustration 1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Illustration0_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("A picture"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Illustration0_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Illustration1_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("an other image"), xRange->getString());
+ }
+
+ // Cross references to text frames
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Text0_full"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Text 1: A frame"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Text0_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Text 1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Text0_caption_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("A frame"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Text0_number_only"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xRange->getString());
+ }
+ {
+ uno::Reference<text::XTextContent> xContent(xBookmarksByName->getByName("Ref_Text1_label_and_number"), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xRange(xContent->getAnchor(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Text 2"), xRange->getString());
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
index dc32dd36d8fe..86b468198ed9 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -169,10 +169,10 @@ public:
virtual void EmptyParagraph() = 0;
/// Start of the text run.
- virtual void StartRun( const SwRedlineData* pRedlineData, bool bSingleEmptyRun = false ) = 0;
+ virtual void StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun = false ) = 0;
/// End of the text run.
- virtual void EndRun( const SwTextNode* pNode, sal_Int32 nPos ) = 0;
+ virtual void EndRun( const SwTextNode* pNode, sal_Int32 nPos, bool bLastRun = false ) = 0;
/// Called before we start outputting the attributes.
virtual void StartRunProperties() = 0;
@@ -209,7 +209,8 @@ public:
virtual void FieldVanish( const OUString& rText, ww::eField eType ) = 0;
- virtual void GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter) = 0;
+ /// MSO uses bookmarks to reference sequence fields, so we need to generate these additional bookmarks during export
+ void GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter);
void StartTOX( const SwSection& rSect );
@@ -625,6 +626,9 @@ protected:
virtual bool AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark );
+ /// Insert a bookmark inside the currently processed parargaph.
+ virtual void WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos ) = 0;
+
ww8::GridColsPtr GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
ww8::WidthsPtr GetColumnWidths( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index e8cdfc86182c..76de5cabb222 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -117,8 +117,6 @@
#include <IDocumentSettingAccess.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
-#include <IDocumentFieldsAccess.hxx>
-#include <reffld.hxx>
#include <osl/file.hxx>
#include <vcl/embeddedfontshelper.hxx>
@@ -603,10 +601,9 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
if( !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen() )
m_bParagraphOpened = false;
- // Clear gererated bookmarks
- m_aBookmarksWithPosStart.clear();
- m_aBookmarksWithPosEnd.clear();
-
+ // Clear bookmarks of the current paragraph
+ m_aBookmarksOfParagraphStart.clear();
+ m_aBookmarksOfParagraphEnd.clear();
}
void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken,
@@ -1103,7 +1100,7 @@ bool DocxAttributeOutput::IsFlyProcessingPostponed()
return m_bPostponedProcessingFly;
}
-void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSingleEmptyRun*/ )
+void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32 /*nPos*/, bool /*bSingleEmptyRun*/ )
{
// Don't start redline data here, possibly there is a hyperlink later, and
// that has to be started first.
@@ -1122,7 +1119,7 @@ void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bS
m_pSerializer->mark(Tag_StartRun_3); // let's call it "postponed text"
}
-void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos)
+void DocxAttributeOutput::EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool /*bLastRun*/)
{
int nFieldsInPrevHyperlink = m_nFieldsInHyperlink;
// Reset m_nFieldsInHyperlink if a new hyperlink is about to start
@@ -1401,9 +1398,9 @@ void DocxAttributeOutput::DoWriteBookmarkTagEnd(const OUString & bookmarkName)
}
}
-void DocxAttributeOutput::DoWriteBookmarkStartIfExist(sal_Int32 nPos)
+void DocxAttributeOutput::DoWriteBookmarkStartIfExist(sal_Int32 nRunPos)
{
- auto aRange = m_aBookmarksWithPosStart.equal_range(nPos);
+ auto aRange = m_aBookmarksOfParagraphStart.equal_range(nRunPos);
for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
{
DoWriteBookmarkTagStart(aIter->second);
@@ -1413,9 +1410,9 @@ void DocxAttributeOutput::DoWriteBookmarkStartIfExist(sal_Int32 nPos)
}
}
-void DocxAttributeOutput::DoWriteBookmarkEndIfExist(sal_Int32 nPos)
+void DocxAttributeOutput::DoWriteBookmarkEndIfExist(sal_Int32 nRunPos)
{
- auto aRange = m_aBookmarksWithPosEnd.equal_range(nPos);
+ auto aRange = m_aBookmarksOfParagraphEnd.equal_range(nRunPos);
for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
{
// Get the id of the bookmark
@@ -2524,7 +2521,7 @@ void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, co
m_pSerializer->endElementNS( XML_w, XML_rubyPr );
m_pSerializer->startElementNS( XML_w, XML_rt, FSEND );
- StartRun( nullptr );
+ StartRun( nullptr, nPos );
StartRunProperties( );
SwWW8AttrIter aAttrIt( m_rExport, rNode );
aAttrIt.OutAttr( nPos, true );
@@ -2540,7 +2537,7 @@ void DocxAttributeOutput::StartRuby( const SwTextNode& rNode, sal_Int32 nPos, co
m_pSerializer->endElementNS( XML_w, XML_rt );
m_pSerializer->startElementNS( XML_w, XML_rubyBase, FSEND );
- StartRun( nullptr );
+ StartRun( nullptr, nPos );
}
void DocxAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos)
@@ -2549,7 +2546,7 @@ void DocxAttributeOutput::EndRuby(const SwTextNode& rNode, sal_Int32 nPos)
EndRun( &rNode, nPos );
m_pSerializer->endElementNS( XML_w, XML_rubyBase );
m_pSerializer->endElementNS( XML_w, XML_ruby );
- StartRun(nullptr); // open Run again so OutputTextNode loop can close it
+ StartRun(nullptr, nPos); // open Run again so OutputTextNode loop can close it
}
bool DocxAttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
@@ -2576,6 +2573,12 @@ bool DocxAttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTar
return bBookMarkOnly;
}
+void DocxAttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos )
+{
+ m_aBookmarksOfParagraphStart.insert(std::pair<sal_Int32, OUString>(nFirstRunPos, rName));
+ m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName));
+}
+
bool DocxAttributeOutput::StartURL( const OUString& rUrl, const OUString& rTarget )
{
OUString sMark;
@@ -6988,176 +6991,6 @@ bool DocxAttributeOutput::PlaceholderField( const SwField* pField )
return false; // do not expand
}
-void DocxAttributeOutput::GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter)
-{
- if (const SwpHints* pTextAttrs = rNode.GetpSwpHints())
- {
- for( size_t i = 0; i < pTextAttrs->Count(); ++i )
- {
- const SwTextAttr* pHt = pTextAttrs->Get(i);
- if (pHt->GetAttr().Which() == RES_TXTATR_FIELD)
- {
- const SwFormatField& rField = static_cast<const SwFormatField&>(pHt->GetAttr());
- const SwField* pField = rField.GetField();
- // Need to have bookmarks only for sequence fields
- if (pField && pField->GetTyp()->Which() == RES_SETEXPFLD && pField->GetSubType() == nsSwGetSetExpType::GSE_SEQ)
- {
- const sal_uInt16 nSeqFieldNumber = static_cast<const SwSetExpField*>(pField)->GetSeqNumber();
- const OUString sObjectName = static_cast<const SwSetExpFieldType*>(pField->GetTyp())->GetName();
- const SwFieldTypes* pFieldTypes = m_rExport.m_pDoc->getIDocumentFieldsAccess().GetFieldTypes();
- bool bHaveFullBkm = false;
- bool bHaveLabelAndNumberBkm = false;
- bool bHaveCaptionOnlyBkm = false;
- bool bHaveNumberOnlyBkm = false;
- bool bRunSplittedAtSep = false;
- for( auto pFieldType : *pFieldTypes )
- {
- if( RES_GETREFFLD == pFieldType->Which() )
- {
- SwIterator<SwFormatField,SwFieldType> aIter( *pFieldType );
- for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
- {
- SwGetRefField* pRefField = static_cast<SwGetRefField*>(pFormatField->GetField());
- // If we have a reference to the current sequence field
- if(pRefField->GetSeqNo() == nSeqFieldNumber && pRefField->GetSetRefName() == sObjectName)
- {
- // Need to create a seperate run for separator character
- SwWW8AttrIter aLocalAttrIter( m_rExport, rNode );
- const OUString aText = rNode.GetText();
- const sal_Int32 nCategoryStart = aText.indexOf(pRefField->GetSetRefName());
- const sal_Int32 nPosBeforeSeparator = std::max(nCategoryStart, pHt->GetStart());
- bool bCategoryFirst = nCategoryStart < pHt->GetStart();
- sal_Int32 nSeparatorPos = 0;
- if (bCategoryFirst)
- {
- nSeparatorPos = aLocalAttrIter.WhereNext();
- while (nSeparatorPos <= nPosBeforeSeparator)
- {
- aLocalAttrIter.NextPos();
- nSeparatorPos = aLocalAttrIter.WhereNext();
- }
- }
- else
- {
- nSeparatorPos = nCategoryStart + pRefField->GetSetRefName().getLength();
- }
- sal_Int32 nRefTextPos = 0;
- if(nSeparatorPos < aText.getLength())
- {
- nRefTextPos = SwGetExpField::GetReferenceTextPos(pHt->GetFormatField(), *m_rExport.m_pDoc, nSeparatorPos);
- if(nRefTextPos != nSeparatorPos)
- {
- if(!bRunSplittedAtSep)
- {
- if(!bCategoryFirst)
- rAttrIter.SplitRun(nSeparatorPos);
- rAttrIter.SplitRun(nRefTextPos);
- bRunSplittedAtSep = true;
- }
- if(!bCategoryFirst)
- aLocalAttrIter.SplitRun(nSeparatorPos);
- aLocalAttrIter.SplitRun(nRefTextPos);
- }
- else if (bCategoryFirst)
- {
- if(!bRunSplittedAtSep)
- {
- rAttrIter.SplitRun(nSeparatorPos);
- bRunSplittedAtSep = true;
- }
- aLocalAttrIter.SplitRun(nSeparatorPos);
- }
- }
- // Generate bookmarks on the right position
- OUString sName("Ref_" + pRefField->GetSetRefName());
- sName += OUString::number(pRefField->GetSeqNo());
- switch (pRefField->GetFormat())
- {
- case REF_PAGE:
- case REF_PAGE_PGDESC:
- case REF_CONTENT:
- case REF_UPDOWN:
- sName += "_full";
- if(!bHaveFullBkm)
- {
- sal_Int32 nLastAttrStart = 0;
- sal_Int32 nActAttr = aLocalAttrIter.WhereNext();
- while (nActAttr < rNode.GetText().getLength())
- {
- nLastAttrStart = nActAttr;
- aLocalAttrIter.NextPos();
- nActAttr = aLocalAttrIter.WhereNext();
- }
- WriteBookmarks_Impl( sName, std::min(nCategoryStart, pHt->GetStart()), nLastAttrStart );
- bHaveFullBkm = true;
- }
- break;
- case REF_ONLYNUMBER:
- {
- sName += "_label_and_number";
- if(!bHaveLabelAndNumberBkm)
- {
- if(bCategoryFirst)
- WriteBookmarks_Impl( sName, std::min(nCategoryStart, pHt->GetStart()), std::max(nCategoryStart, pHt->GetStart()) );
- else
- {
- // Find the last run which contains category text
- SwWW8AttrIter aLocalAttrIter2( m_rExport, rNode );
- sal_Int32 nCatLastRun = 0;
- sal_Int32 nNextAttr = aLocalAttrIter2.WhereNext();
- while (nNextAttr < nSeparatorPos)
- {
- nCatLastRun = nNextAttr;
- aLocalAttrIter2.NextPos();
- nNextAttr = aLocalAttrIter2.WhereNext();
- }
- WriteBookmarks_Impl( sName, pHt->GetStart(), nCatLastRun );
- }
- bHaveLabelAndNumberBkm = true;
- }
- break;
- }
- case REF_ONLYCAPTION:
- {
- sName += "_caption_only";
- if(!bHaveCaptionOnlyBkm)
- {
- // Find last run
- sal_Int32 nLastAttrStart = 0;
- sal_Int32 nActAttr = aLocalAttrIter.WhereNext();
- while (nActAttr < rNode.GetText().getLength())
- {
- nLastAttrStart = nActAttr;
- aLocalAttrIter.NextPos();
- nActAttr = aLocalAttrIter.WhereNext();
- }
- WriteBookmarks_Impl( sName, nRefTextPos, nLastAttrStart );
- bHaveCaptionOnlyBkm = true;
- }
- break;
- }
- case REF_ONLYSEQNO:
- {
- sName += "_number_only";
- if(!bHaveNumberOnlyBkm)
- {
- WriteBookmarks_Impl( sName, pHt->GetStart(), pHt->GetStart() );
- bHaveNumberOnlyBkm = true;
- }
- break;
- }
- }
- }
- }
- }
- }
- return;
- }
- }
- }
- }
-}
-
void DocxAttributeOutput::WritePendingPlaceholder()
{
if( pendingPlaceholder == nullptr )
@@ -7264,12 +7097,6 @@ void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
rEnds.clear();
}
-void DocxAttributeOutput::WriteBookmarks_Impl( const OUString& rName, sal_Int32 nWithStartPos, sal_Int32 nWithEndPos )
-{
- m_aBookmarksWithPosStart.insert(std::pair<sal_Int32, OUString>(nWithStartPos, rName));
- m_aBookmarksWithPosEnd.insert(std::pair<sal_Int32, OUString>(nWithEndPos, rName));
-}
-
void DocxAttributeOutput::WriteAnnotationMarks_Impl( std::vector< OUString >& rStarts,
std::vector< OUString >& rEnds )
{
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 64fa4238e617..c76b8a671f2d 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -163,10 +163,10 @@ public:
virtual void EndParagraphProperties(const SfxItemSet& rParagraphMarkerProperties, const SwRedlineData* pRedlineData, const SwRedlineData* pRedlineParagraphMarkerDeleted, const SwRedlineData* pRedlineParagraphMarkerInserted) override;
/// Start of the text run.
- virtual void StartRun( const SwRedlineData* pRedlineData, bool bSingleEmptyRun = false ) override;
+ virtual void StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun = false ) override;
/// End of the text run.
- virtual void EndRun(const SwTextNode* pNode, sal_Int32 nPos) override;
+ virtual void EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool bLastRun = false) override;
/// Called before we start outputting the attributes.
virtual void StartRunProperties() override;
@@ -370,7 +370,6 @@ public:
void WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark );
void WriteBookmarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds );
- void WriteBookmarks_Impl( const OUString& rName, sal_Int32 nWithStartPos, sal_Int32 nWithEndPos );
void WriteAnnotationMarks_Impl( std::vector< OUString >& rStarts, std::vector< OUString >& rEnds );
void PushRelIdCache();
void PopRelIdCache();
@@ -682,6 +681,8 @@ protected:
virtual bool AnalyzeURL( const OUString& rURL, const OUString& rTarget, OUString* pLinkURL, OUString* pMark ) override;
+ virtual void WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos ) override;
+
/// Reference to the export, where to get the data from
DocxExport &m_rExport;
@@ -697,8 +698,8 @@ private:
void DoWriteBookmarkTagEnd(const OUString & bookmarkName);
void DoWriteBookmarksStart();
void DoWriteBookmarksEnd();
- void DoWriteBookmarkStartIfExist(sal_Int32 nPos);
- void DoWriteBookmarkEndIfExist(sal_Int32 nPos);
+ void DoWriteBookmarkStartIfExist(sal_Int32 nRunPos);
+ void DoWriteBookmarkEndIfExist(sal_Int32 nRunPos);
void DoWritePermissionTagStart(const OUString & permission);
void DoWritePermissionTagEnd(const OUString & permission);
@@ -730,7 +731,6 @@ private:
void CmdField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos const & rInfos, bool bWriteRun );
void EndField_Impl( const SwTextNode* pNode, sal_Int32 nPos, FieldInfos& rInfos );
void DoWriteFieldRunProperties( const SwTextNode* pNode, sal_Int32 nPos, bool bWriteCombChars = false );
- virtual void GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter) override;
static void AddToAttrList( css::uno::Reference<sax_fastparser::FastAttributeList>& pAttrList, sal_Int32 nAttrName, const sal_Char* sAttrValue );
static void AddToAttrList( css::uno::Reference<sax_fastparser::FastAttributeList>& pAttrList, sal_Int32 nArgs, ... );
@@ -788,9 +788,9 @@ private:
std::vector<OUString> m_rBookmarksStart;
std::vector<OUString> m_rBookmarksEnd;
- /// Bookmarks with position to output
- std::multimap<sal_Int32, OUString> m_aBookmarksWithPosStart;
- std::multimap<sal_Int32, OUString> m_aBookmarksWithPosEnd;
+ /// Bookmarks of the current paragraph
+ std::multimap<sal_Int32, OUString> m_aBookmarksOfParagraphStart;
+ std::multimap<sal_Int32, OUString> m_aBookmarksOfParagraphEnd;
/// Permissions to output
std::vector<OUString> m_rPermissionsStart;
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 3f62a6c56310..7e32fe727519 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -1442,7 +1442,7 @@ void DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTy
sal_Int32 nAktPos = 0;
const sal_Int32 nEnd = aStr.getLength();
do {
- AttrOutput().StartRun( nullptr );
+ AttrOutput().StartRun( nullptr, 0 );
const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index ee3ff68665e7..880bf36f12f7 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -376,7 +376,7 @@ void RtfAttributeOutput::EndParagraphProperties(const SfxItemSet& /*rParagraphMa
m_rExport.Strm().WriteCharPtr(m_aStyles.makeStringAndClear().getStr());
}
-void RtfAttributeOutput::StartRun(const SwRedlineData* pRedlineData, bool bSingleEmptyRun)
+void RtfAttributeOutput::StartRun(const SwRedlineData* pRedlineData, sal_Int32 /*nPos*/, bool bSingleEmptyRun)
{
SAL_INFO("sw.rtf", OSL_THIS_FUNC << ", bSingleEmptyRun: " << bSingleEmptyRun);
@@ -391,7 +391,7 @@ void RtfAttributeOutput::StartRun(const SwRedlineData* pRedlineData, bool bSingl
OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
}
-void RtfAttributeOutput::EndRun(const SwTextNode* /*pNode*/, sal_Int32 /*nPos*/)
+void RtfAttributeOutput::EndRun(const SwTextNode* /*pNode*/, sal_Int32 /*nPos*/, bool /*bLastRun*/)
{
m_aRun->append(SAL_NEWLINE_STRING);
m_aRun.appendAndClear(m_aRunText);
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx
index 82e2817e1a03..9dfebef27a86 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -62,10 +62,10 @@ public:
virtual void EndParagraphProperties(const SfxItemSet& rParagraphMarkerProperties, const SwRedlineData* pRedlineData, const SwRedlineData* pRedlineParagraphMarkerDeleted, const SwRedlineData* pRedlineParagraphMarkerInserted) override;
/// Start of the text run.
- virtual void StartRun(const SwRedlineData* pRedlineData, bool bSingleEmptyRun = false) override;
+ virtual void StartRun(const SwRedlineData* pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun = false) override;
/// End of the text run.
- void EndRun(const SwTextNode* pNode, sal_Int32 nPos) override;
+ void EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool bLastRun = false) override;
/// Called before we start outputting the attributes.
virtual void StartRunProperties() override;
@@ -217,7 +217,7 @@ public:
void WriteBookmarks_Impl(std::vector< OUString >& rStarts, std::vector< OUString >& rEnds);
void WriteAnnotationMarks_Impl(std::vector< OUString >& rStarts, std::vector< OUString >& rEnds);
void WriteHeaderFooter_Impl(const SwFrameFormat& rFormat, bool bHeader, const sal_Char* pStr, bool bTitlepg);
- void GenerateBookmarksForSequenceField(const SwTextNode& /*rNode*/, SwWW8AttrIter& /*rAttrIter*/) override {};
+ void WriteBookmarkInActParagraph( const OUString& /*rName*/, sal_Int32 /*nFirstRunPos*/, sal_Int32 /*nLastRunPos*/ ) override {};
protected:
/// Output frames - the implementation.
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 33b67ea5e627..cbc0a777154f 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -975,6 +975,12 @@ bool WW8AttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarg
return bBookMarkOnly;
}
+void WW8AttributeOutput::WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos )
+{
+ m_aBookmarksOfParagraphStart.insert(std::pair<sal_Int32, OUString>(nFirstRunPos, rName));
+ m_aBookmarksOfParagraphEnd.insert(std::pair<sal_Int32, OUString>(nLastRunPos, rName));
+}
+
bool WW8AttributeOutput::StartURL( const OUString &rUrl, const OUString &rTarget )
{
INetURLObject aURL( rUrl );
@@ -2166,8 +2172,7 @@ void MSWordExportBase::OutputTextNode( const SwTextNode& rNode )
}
// Call this before write out fields and runs
- if(GetExportFormat() == ExportFormat::DOCX)
- AttrOutput().GenerateBookmarksForSequenceField(rNode, aAttrIter);
+ AttrOutput().GenerateBookmarksForSequenceField(rNode, aAttrIter);
const OUString& aStr( rNode.GetText() );
@@ -2192,14 +2197,14 @@ void MSWordExportBase::OutputTextNode( const SwTextNode& rNode )
sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
// Is this the only run in this paragraph and it's empty?
bool bSingleEmptyRun = nAktPos == 0 && nNextAttr == 0;
- AttrOutput().StartRun( pRedlineData, bSingleEmptyRun );
-
- if( m_nTextTyp == TXT_FTN || m_nTextTyp == TXT_EDN )
- AttrOutput().FootnoteEndnoteRefTag();
+ AttrOutput().StartRun( pRedlineData, nAktPos, bSingleEmptyRun );
if( nNextAttr > nEnd )
nNextAttr = nEnd;
+ if( m_nTextTyp == TXT_FTN || m_nTextTyp == TXT_EDN )
+ AttrOutput().FootnoteEndnoteRefTag();
+
/*
1) If there is a text node and an overlapping anchor, then write them in two different
runs and not as part of the same run.
@@ -2461,9 +2466,9 @@ void MSWordExportBase::OutputTextNode( const SwTextNode& rNode )
if( bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame )
{
- AttrOutput().EndRun(&rNode, nAktPos);
+ AttrOutput().EndRun(&rNode, nAktPos, nNextAttr == nEnd);
//write the postponed text run
- AttrOutput().StartRun( pRedlineData, bSingleEmptyRun );
+ AttrOutput().StartRun( pRedlineData, nAktPos, bSingleEmptyRun );
AttrOutput().SetAnchorIsLinkedToNode( false );
AttrOutput().ResetFlyProcessingFlag();
if (0 != nEnd)
@@ -2473,16 +2478,16 @@ void MSWordExportBase::OutputTextNode( const SwTextNode& rNode )
AttrOutput().EndRunProperties( pRedlineData );
}
AttrOutput().RunText( aSavedSnippet, eChrSet );
- AttrOutput().EndRun(&rNode, nAktPos);
+ AttrOutput().EndRun(&rNode, nAktPos, nNextAttr == nEnd);
}
else if( bPostponeWritingText && !aSavedSnippet.isEmpty() )
{
//write the postponed text run
AttrOutput().RunText( aSavedSnippet, eChrSet );
- AttrOutput().EndRun(&rNode, nAktPos);
+ AttrOutput().EndRun(&rNode, nAktPos, nNextAttr == nEnd);
}
else
- AttrOutput().EndRun(&rNode, nAktPos);
+ AttrOutput().EndRun(&rNode, nAktPos, nNextAttr == nEnd);
nAktPos = nNextAttr;
UpdatePosition( &aAttrIter, nAktPos, nEnd );
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 85bf4ea3a312..8e8c02496560 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -1514,6 +1514,12 @@ void WW8Export::AppendBookmark( const OUString& rName )
m_pBkmks->Append( nSttCP, rName );
}
+void WW8Export::AppendBookmarkEndWithCorrection( const OUString& rName )
+{
+ sal_uLong nEndCP = Fc2Cp( Strm().Tell() );
+ m_pBkmks->Append( nEndCP - 1, rName );
+}
+
boost::optional<SvxBrushItem> MSWordExportBase::getBackground()
{
boost::optional<SvxBrushItem> oRet;
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index ff25dedd1c3e..b5633010789a 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -1036,6 +1036,7 @@ public:
virtual void AppendBookmarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_Int32 nLen ) override;
virtual void AppendBookmark( const OUString& rName ) override;
+ void AppendBookmarkEndWithCorrection( const OUString& rName );
virtual void AppendAnnotationMarks( const SwTextNode& rNd, sal_Int32 nAktPos, sal_Int32 nLen ) override;
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 3250808165a8..33b1bc42ee66 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -981,6 +981,10 @@ void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTe
m_rWW8Export.pO->clear();
}
}
+
+ // Clear bookmarks of the current paragraph
+ m_aBookmarksOfParagraphStart.clear();
+ m_aBookmarksOfParagraphEnd.clear();
}
void WW8AttributeOutput::StartRunProperties()
@@ -989,7 +993,7 @@ void WW8AttributeOutput::StartRunProperties()
m_nFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;
}
-void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSingleEmptyRun*/ )
+void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool /*bSingleEmptyRun*/ )
{
if (pRedlineData)
{
@@ -1004,6 +1008,13 @@ void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSi
}
}
}
+
+ /// Insert bookmarks started at this run
+ auto aRange = m_aBookmarksOfParagraphStart.equal_range(nPos);
+ for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
+ {
+ GetExport().AppendBookmark(BookmarkToWord(aIter->second));
+ }
}
void WW8AttributeOutput::OnTOXEnding()
@@ -1011,6 +1022,19 @@ void WW8AttributeOutput::OnTOXEnding()
mbOnTOXEnding = true;
}
+void WW8AttributeOutput::EndRun( const SwTextNode* /*pNode*/, sal_Int32 nPos, bool bLastRun )
+{
+ /// Insert bookmarks ended after this run
+ auto aRange = m_aBookmarksOfParagraphEnd.equal_range(nPos);
+ for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)
+ {
+ if(bLastRun)
+ GetExport().AppendBookmarkEndWithCorrection(BookmarkToWord(aIter->second));
+ else
+ GetExport().AppendBookmark(BookmarkToWord(aIter->second));
+ }
+}
+
void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
{
Redline( pRedlineData );
@@ -1950,6 +1974,179 @@ static bool lcl_IsHyperlinked(const SwForm& rForm, sal_uInt16 nTOXLvl)
return bRes;
}
+void AttributeOutputBase::GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter)
+{
+ if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) // Not implemented for RTF
+ return;
+
+ if (const SwpHints* pTextAttrs = rNode.GetpSwpHints())
+ {
+ for( size_t i = 0; i < pTextAttrs->Count(); ++i )
+ {
+ const SwTextAttr* pHt = pTextAttrs->Get(i);
+ if (pHt->GetAttr().Which() == RES_TXTATR_FIELD)
+ {
+ const SwFormatField& rField = static_cast<const SwFormatField&>(pHt->GetAttr());
+ const SwField* pField = rField.GetField();
+ // Need to have bookmarks only for sequence fields
+ if (pField && pField->GetTyp()->Which() == RES_SETEXPFLD && pField->GetSubType() == nsSwGetSetExpType::GSE_SEQ)
+ {
+ const sal_uInt16 nSeqFieldNumber = static_cast<const SwSetExpField*>(pField)->GetSeqNumber();
+ const OUString sObjectName = static_cast<const SwSetExpFieldType*>(pField->GetTyp())->GetName();
+ const SwFieldTypes* pFieldTypes = GetExport().m_pDoc->getIDocumentFieldsAccess().GetFieldTypes();
+ bool bHaveFullBkm = false;
+ bool bHaveLabelAndNumberBkm = false;
+ bool bHaveCaptionOnlyBkm = false;
+ bool bHaveNumberOnlyBkm = false;
+ bool bRunSplittedAtSep = false;
+ for( auto pFieldType : *pFieldTypes )
+ {
+ if( RES_GETREFFLD == pFieldType->Which() )
+ {
+ SwIterator<SwFormatField,SwFieldType> aIter( *pFieldType );
+ for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
+ {
+ SwGetRefField* pRefField = static_cast<SwGetRefField*>(pFormatField->GetField());
+ // If we have a reference to the current sequence field
+ if(pRefField->GetSeqNo() == nSeqFieldNumber && pRefField->GetSetRefName() == sObjectName)
+ {
+ // Need to create a seperate run for separator character
+ SwWW8AttrIter aLocalAttrIter( GetExport(), rNode ); // We need a local iterator having the right number of runs
+ const OUString aText = rNode.GetText();
+ const sal_Int32 nCategoryStart = aText.indexOf(pRefField->GetSetRefName());
+ const sal_Int32 nPosBeforeSeparator = std::max(nCategoryStart, pHt->GetStart());
+ bool bCategoryFirst = nCategoryStart < pHt->GetStart();
+ sal_Int32 nSeparatorPos = 0;
+ if (bCategoryFirst)
+ {
+ nSeparatorPos = aLocalAttrIter.WhereNext();
+ while (nSeparatorPos <= nPosBeforeSeparator)
+ {
+ aLocalAttrIter.NextPos();
+ nSeparatorPos = aLocalAttrIter.WhereNext();
+ }
+ }
+ else
+ {
+ nSeparatorPos = nCategoryStart + pRefField->GetSetRefName().getLength();
+ }
+ sal_Int32 nRefTextPos = 0;
+ if(nSeparatorPos < aText.getLength())
+ {
+ nRefTextPos = SwGetExpField::GetReferenceTextPos(pHt->GetFormatField(), *GetExport().m_pDoc, nSeparatorPos);
+ if(nRefTextPos != nSeparatorPos)
+ {
+ if(!bRunSplittedAtSep)
+ {
+ if(!bCategoryFirst)
+ rAttrIter.SplitRun(nSeparatorPos);
+ rAttrIter.SplitRun(nRefTextPos);
+ bRunSplittedAtSep = true;
+ }
+ if(!bCategoryFirst)
+ aLocalAttrIter.SplitRun(nSeparatorPos);
+ aLocalAttrIter.SplitRun(nRefTextPos);
+ }
+ else if (bCategoryFirst)
+ {
+ if(!bRunSplittedAtSep)
+ {
+ rAttrIter.SplitRun(nSeparatorPos);
+ bRunSplittedAtSep = true;
+ }
+ aLocalAttrIter.SplitRun(nSeparatorPos);
+ }
+ }
+ // Generate bookmarks on the right position
+ OUString sName("Ref_" + pRefField->GetSetRefName());
+ sName += OUString::number(pRefField->GetSeqNo());
+ switch (pRefField->GetFormat())
+ {
+ case REF_PAGE:
+ case REF_PAGE_PGDESC:
+ case REF_CONTENT:
+ case REF_UPDOWN:
+ sName += "_full";
+ if(!bHaveFullBkm)
+ {
+ sal_Int32 nLastAttrStart = 0;
+ sal_Int32 nActAttr = aLocalAttrIter.WhereNext();
+ while (nActAttr < rNode.GetText().getLength())
+ {
+ nLastAttrStart = nActAttr;
+ aLocalAttrIter.NextPos();
+ nActAttr = aLocalAttrIter.WhereNext();
+ }
+ WriteBookmarkInActParagraph( sName, std::min(nCategoryStart, pHt->GetStart()), nLastAttrStart );
+ bHaveFullBkm = true;
+ }
+ break;
+ case REF_ONLYNUMBER:
+ {
+ sName += "_label_and_number";
+ if(!bHaveLabelAndNumberBkm)
+ {
+ if(bCategoryFirst)
+ WriteBookmarkInActParagraph( sName, std::min(nCategoryStart, pHt->GetStart()), std::max(nCategoryStart, pHt->GetStart()) );
+ else
+ {
+ // Find the last run which contains category text
+ SwWW8AttrIter aLocalAttrIter2( GetExport(), rNode );
+ sal_Int32 nCatLastRun = 0;
+ sal_Int32 nNextAttr = aLocalAttrIter2.WhereNext();
+ while (nNextAttr < nSeparatorPos)
+ {
+ nCatLastRun = nNextAttr;
+ aLocalAttrIter2.NextPos();
+ nNextAttr = aLocalAttrIter2.WhereNext();
+ }
+ WriteBookmarkInActParagraph( sName, pHt->GetStart(), nCatLastRun );
+ }
+ bHaveLabelAndNumberBkm = true;
+ }
+ break;
+ }
+ case REF_ONLYCAPTION:
+ {
+ sName += "_caption_only";
+ if(!bHaveCaptionOnlyBkm)
+ {
+ // Find last run
+ sal_Int32 nLastAttrStart = 0;
+ sal_Int32 nActAttr = aLocalAttrIter.WhereNext();
+ while (nActAttr < rNode.GetText().getLength())
+ {
+ nLastAttrStart = nActAttr;
+ aLocalAttrIter.NextPos();
+ nActAttr = aLocalAttrIter.WhereNext();
+ }
+ WriteBookmarkInActParagraph( sName, nRefTextPos, nLastAttrStart );
+ bHaveCaptionOnlyBkm = true;
+ }
+ break;
+ }
+ case REF_ONLYSEQNO:
+ {
+ sName += "_number_only";
+ if(!bHaveNumberOnlyBkm)
+ {
+ WriteBookmarkInActParagraph( sName, pHt->GetStart(), pHt->GetStart() );
+ bHaveNumberOnlyBkm = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
+}
+
void AttributeOutputBase::StartTOX( const SwSection& rSect )
{
if ( const SwTOXBase* pTOX = rSect.GetTOXBase() )
@@ -2805,8 +3002,8 @@ void AttributeOutputBase::TextField( const SwFormatField& rField )
break;
case REF_SEQUENCEFLD:
{
- // Have this only for DOCX format by now
- if(!(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::DOCX))
+ // Not implemented for RTF
+ if(!(GetExport().GetExportFormat() != MSWordExportBase::ExportFormat::RTF))
break;
switch (pField->GetFormat())
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx
index e2a978fcb4ac..dc21f2a2fb28 100644
--- a/sw/source/filter/ww8/ww8attributeoutput.hxx
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -49,14 +49,14 @@ public:
/// Start of the text run.
///
- virtual void StartRun( const SwRedlineData* pRedlineData, bool bSingleEmptyRun = false ) override;
+ virtual void StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool bSingleEmptyRun = false ) override;
virtual void OnTOXEnding() override;
/// End of the text run.
///
/// No-op for binary filters.
- virtual void EndRun(const SwTextNode* , sal_Int32 ) override {}
+ virtual void EndRun(const SwTextNode* pNode, sal_Int32 nPos, bool bLastRun = false) override;
/// Before we start outputting the attributes.
virtual void StartRunProperties() override;
@@ -84,8 +84,6 @@ public:
virtual void FieldVanish( const OUString& rText, ww::eField eType ) override;
- virtual void GenerateBookmarksForSequenceField(const SwTextNode& /*rNode*/, SwWW8AttrIter& /*rAttrIter*/) override {};
-
/// Output redlining.
virtual void Redline( const SwRedlineData* pRedline ) override;
@@ -429,6 +427,8 @@ protected:
virtual bool AnalyzeURL( const OUString& rURL, const OUString& rTarget, OUString* pLinkURL, OUString* pMark ) override;
+ virtual void WriteBookmarkInActParagraph( const OUString& rName, sal_Int32 nFirstRunPos, sal_Int32 nLastRunPos ) override;
+
/// Reference to the export, where to get the data from
WW8Export &m_rWW8Export;
@@ -457,6 +457,10 @@ protected:
bool mbOnTOXEnding;
+ /// Bookmarks of the current paragraph
+ std::multimap<sal_Int32, OUString> m_aBookmarksOfParagraphStart;
+ std::multimap<sal_Int32, OUString> m_aBookmarksOfParagraphEnd;
+
public:
explicit WW8AttributeOutput( WW8Export &rWW8Export )
: AttributeOutputBase()
commit c73a2449fb245993e6cc53e16cc3f2eea8930c85
Author: Szymon Kłos <szymon.klos at collabora.com>
Date: Tue Nov 7 20:39:06 2017 +0100
tdf#100922 Refactor Custom Properties page
This commit solves problems with big number of entries.
Window is loaded quickly and is responsive even with
over a thousand custom properties.
Change-Id: I4745c69aaff95661ca930e303ab65591e374a24d
Reviewed-on: https://gerrit.libreoffice.org/44429
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/44497
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
diff --git a/include/sfx2/dinfdlg.hxx b/include/sfx2/dinfdlg.hxx
index 3761f229c019..2b9b0d4b59ba 100644
--- a/include/sfx2/dinfdlg.hxx
+++ b/include/sfx2/dinfdlg.hxx
@@ -380,6 +380,7 @@ public:
struct CustomPropertyLine
{
+ ScopedVclPtr<VclGrid> m_aLine;
ScopedVclPtr<ComboBox> m_aNameBox;
ScopedVclPtr<CustomPropertiesTypeBox> m_aTypeBox;
ScopedVclPtr<CustomPropertiesEdit> m_aValueEdit;
@@ -391,12 +392,12 @@ struct CustomPropertyLine
ScopedVclPtr<CustomPropertiesYesNoButton> m_aYesNoButton;
ScopedVclPtr<CustomPropertiesRemoveButton> m_aRemoveButton;
- bool m_bIsDate;
- bool m_bIsRemoved;
- bool m_bTypeLostFocus;
+ bool m_bIsDate;
+ bool m_bTypeLostFocus;
CustomPropertyLine( vcl::Window* pParent );
- void SetRemoved();
+ void Clear();
+ void Hide();
};
// class CustomPropertiesWindow ------------------------------------------
@@ -404,30 +405,26 @@ struct CustomPropertyLine
class CustomPropertiesWindow : public vcl::Window
{
private:
+ VclPtr<HeaderBar> m_pHeaderBar;
+ VclPtr<ScrollBar> m_pScrollBar;
VclPtr<FixedText> m_pHeaderAccName;
VclPtr<FixedText> m_pHeaderAccType;
VclPtr<FixedText> m_pHeaderAccValue;
- VclPtr<ComboBox> m_aNameBox;
- VclPtr<ListBox> m_aTypeBox;
- VclPtr<Edit> m_aValueEdit;
- VclPtr<DateField> m_aDateField;
- VclPtr<TimeField> m_aTimeField;
- VclPtr<Edit> m_aDurationField;
- VclPtr<PushButton> m_aEditButton;
- VclPtr<CustomPropertiesYesNoButton> m_aYesNoButton;
- VclPtr<ImageButton> m_aRemoveButton;
-
+ sal_Int32 m_nWidgetHeight;
+ sal_Int32 m_nRemoveButtonWidth;
+ sal_Int32 m_nTypeBoxWidth;
sal_Int32 m_nLineHeight;
sal_Int32 m_nScrollPos;
- std::vector< CustomPropertyLine* > m_aCustomPropertiesLines;
+ std::vector<CustomProperty*> m_aCustomProperties;
+ std::vector<CustomPropertyLine*> m_aCustomPropertiesLines;
CustomPropertyLine* m_pCurrentLine;
SvNumberFormatter m_aNumberFormatter;
Idle m_aEditLoseFocusIdle;
Idle m_aBoxLoseFocusIdle;
Link<void*,void> m_aRemovedHdl;
- DECL_STATIC_LINK_TYPED( CustomPropertiesWindow, TypeHdl, ListBox&, void );
+ DECL_LINK_TYPED( TypeHdl, ListBox&, void );
DECL_LINK_TYPED( RemoveHdl, Button*, void );
DECL_LINK_TYPED( EditLoseFocusHdl, Control&, void );
DECL_LINK_TYPED( BoxLoseFocusHdl, Control&, void );
@@ -438,28 +435,36 @@ private:
bool IsLineValid( CustomPropertyLine* pLine ) const;
void ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox );
+ void CreateNewLine();
+ void ReloadLinesContent();
+ void StoreCustomProperties();
+ sal_uInt32 GetCurrentDataModelPosition() const { return -1 * m_nScrollPos / m_nLineHeight; }
public:
CustomPropertiesWindow(vcl::Window* pParent,
FixedText *pHeaderAccName,
FixedText *pHeaderAccType,
FixedText *pHeaderAccValue);
+ void Init(HeaderBar* pHeaderBar, ScrollBar* pScrollBar);
virtual ~CustomPropertiesWindow();
virtual void dispose() override;
- bool InitControls( HeaderBar* pHeaderBar, const ScrollBar* pScrollBar );
+ virtual void Resize() override;
+ void SetWidgetWidths(const CustomPropertyLine* pLine) const;
+ sal_uInt16 GetExistingLineCount() const { return m_aCustomPropertiesLines.size(); }
+ sal_uInt16 GetTotalLineCount() const { return m_aCustomProperties.size(); }
sal_uInt16 GetVisibleLineCount() const;
- inline sal_Int32 GetLineHeight() const { return m_nLineHeight; }
- void AddLine( const OUString& sName, css::uno::Any& rAny );
+ void SetVisibleLineCount(sal_uInt32 nCount);
+ sal_Int32 GetLineHeight() const { return m_nLineHeight; }
+ void AddLine( const OUString& sName, css::uno::Any const & rAny );
bool AreAllLinesValid() const;
void ClearAllLines();
void DoScroll( sal_Int32 nNewPos );
css::uno::Sequence< css::beans::PropertyValue >
- GetCustomProperties() const;
+ GetCustomProperties();
+ void SetCustomProperties(const std::vector<CustomProperty*>& rProperties);
void SetRemovedHdl( const Link<void*,void>& rLink ) { m_aRemovedHdl = rLink; }
-
- void updateLineWidth();
};
// class CustomPropertiesControl -----------------------------------------
@@ -483,14 +488,17 @@ public:
virtual ~CustomPropertiesControl();
virtual void dispose() override;
- void AddLine( const OUString& sName, css::uno::Any& rAny, bool bInteractive );
+ void AddLine(const OUString& sName, css::uno::Any const & rAny, bool bInteractive);
- inline bool AreAllLinesValid() const { return m_pPropertiesWin->AreAllLinesValid(); }
- inline void ClearAllLines() { m_pPropertiesWin->ClearAllLines(); }
- inline css::uno::Sequence< css::beans::PropertyValue >
- GetCustomProperties() const
+ bool AreAllLinesValid() const { return m_pPropertiesWin->AreAllLinesValid(); }
+ void ClearAllLines() { m_pPropertiesWin->ClearAllLines(); }
+
+ css::uno::Sequence<css::beans::PropertyValue>
+ GetCustomProperties() const
{ return m_pPropertiesWin->GetCustomProperties(); }
- void Init(VclBuilderContainer& rParent);
+ void SetCustomProperties(const std::vector<CustomProperty*>& rProperties);
+
+ void Init(VclBuilderContainer& rParent);
virtual void Resize() override;
};
diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx
index 0bb2720e79be..e82b64b89304 100644
--- a/sfx2/source/dialog/dinfdlg.cxx
+++ b/sfx2/source/dialog/dinfdlg.cxx
@@ -1402,21 +1402,65 @@ void CustomPropertiesYesNoButton::Resize()
// struct CustomPropertyLine ---------------------------------------------
CustomPropertyLine::CustomPropertyLine( vcl::Window* pParent ) :
- m_aNameBox ( VclPtr<ComboBox>::Create(pParent, SfxResId( SFX_CB_PROPERTY_NAME )) ),
- m_aTypeBox ( VclPtr<CustomPropertiesTypeBox>::Create(pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), this) ),
- m_aValueEdit ( VclPtr<CustomPropertiesEdit>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_LEFT, this ) ),
- m_aDateField ( VclPtr<CustomPropertiesDateField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
- m_aTimeField ( VclPtr<CustomPropertiesTimeField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
- m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT ).toString() ),
- m_aDurationField( VclPtr<CustomPropertiesDurationField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_READONLY, this ) ),
- m_aEditButton ( VclPtr<CustomPropertiesEditButton>::Create(pParent, WB_TABSTOP, this) ),
- m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create(pParent, SfxResId( SFX_WIN_PROPERTY_YESNO )) ),
- m_aRemoveButton ( VclPtr<CustomPropertiesRemoveButton>::Create(pParent, 0, this) ),
- m_bIsDate ( false ),
- m_bIsRemoved ( false ),
+ m_aLine ( VclPtr<VclGrid>::Create(pParent) ),
+ m_aNameBox ( VclPtr<ComboBox>::Create(m_aLine, SfxResId( SFX_CB_PROPERTY_NAME )) ),
+ m_aTypeBox ( VclPtr<CustomPropertiesTypeBox>::Create(m_aLine.get(), SfxResId( SFX_LB_PROPERTY_TYPE ), this) ),
+ m_aValueEdit ( VclPtr<CustomPropertiesEdit>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_LEFT, this ) ),
+ m_aDateField ( VclPtr<CustomPropertiesDateField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
+ m_aTimeField ( VclPtr<CustomPropertiesTimeField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
+ m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT ) ),
+ m_aDurationField( VclPtr<CustomPropertiesDurationField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_READONLY, this ) ),
+ m_aEditButton ( VclPtr<CustomPropertiesEditButton>::Create(m_aLine, WB_TABSTOP, this) ),
+ m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create(m_aLine.get(), SfxResId( SFX_WIN_PROPERTY_YESNO )) ),
+ m_aRemoveButton ( VclPtr<CustomPropertiesRemoveButton>::Create(m_aLine, 0, this) ),
m_bTypeLostFocus( false )
{
+ m_aLine->set_column_spacing(4);
+
+ m_aNameBox->set_grid_left_attach(0);
+ m_aNameBox->set_grid_top_attach(0);
+ m_aNameBox->set_margin_left(4);
+ m_aNameBox->Show();
+
+ m_aTypeBox->set_grid_left_attach(1);
+ m_aTypeBox->set_grid_top_attach(0);
+ m_aTypeBox->Show();
+
+ m_aValueEdit->set_grid_left_attach(2);
+ m_aValueEdit->set_grid_top_attach(0);
+ m_aValueEdit->set_hexpand(true);
+ m_aValueEdit->Show();
+
+ m_aDateField->set_grid_left_attach(3);
+ m_aDateField->set_grid_top_attach(0);
+ m_aDateField->set_hexpand(true);
+ m_aDateField->Show();
+
+ m_aTimeField->set_grid_left_attach(4);
+ m_aTimeField->set_grid_top_attach(0);
+ m_aTimeField->set_hexpand(true);
+ m_aTimeField->Show();
+
+ m_aDurationField->set_grid_left_attach(5);
+ m_aDurationField->set_grid_top_attach(0);
+ m_aDurationField->set_hexpand(true);
+ m_aDurationField->Show();
+
+ m_aEditButton->set_grid_left_attach(6);
+ m_aEditButton->set_grid_top_attach(0);
+ m_aEditButton->Show();
+
+ m_aYesNoButton->set_grid_left_attach(7);
+ m_aYesNoButton->set_grid_top_attach(0);
+ m_aYesNoButton->set_hexpand(true);
+ m_aYesNoButton->Show();
+
+ m_aRemoveButton->set_grid_left_attach(8);
+ m_aRemoveButton->set_grid_top_attach(0);
+ m_aRemoveButton->set_margin_right(4);
+ m_aRemoveButton->Show();
+
m_aTimeField->SetExtFormat( EXTTIMEF_24H_LONG );
m_aDateField->SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
@@ -1426,19 +1470,16 @@ CustomPropertyLine::CustomPropertyLine( vcl::Window* pParent ) :
m_aEditButton->SetText(SfxResId(SFX_ST_EDIT).toString());
}
-void CustomPropertyLine::SetRemoved()
+void CustomPropertyLine::Clear()
+{
+ m_aNameBox->SetNoSelection();
+ m_aValueEdit->SetText(OUString());
+
+}
+
+void CustomPropertyLine::Hide()
{
- DBG_ASSERT( !m_bIsRemoved, "CustomPropertyLine::SetRemoved(): line already removed" );
- m_bIsRemoved = true;
- m_aNameBox->Hide();
- m_aTypeBox->Hide();
- m_aValueEdit->Hide();
- m_aDateField->Hide();
- m_aTimeField->Hide();
- m_aDurationField->Hide();
- m_aEditButton->Hide();
- m_aYesNoButton->Hide();
- m_aRemoveButton->Hide();
+ m_aLine->Hide();
}
CustomPropertiesWindow::CustomPropertiesWindow(vcl::Window* pParent,
@@ -1449,57 +1490,30 @@ CustomPropertiesWindow::CustomPropertiesWindow(vcl::Window* pParent,
m_pHeaderAccName(pHeaderAccName),
m_pHeaderAccType(pHeaderAccType),
m_pHeaderAccValue(pHeaderAccValue),
- m_aNameBox ( VclPtr<ComboBox>::Create( this, SfxResId( SFX_CB_PROPERTY_NAME ) ) ),
- m_aTypeBox ( VclPtr<ListBox>::Create( this, SfxResId( SFX_LB_PROPERTY_TYPE ) ) ),
- m_aValueEdit ( VclPtr<Edit>::Create( this, WB_BORDER|WB_TABSTOP|WB_LEFT ) ),
- m_aDateField ( VclPtr<DateField>::Create( this, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
- m_aTimeField ( VclPtr<TimeField>::Create( this, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
- m_aDurationField( VclPtr<Edit>::Create( this, WB_BORDER|WB_TABSTOP|WB_READONLY ) ),
- m_aEditButton ( VclPtr<PushButton>::Create( this, WB_TABSTOP ) ),
- m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create( this, SfxResId( SFX_WIN_PROPERTY_YESNO )) ),
- m_aRemoveButton ( VclPtr<ImageButton>::Create( this, 0 ) ),
m_nScrollPos (0),
m_pCurrentLine (nullptr),
m_aNumberFormatter( ::comphelper::getProcessComponentContext(),
Application::GetSettings().GetLanguageTag().getLanguageType() )
{
- Point aPos(LogicToPixel(Point(159, 2), MAP_APPFONT));
-
- m_aEditButton->SetPosSizePixel(aPos,
- LogicToPixel(Size(RSC_CD_TEXTBOX_HEIGHT, RSC_CD_TEXTBOX_HEIGHT), MAP_APPFONT));
+ m_nRemoveButtonWidth = ScopedVclPtrInstance<CustomPropertiesRemoveButton>(pParent, 0, nullptr)->get_preferred_size().Width();
+ Size aSize = ScopedVclPtrInstance<CustomPropertiesTypeBox>(pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), nullptr)->CalcMinimumSize();
+ m_nTypeBoxWidth = aSize.Width();
+ m_nWidgetHeight = aSize.Height();
- m_aRemoveButton->SetSizePixel(LogicToPixel(Size(RSC_CD_PUSHBUTTON_HEIGHT, RSC_CD_PUSHBUTTON_HEIGHT), MAP_APPFONT));
-
- Size aSize(LogicToPixel(Size(61, RSC_CD_TEXTBOX_HEIGHT), MAP_APPFONT));
- m_aValueEdit->SetPosSizePixel(aPos, aSize);
- m_aDurationField->SetPosSizePixel(aPos, aSize);
- m_aDateField->SetPosSizePixel(aPos, aSize);
- m_aTimeField->SetPosSizePixel(aPos, aSize);
+ Point aPos(LogicToPixel(Point(0, 2), MapMode(MAP_APPFONT)));
m_aEditLoseFocusIdle.SetPriority( TaskPriority::LOWEST );
m_aEditLoseFocusIdle.SetInvokeHandler( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) );
m_aBoxLoseFocusIdle.SetPriority( TaskPriority::LOWEST );
m_aBoxLoseFocusIdle.SetInvokeHandler( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) );
- m_aNameBox->add_mnemonic_label(m_pHeaderAccName);
- m_aNameBox->SetAccessibleName(m_pHeaderAccName->GetText());
- m_aTypeBox->add_mnemonic_label(m_pHeaderAccType);
- m_aTypeBox->SetAccessibleName(m_pHeaderAccType->GetText());
- m_aValueEdit->add_mnemonic_label(m_pHeaderAccValue);
- m_aValueEdit->SetAccessibleName(m_pHeaderAccValue->GetText());
-
- m_aNameBox->Hide();
- m_aTypeBox->Hide();
- m_aValueEdit->Hide();
- m_aDateField->Hide();
- m_aTimeField->Hide();
- m_aDurationField->Hide();
- m_aEditButton->Hide();
- m_aYesNoButton->Hide();
- m_aRemoveButton->Hide();
+ m_nLineHeight = (aPos.Y() * 2) + m_nWidgetHeight;
+}
- m_nLineHeight =
- ( m_aRemoveButton->GetPosPixel().Y() * 2 ) + m_aRemoveButton->GetSizePixel().Height();
+void CustomPropertiesWindow::Init(HeaderBar* pHeaderBar, ScrollBar* pScrollBar)
+{
+ m_pHeaderBar = pHeaderBar;
+ m_pScrollBar = pScrollBar;
}
CustomPropertiesWindow::~CustomPropertiesWindow()
@@ -1512,23 +1526,13 @@ void CustomPropertiesWindow::dispose()
m_aEditLoseFocusIdle.Stop();
m_aBoxLoseFocusIdle.Stop();
ClearAllLines();
- m_aNameBox.disposeAndClear();
- m_aTypeBox.disposeAndClear();
- m_aValueEdit.disposeAndClear();
- m_aDateField.disposeAndClear();
- m_aTimeField.disposeAndClear();
- m_aDurationField.disposeAndClear();
- m_aEditButton.disposeAndClear();
- m_aYesNoButton.disposeAndClear();
- m_aRemoveButton.disposeAndClear();
m_pHeaderAccName.clear();
m_pHeaderAccType.clear();
m_pHeaderAccValue.clear();
vcl::Window::dispose();
}
-IMPL_STATIC_LINK_TYPED(
- CustomPropertiesWindow, TypeHdl, ListBox&, rListBox, void )
+IMPL_LINK_TYPED( CustomPropertiesWindow, TypeHdl, ListBox&, rListBox, void )
{
CustomPropertiesTypeBox* pBox = static_cast<CustomPropertiesTypeBox*>(&rListBox);
long nType = reinterpret_cast<long>( pBox->GetSelectEntryData() );
@@ -1540,52 +1544,24 @@ IMPL_STATIC_LINK_TYPED(
pLine->m_aEditButton->Show( CUSTOM_TYPE_DURATION == nType );
pLine->m_aYesNoButton->Show( CUSTOM_TYPE_BOOLEAN == nType );
- //adjust positions of date and time controls
- if ( nType == CUSTOM_TYPE_DATE )
- {
- pLine->m_bIsDate = true;
- pLine->m_aDateField->SetSizePixel( pLine->m_aValueEdit->GetSizePixel() );
- }
- else if ( nType == CUSTOM_TYPE_DATETIME)
- {
- // because m_aDateField and m_aTimeField have the same size for type "DateTime",
- // we just rely on m_aTimeField here.
- pLine->m_bIsDate = false;
- pLine->m_aDateField->SetSizePixel( pLine->m_aTimeField->GetSizePixel() );
- }
+ pLine->m_aLine->SetSizePixel(Size(GetSizePixel().Width(), m_nWidgetHeight));
}
IMPL_LINK_TYPED( CustomPropertiesWindow, RemoveHdl, Button*, pBtn, void )
{
+ StoreCustomProperties();
+
CustomPropertiesRemoveButton* pButton = static_cast<CustomPropertiesRemoveButton*>(pBtn);
CustomPropertyLine* pLine = pButton->GetLine();
std::vector< CustomPropertyLine* >::iterator pFound =
std::find( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), pLine );
if ( pFound != m_aCustomPropertiesLines.end() )
{
- pLine = *pFound;
- pLine->SetRemoved();
- std::vector< CustomPropertyLine* >::iterator pIter = pFound + 1;
- const long nDelta = GetLineHeight();
- for ( ; pIter != m_aCustomPropertiesLines.end(); ++pIter )
- {
- pLine = *pIter;
- if ( pLine->m_bIsRemoved )
- continue;
-
- vcl::Window* pWindows[] = { pLine->m_aNameBox.get(), pLine->m_aTypeBox.get(), pLine->m_aValueEdit.get(),
- pLine->m_aDateField.get(), pLine->m_aTimeField.get(),
- pLine->m_aDurationField.get(), pLine->m_aEditButton.get(),
- pLine->m_aYesNoButton.get(), pLine->m_aRemoveButton.get(), nullptr };
- vcl::Window** pCurrent = pWindows;
- while ( *pCurrent )
- {
- Point aPos = (*pCurrent)->GetPosPixel();
- aPos.Y() -= nDelta;
- (*pCurrent)->SetPosPixel( aPos );
- pCurrent++;
- }
- }
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list