diff options
author | Vojtěch Doležal <dolezvo1@cvut.cz> | 2023-02-27 08:52:35 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-03-07 07:12:31 +0000 |
commit | 7b99871635cd48c2a8a1d0afbd7afc60a45cc2ff (patch) | |
tree | d2238324dac2096656a5b682bcedd288be5a5787 /sw/source/core | |
parent | cc45d748e241ea96fd0c81154e3dd49f9fc58357 (diff) |
tdf#153396 - Bibliography marks improvements
Adds option to separate function of "URL" into (listed) "URL" and "Target URL" to allow for more flexibility (in that case if target URL is empty, bibliography mark hyperlink leads to bibliography table row if possible)
When writing tests also found and fixed bug where exporting new file with anchor link bibliography mark crashes LO.
Change-Id: Ic1b5c8c9590c0338dcfc4fa3a981142bddae0113
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147868
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sw/source/core')
-rw-r--r-- | sw/source/core/fields/authfld.cxx | 30 | ||||
-rw-r--r-- | sw/source/core/fields/fldbas.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/text/EnhancedPDFExportHelper.cxx | 149 |
3 files changed, 155 insertions, 34 deletions
diff --git a/sw/source/core/fields/authfld.cxx b/sw/source/core/fields/authfld.cxx index 44d1e39dd3ae..d1d50506d741 100644 --- a/sw/source/core/fields/authfld.cxx +++ b/sw/source/core/fields/authfld.cxx @@ -634,6 +634,12 @@ OUString SwAuthorityField::GetAuthority(const SwRootFrame* pLayout, const SwForm return aText; } +bool SwAuthorityField::UseTargetURL() const +{ + const OUString& rValue = GetAuthEntry()->GetAuthorField(AUTH_FIELD_USE_TARGET_URL); + return rValue.toAsciiLowerCase() == "true"; +} + bool SwAuthorityField::HasURL() const { const OUString& rURL = GetAuthEntry()->GetAuthorField(AUTH_FIELD_URL); @@ -650,6 +656,22 @@ OUString SwAuthorityField::GetAbsoluteURL() const INetURLObject::DecodeMechanism::WithCharset); } +bool SwAuthorityField::HasTargetURL() const +{ + const OUString& rURL = GetAuthEntry()->GetAuthorField(AUTH_FIELD_TARGET_URL); + return !rURL.isEmpty(); +} + +OUString SwAuthorityField::GetAbsoluteTargetURL() const +{ + const OUString& rURL = GetAuthEntry()->GetAuthorField(AUTH_FIELD_TARGET_URL); + SwDoc* pDoc = static_cast<SwAuthorityFieldType*>(GetTyp())->GetDoc(); + SwDocShell* pDocShell = pDoc->GetDocShell(); + OUString aBasePath = pDocShell->getDocumentBaseURL(); + return INetURLObject::GetAbsURL(aBasePath, rURL, INetURLObject::EncodeMechanism::WasEncoded, + INetURLObject::DecodeMechanism::WithCharset); +} + OUString SwAuthorityField::GetURI(bool bRelative) const { OUString sTmp = GetFieldText(AUTH_FIELD_URL); @@ -751,7 +773,9 @@ const char* const aFieldNames[] = "Custom4", "Custom5", "ISBN", - "LocalURL" + "LocalURL", + "TargetURL", + "UseTargetURL" }; void SwAuthEntry::dumpAsXml(xmlTextWriterPtr pWriter) const @@ -808,8 +832,8 @@ bool SwAuthorityField::PutValue( const Any& rAny, sal_uInt16 /*nWhichId*/ ) if(!(rAny >>= aParam)) return false; - OUStringBuffer sBuf(+AUTH_FIELD_LOCAL_URL); - comphelper::string::padToLength(sBuf, AUTH_FIELD_LOCAL_URL, TOX_STYLE_DELIMITER); + OUStringBuffer sBuf(+(AUTH_FIELD_END - 1)); + comphelper::string::padToLength(sBuf, (AUTH_FIELD_END - 1), TOX_STYLE_DELIMITER); OUString sToSet(sBuf.makeStringAndClear()); for(const PropertyValue& rParam : std::as_const(aParam)) { diff --git a/sw/source/core/fields/fldbas.cxx b/sw/source/core/fields/fldbas.cxx index 71afe0d7e425..80ae487f93fe 100644 --- a/sw/source/core/fields/fldbas.cxx +++ b/sw/source/core/fields/fldbas.cxx @@ -423,7 +423,8 @@ bool SwField::HasClickHdl() const case SwFieldIds::GetRef: case SwFieldIds::Macro: case SwFieldIds::Input: - case SwFieldIds::Dropdown : + case SwFieldIds::Dropdown: + case SwFieldIds::TableOfAuthorities: bRet = true; break; @@ -431,13 +432,6 @@ bool SwField::HasClickHdl() const bRet = static_cast<const SwSetExpField*>(this)->GetInputFlag(); break; - case SwFieldIds::TableOfAuthorities: - { - const auto pAuthorityField = static_cast<const SwAuthorityField*>(this); - bRet = pAuthorityField->HasURL(); - break; - } - default: break; } return bRet; diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx index 053b67990eda..1dde77106624 100644 --- a/sw/source/core/text/EnhancedPDFExportHelper.cxx +++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx @@ -803,6 +803,13 @@ void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType ) bLanguage = true; break; + case vcl::PDFWriter::BibEntry : + bTextDecorationType = + bBaselineShift = + bLinkAttribute = + bLanguage = true; + break; + default: break; } @@ -2246,6 +2253,50 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() return; } + // Create PDF destinations for bibliography table entries + std::vector<std::tuple<const SwTOXBase*, const OUString*, sal_Int32>> vDestinations; + // string is the row node text, sal_Int32 is number of the destination + // Note: This way of iterating doesn't seem to take into account TOXes + // that are in a frame, probably in some other cases too + { + mrSh.GotoPage(1); + while (mrSh.GotoNextTOXBase()) + { + const SwTOXBase* pIteratedTOX = nullptr; + while ((pIteratedTOX = mrSh.GetCurTOX()) != nullptr + && pIteratedTOX->GetType() == TOX_AUTHORITIES) + { + if (const SwNode& rCurrentNode = mrSh.GetCursor()->GetPoint()->GetNode(); + rCurrentNode.GetNodeType() == SwNodeType::Text) + { + if (mrSh.GetCursor()->GetPoint()->GetNode().FindSectionNode()->GetSection().GetType() + == SectionType::ToxContent) // this checks it's not a heading + { + // Destination Rectangle + const SwRect& rDestRect = mrSh.GetCharRect(); + + const SwPageFrame* pCurrPage = + static_cast<const SwPageFrame*>( mrSh.GetLayout()->Lower() ); + + // Destination PageNum + const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect ); + + // Destination Export + if ( -1 != nDestPageNum ) + { + tools::Rectangle aRect(SwRectToPDFRect(pCurrPage, rDestRect.SVRect())); + const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest(aRect, nDestPageNum); + const OUString* vNodeText = &static_cast<const SwTextNode*>(&rCurrentNode)->GetText(); + vDestinations.emplace_back(pIteratedTOX, vNodeText, nDestId); + } + } + } + mrSh.MovePara(GoNextPara, fnParaStart); + } + } + } + + // Generate links to matching entries in the bibliography tables std::vector<SwFormatField*> aFields; SwFieldType* pType = mrSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()); if (!pType) @@ -2264,38 +2315,90 @@ void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() const auto& rAuthorityField = *static_cast<const SwAuthorityField*>(pFormatField->GetField()); - if (!rAuthorityField.HasURL()) - { - continue; - } - const OUString& rURL = rAuthorityField.GetAuthEntry()->GetAuthorField(AUTH_FIELD_URL); - const SwTextNode& rTextNode = pFormatField->GetTextField()->GetTextNode(); - if (!lcl_TryMoveToNonHiddenField(mrSh, rTextNode, *pFormatField)) + if ((!rAuthorityField.UseTargetURL() && rAuthorityField.HasURL()) + || (rAuthorityField.UseTargetURL() && rAuthorityField.HasTargetURL())) { - continue; - } + // Since the conditions indicate usage of a URL link to it + const OUString& rURL = rAuthorityField.GetAuthEntry()->GetAuthorField( + rAuthorityField.UseTargetURL() ? AUTH_FIELD_TARGET_URL : AUTH_FIELD_URL); - OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); + const SwTextNode& rTextNode = pFormatField->GetTextField()->GetTextNode(); + if (!lcl_TryMoveToNonHiddenField(mrSh, rTextNode, *pFormatField)) + { + continue; + } - // Select the field. - mrSh.SwCursorShell::SetMark(); - mrSh.SwCursorShell::Right(1, SwCursorSkipMode::Chars); + OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); - // Create the links. - for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_()) - { - for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect)) + // Select the field. + mrSh.SwCursorShell::SetMark(); + mrSh.SwCursorShell::Right(1, SwCursorSkipMode::Chars); + + // Create the links. + for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_()) { - tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, rLinkRect.SVRect())); - sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, content, rLinkPageNum); - IdMapEntry aLinkEntry(rLinkRect, nLinkId); - s_aLinkIdMap.push_back(aLinkEntry); - pPDFExtOutDevData->SetLinkURL(nLinkId, rURL); + for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect)) + { + tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, rLinkRect.SVRect())); + sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, content, rLinkPageNum); + IdMapEntry aLinkEntry(rLinkRect, nLinkId); + s_aLinkIdMap.push_back(aLinkEntry); + pPDFExtOutDevData->SetLinkURL(nLinkId, rURL); + } } + mrSh.SwCursorShell::ClearMark(); } + else if (rAuthorityField.UseTargetURL()) + { + // Since the bibliography mark doesn't have target URL, try linking to a bibliography table + sal_Int32 nDestId = -1; + + std::unordered_map<const SwTOXBase*, OUString> vFormattedFieldStrings; + for (const auto& rDestinationTuple : vDestinations) + { + if (vFormattedFieldStrings.find(std::get<0>(rDestinationTuple)) + == vFormattedFieldStrings.end()) + vFormattedFieldStrings.emplace(std::get<0>(rDestinationTuple), + rAuthorityField.GetAuthority(mrSh.GetLayout(), + &std::get<0>(rDestinationTuple)->GetTOXForm())); + + if (vFormattedFieldStrings.at(std::get<0>(rDestinationTuple)) == *std::get<1>(rDestinationTuple)) + { + nDestId = std::get<2>(rDestinationTuple); + break; + } + } + + if (nDestId == -1) + continue; + + const SwTextNode& rTextNode = pFormatField->GetTextField()->GetTextNode(); + if (!lcl_TryMoveToNonHiddenField(mrSh, rTextNode, *pFormatField)) + { + continue; + } + + OUString const content(rAuthorityField.ExpandField(true, mrSh.GetLayout())); - mrSh.SwCursorShell::ClearMark(); + // Select the field. + mrSh.SwCursorShell::SetMark(); + mrSh.SwCursorShell::Right(1, SwCursorSkipMode::Chars); + + // Create the links. + for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_()) + { + for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect)) + { + tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, rLinkRect.SVRect())); + sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, content, rLinkPageNum); + IdMapEntry aLinkEntry(rLinkRect, nLinkId); + s_aLinkIdMap.push_back(aLinkEntry); + pPDFExtOutDevData->SetLinkDest(nLinkId, nDestId); + } + } + mrSh.SwCursorShell::ClearMark(); + } } } |