include/svx/xmlgrhlp.hxx | 12 + include/vcl/gfxlink.hxx | 2 include/vcl/graphicfilter.hxx | 15 + include/vcl/pdfread.hxx | 5 include/xmloff/xmlimp.hxx | 3 offapi/com/sun/star/document/XGraphicStorageHandler.idl | 4 schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng | 9 + svx/source/xml/xmlgrhlp.cxx | 49 ++++- sw/inc/docsh.hxx | 6 sw/inc/rdfhelper.hxx | 26 +-- sw/source/core/doc/rdfhelper.cxx | 103 ++++-------- sw/source/core/edit/edfcol.cxx | 97 +++++------ sw/source/core/txtnode/thints.cxx | 3 sw/source/core/unocore/unoobj2.cxx | 7 sw/source/filter/ww8/docxattributeoutput.cxx | 9 - sw/source/filter/ww8/docxexport.cxx | 28 +-- sw/source/uibase/app/docsh.cxx | 6 sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx | 5 vcl/inc/impgraph.hxx | 2 vcl/source/filter/graphicfilter.cxx | 20 +- vcl/source/filter/ipdf/pdfread.cxx | 11 - vcl/source/gdi/gfxlink.cxx | 6 vcl/source/gdi/impgraph.cxx | 2 xmloff/qa/unit/data/two-pages.pdf |binary xmloff/qa/unit/draw.cxx | 45 +++++ xmloff/source/core/xmlimp.cxx | 5 xmloff/source/draw/shapeexport.cxx | 17 + xmloff/source/draw/ximpshap.cxx | 14 + xmloff/source/draw/ximpshap.hxx | 1 29 files changed, 310 insertions(+), 202 deletions(-)
New commits: commit f676426d3f543b022606657a34648594aae135cb Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 28 20:53:29 2025 +0000 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jan 29 14:36:18 2025 +0100 xml::sax::XWriter is a xml::sax::XDocumentHandler Change-Id: I492bff5580b61c222a7e9b84d49ba70a5dc318b9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180865 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 570b1bb7e6c4..fe0b86381369 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -1545,8 +1545,7 @@ void DocxExport::WriteGlossary() uno::Reference< xml::sax::XSAXSerializable > serializer( glossaryDocDom, uno::UNO_QUERY ); uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); writer->setOutputStream( xOutputStream ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); + serializer->serialize(writer, uno::Sequence< beans::StringPair >()); for (const uno::Sequence<beans::NamedValue>& glossaryElement : glossaryDomList) { @@ -1587,8 +1586,7 @@ void DocxExport::WriteGlossary() continue; // External relation, no stream to write uno::Reference< xml::sax::XSAXSerializable > gserializer( xDom, uno::UNO_QUERY ); writer->setOutputStream(GetFilter().openFragmentStream( "word/glossary/" + gTarget, contentType ) ); - gserializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); + gserializer->serialize(writer, uno::Sequence< beans::StringPair >()); } } @@ -1710,8 +1708,7 @@ void DocxExport::WriteCustomXml() writer->setOutputStream(xMemStream->getOutputStream()); - serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), - uno::Sequence< beans::StringPair >()); + serializer->serialize(writer, uno::Sequence< beans::StringPair >()); uno::Reference< io::XStream > xXSLTInStream = xMemStream; uno::Reference< io::XStream > xXSLTOutStream; @@ -1742,8 +1739,7 @@ void DocxExport::WriteCustomXml() { writer->setOutputStream(xOutStream); - serializer->serialize(uno::Reference< xml::sax::XDocumentHandler >(writer, uno::UNO_QUERY_THROW), - uno::Sequence< beans::StringPair >()); + serializer->serialize(writer, uno::Sequence< beans::StringPair >()); } } @@ -1753,8 +1749,7 @@ void DocxExport::WriteCustomXml() uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); writer->setOutputStream( GetFilter().openFragmentStream( "customXml/itemProps"+OUString::number(j+1)+".xml", "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" ) ); - serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), - uno::Sequence< beans::StringPair >() ); + serializer->serialize(writer, uno::Sequence< beans::StringPair >()); // Adding itemprops's relationship entry to item.xml.rels file m_rFilter.addRelation( GetFilter().openFragmentStream( "customXml/item"+OUString::number(j+1)+".xml", commit 5093e8c85411b7535576c9c4d018b4039db6995c Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 28 21:30:43 2025 +0000 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Wed Jan 29 11:54:18 2025 +0100 use getFastAttributeTokens and getValueByIndex instead of getFastAttributes Change-Id: I011f0fd8bfd615ff9ee89dd7755c536740463f70 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180867 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index f4ced57b4ad5..f2b611b9e2a9 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -775,9 +775,12 @@ void SdtBlockHelper::WriteSdtBlock(const ::sax_fastparser::FSHelperPtr& pSeriali } if (m_nSdtPrToken == FSNS(XML_w, XML_date) || m_nSdtPrToken == FSNS(XML_w, XML_docPartObj) || m_nSdtPrToken == FSNS(XML_w, XML_docPartList) || m_nSdtPrToken == FSNS(XML_w14, XML_checkbox)) { - const uno::Sequence<xml::FastAttribute> aChildren = m_pTokenChildren->getFastAttributes(); - for (const auto& rChild : aChildren) - pSerializer->singleElement(rChild.Token, FSNS(XML_w, XML_val), rChild.Value); + const std::vector<sal_Int32>& rAttributeTokens = m_pTokenChildren->getFastAttributeTokens(); + for (size_t i = 0, n = rAttributeTokens.size(); i < n; ++i) + { + pSerializer->singleElement(rAttributeTokens[i], FSNS(XML_w, XML_val), + m_pTokenChildren->getValueByIndex(i)); + } } pSerializer->endElement(m_nSdtPrToken); commit 527983407624df16f9bec6499088e9b98396d0e4 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 28 17:00:19 2025 +0000 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jan 29 11:53:41 2025 +0100 We already have a SwXTextDocument, don't need to cast to XDocumentMetadataAccess, it's already available also contains partial backport of: commit c69ad797408fd93afec2c5ac47ba94eba5e4c81c Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Sep 17 11:37:15 2024 +0200 use more concrete UNO types in sw but with GetBaseModel override replaced with additional GetXTextDocument where needed for rdfhelper. Change-Id: I35965afafb4080a2315862739d602677b966245a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180855 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/inc/docsh.hxx b/sw/inc/docsh.hxx index 3cbc43c98803..66bc38a56372 100644 --- a/sw/inc/docsh.hxx +++ b/sw/inc/docsh.hxx @@ -53,6 +53,7 @@ class SwDocShell; class SwDrawModel; class SwViewShell; class SwDocStyleSheetPool; +class SwXTextDocument; namespace svt { class EmbeddedObjectRef; @@ -120,6 +121,11 @@ class SW_DLLPUBLIC SwDocShell /// Make DocInfo known to the Doc. SAL_DLLPRIVATE virtual std::shared_ptr<SfxDocumentInfoDialog> CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet) override; + +public: + rtl::Reference<SwXTextDocument> GetXTextDocument() const; +private: + /// OLE-stuff SAL_DLLPRIVATE virtual void Draw(OutputDevice*, const JobSetup&, sal_uInt16 nAspect, bool bOutputToWindow) override; diff --git a/sw/inc/rdfhelper.hxx b/sw/inc/rdfhelper.hxx index ee346c499fe2..dd7267758846 100644 --- a/sw/inc/rdfhelper.hxx +++ b/sw/inc/rdfhelper.hxx @@ -12,6 +12,7 @@ #include <map> +#include <rtl/ref.hxx> #include <rtl/ustring.hxx> #include "swdllapi.h" @@ -20,7 +21,7 @@ #include <com/sun/star/uno/Sequence.h> class SwTextNode; - +class SwXTextDocument; namespace com::sun::star { namespace frame { class XModel; @@ -38,49 +39,42 @@ class SW_DLLPUBLIC SwRDFHelper public: /// Gets all graph-names in RDF of a given type. static css::uno::Sequence<css::uno::Reference<css::rdf::XURI>> - getGraphNames(const css::uno::Reference<css::rdf::XDocumentMetadataAccess>& xDocumentMetadataAccess, + getGraphNames(const rtl::Reference<SwXTextDocument>& xModel, const css::uno::Reference<css::rdf::XURI>& xType); /// Gets all graph-names in RDF of a given type. static css::uno::Sequence<css::uno::Reference<css::rdf::XURI>> - getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType); + getGraphNames(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType); /// Gets all (XResource, key, value) statements in RDF graphs given the graph-names. static std::map<OUString, OUString> - getStatements(const css::uno::Reference<css::frame::XModel>& xModel, + getStatements(const rtl::Reference<SwXTextDocument>& xModel, const css::uno::Sequence<css::uno::Reference<css::rdf::XURI>>& rGraphNames, const css::uno::Reference<css::rdf::XResource>& xSubject); /// Gets all (XResource, key, value) statements in RDF graphs of type rType. static std::map<OUString, OUString> - getStatements(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType, + getStatements(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject); /// Add an (XResource, key, value) statement in the graph of type rType -- or if it does not exist, create a graph at rPath first. - static void addStatement(const css::uno::Reference<css::frame::XModel>& xModel, + static void addStatement(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const OUString& rPath, const css::uno::Reference<css::rdf::XResource>& xSubject, const OUString& rKey, const OUString& rValue); /// Check if a graph of type rType exists. - static bool hasMetadataGraph(const css::uno::Reference<css::frame::XModel>& xModel, + static bool hasMetadataGraph(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType); /// Remove an (XResource, key, value) statement in the graph of type rType, if it exists. - static void removeStatement(const css::uno::Reference<css::frame::XModel>& xModel, + static void removeStatement(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject, const OUString& rKey, const OUString& rValue); - /// Clone all statements in the graph of type rType, if any exists, from one subject to another. - static void cloneStatements(const css::uno::Reference<css::frame::XModel>& xSrcModel, - const css::uno::Reference<css::frame::XModel>& xDstModel, - const OUString& rType, - const css::uno::Reference<css::rdf::XResource>& xSrcSubject, - const css::uno::Reference<css::rdf::XResource>& xDstSubject); - /// Remove all statements in the graph of type rType, if any exists. - static void clearStatements(const css::uno::Reference<css::frame::XModel>& xModel, + static void clearStatements(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject); diff --git a/sw/source/core/doc/rdfhelper.cxx b/sw/source/core/doc/rdfhelper.cxx index d4e5d9da2b52..12295177ebe6 100644 --- a/sw/source/core/doc/rdfhelper.cxx +++ b/sw/source/core/doc/rdfhelper.cxx @@ -22,16 +22,17 @@ #include <ndtxt.hxx> #include <unoparagraph.hxx> #include <unotext.hxx> +#include <unotxdoc.hxx> using namespace com::sun::star; css::uno::Sequence<css::uno::Reference<css::rdf::XURI>> SwRDFHelper::getGraphNames( - const css::uno::Reference<rdf::XDocumentMetadataAccess>& xDocumentMetadataAccess, + const rtl::Reference<SwXTextDocument>& xModel, const css::uno::Reference<rdf::XURI>& xType) { try { - return xDocumentMetadataAccess->getMetadataGraphsWithType(xType); + return xModel->getMetadataGraphsWithType(xType); } catch (const uno::RuntimeException&) { @@ -40,7 +41,7 @@ css::uno::Sequence<css::uno::Reference<css::rdf::XURI>> SwRDFHelper::getGraphNam } css::uno::Sequence<uno::Reference<css::rdf::XURI>> -SwRDFHelper::getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel, +SwRDFHelper::getGraphNames(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType) { try @@ -51,9 +52,7 @@ SwRDFHelper::getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel // message: component context fails to supply service com.sun.star.rdf.URI of type com.sun.star.rdf.XURI // context: cppu::ComponentContext uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, - uno::UNO_QUERY); - return getGraphNames(xDocumentMetadataAccess, xType); + return getGraphNames(xModel, xType); } catch (const ::css::uno::Exception&) { @@ -62,7 +61,7 @@ SwRDFHelper::getGraphNames(const css::uno::Reference<css::frame::XModel>& xModel } std::map<OUString, OUString> -SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel, +SwRDFHelper::getStatements(const rtl::Reference<SwXTextDocument>& xModel, const uno::Sequence<uno::Reference<css::rdf::XURI>>& rGraphNames, const css::uno::Reference<css::rdf::XResource>& xSubject) { @@ -70,8 +69,7 @@ SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel if (!rGraphNames.hasElements()) return aRet; - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY); - const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository(); + const uno::Reference<rdf::XRepository>& xRepo = xModel->getRDFRepository(); for (const uno::Reference<rdf::XURI>& xGraphName : rGraphNames) { uno::Reference<rdf::XNamedGraph> xGraph = xRepo->getGraph(xGraphName); @@ -91,76 +89,72 @@ SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel } std::map<OUString, OUString> -SwRDFHelper::getStatements(const css::uno::Reference<css::frame::XModel>& xModel, +SwRDFHelper::getStatements(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject) { return getStatements(xModel, getGraphNames(xModel, rType), xSubject); } -void SwRDFHelper::addStatement(const css::uno::Reference<css::frame::XModel>& xModel, +void SwRDFHelper::addStatement(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const OUString& rPath, const css::uno::Reference<css::rdf::XResource>& xSubject, const OUString& rKey, const OUString& rValue) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); + const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xModel, xType); uno::Reference<rdf::XURI> xGraphName; if (aGraphNames.hasElements()) xGraphName = aGraphNames[0]; else { uno::Sequence< uno::Reference<rdf::XURI> > xTypes = { xType }; - xGraphName = xDocumentMetadataAccess->addMetadataFile(rPath, xTypes); + xGraphName = xModel->addMetadataFile(rPath, xTypes); } - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName); + uno::Reference<rdf::XNamedGraph> xGraph = xModel->getRDFRepository()->getGraph(xGraphName); uno::Reference<rdf::XURI> xKey = rdf::URI::create(xComponentContext, rKey); uno::Reference<rdf::XLiteral> xValue = rdf::Literal::create(xComponentContext, rValue); xGraph->addStatement(xSubject, xKey, xValue); } -bool SwRDFHelper::hasMetadataGraph(const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rType) +bool SwRDFHelper::hasMetadataGraph(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY); - return getGraphNames(xDocumentMetadataAccess, xType).hasElements(); + return getGraphNames(xModel, xType).hasElements(); } -void SwRDFHelper::removeStatement(const css::uno::Reference<css::frame::XModel>& xModel, +void SwRDFHelper::removeStatement(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject, const OUString& rKey, const OUString& rValue) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); + const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xModel, xType); if (!aGraphNames.hasElements()) return; - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(aGraphNames[0]); + uno::Reference<rdf::XNamedGraph> xGraph = xModel->getRDFRepository()->getGraph(aGraphNames[0]); uno::Reference<rdf::XURI> xKey = rdf::URI::create(xComponentContext, rKey); uno::Reference<rdf::XLiteral> xValue = rdf::Literal::create(xComponentContext, rValue); xGraph->removeStatements(xSubject, xKey, xValue); } -void SwRDFHelper::clearStatements(const css::uno::Reference<css::frame::XModel>& xModel, +void SwRDFHelper::clearStatements(const rtl::Reference<SwXTextDocument>& xModel, const OUString& rType, const css::uno::Reference<css::rdf::XResource>& xSubject) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); + const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xModel, xType); if (!aGraphNames.hasElements()) return; for (const uno::Reference<rdf::XURI>& xGraphName : aGraphNames) { - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName); + uno::Reference<rdf::XNamedGraph> xGraph = xModel->getRDFRepository()->getGraph(xGraphName); uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(xSubject, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>()); while (xStatements->hasMoreElements()) { @@ -172,57 +166,35 @@ void SwRDFHelper::clearStatements(const css::uno::Reference<css::frame::XModel>& } } -void SwRDFHelper::cloneStatements(const css::uno::Reference<css::frame::XModel>& xSrcModel, - const css::uno::Reference<css::frame::XModel>& xDstModel, - const OUString& rType, - const css::uno::Reference<css::rdf::XResource>& xSrcSubject, - const css::uno::Reference<css::rdf::XResource>& xDstSubject) -{ - uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); - uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xSrcModel, uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); - if (!aGraphNames.hasElements()) - return; - - for (const uno::Reference<rdf::XURI>& xGraphName : aGraphNames) - { - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName); - uno::Reference<container::XEnumeration> xStatements = xGraph->getStatements(xSrcSubject, uno::Reference<rdf::XURI>(), uno::Reference<rdf::XURI>()); - while (xStatements->hasMoreElements()) - { - const rdf::Statement aStatement = xStatements->nextElement().get<rdf::Statement>(); - - const OUString sKey = aStatement.Predicate->getStringValue(); - const OUString sValue = aStatement.Object->getStringValue(); - addStatement(xDstModel, rType, xGraphName->getLocalName(), xDstSubject, sKey, sValue); - } - } -} - std::map<OUString, OUString> SwRDFHelper::getTextNodeStatements(const OUString& rType, SwTextNode& rTextNode) { uno::Reference<rdf::XResource> xTextNode(SwXParagraph::CreateXParagraph(rTextNode.GetDoc(), &rTextNode, nullptr)); - return getStatements(rTextNode.GetDoc().GetDocShell()->GetBaseModel(), rType, xTextNode); + SwDocShell* pShell = rTextNode.GetDoc().GetDocShell(); + if (!pShell) + return std::map<OUString, OUString>(); + return getStatements(pShell->GetXTextDocument(), rType, xTextNode); } void SwRDFHelper::addTextNodeStatement(const OUString& rType, const OUString& rPath, SwTextNode& rTextNode, const OUString& rKey, const OUString& rValue) { uno::Reference<rdf::XResource> xSubject(SwXParagraph::CreateXParagraph(rTextNode.GetDoc(), &rTextNode, nullptr)); - addStatement(rTextNode.GetDoc().GetDocShell()->GetBaseModel(), rType, rPath, xSubject, rKey, rValue); + addStatement(rTextNode.GetDoc().GetDocShell()->GetXTextDocument(), rType, rPath, xSubject, rKey, rValue); } void SwRDFHelper::removeTextNodeStatement(const OUString& rType, SwTextNode& rTextNode, const OUString& rKey, const OUString& rValue) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(rTextNode.GetDoc().GetDocShell()->GetBaseModel(), uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); + SwDocShell* pShell = rTextNode.GetDoc().GetDocShell(); + if (!pShell) + return; + rtl::Reference<SwXTextDocument> xModel(pShell->GetXTextDocument()); + const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xModel, xType); if (!aGraphNames.hasElements()) return; - uno::Reference<rdf::XURI> xGraphName = aGraphNames[0]; - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName); + const uno::Reference<rdf::XURI>& xGraphName = aGraphNames[0]; + uno::Reference<rdf::XNamedGraph> xGraph = xModel->getRDFRepository()->getGraph(xGraphName); uno::Reference<rdf::XResource> xSubject(SwXParagraph::CreateXParagraph(rTextNode.GetDoc(), &rTextNode, nullptr)); uno::Reference<rdf::XURI> xKey = rdf::URI::create(xComponentContext, rKey); uno::Reference<rdf::XLiteral> xValue = rdf::Literal::create(xComponentContext, rValue); @@ -233,8 +205,11 @@ void SwRDFHelper::updateTextNodeStatement(const OUString& rType, const OUString& { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); uno::Reference<rdf::XURI> xType = rdf::URI::create(xComponentContext, rType); - uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(rTextNode.GetDoc().GetDocShell()->GetBaseModel(), uno::UNO_QUERY); - const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xDocumentMetadataAccess, xType); + SwDocShell* pShell = rTextNode.GetDoc().GetDocShell(); + if (!pShell) + return; + rtl::Reference<SwXTextDocument> xModel(pShell->GetXTextDocument()); + const uno::Sequence< uno::Reference<rdf::XURI> > aGraphNames = getGraphNames(xModel, xType); uno::Reference<rdf::XURI> xGraphName; if (aGraphNames.hasElements()) { @@ -243,10 +218,10 @@ void SwRDFHelper::updateTextNodeStatement(const OUString& rType, const OUString& else { uno::Sequence< uno::Reference<rdf::XURI> > xTypes = { xType }; - xGraphName = xDocumentMetadataAccess->addMetadataFile(rPath, xTypes); + xGraphName = xModel->addMetadataFile(rPath, xTypes); } - uno::Reference<rdf::XNamedGraph> xGraph = xDocumentMetadataAccess->getRDFRepository()->getGraph(xGraphName); + uno::Reference<rdf::XNamedGraph> xGraph = xModel->getRDFRepository()->getGraph(xGraphName); uno::Reference<rdf::XResource> xSubject(SwXParagraph::CreateXParagraph(rTextNode.GetDoc(), &rTextNode, nullptr)); uno::Reference<rdf::XURI> xKey = rdf::URI::create(xComponentContext, rKey); diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index d3d9d75063a4..5158c4425a4e 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -266,7 +266,7 @@ OString lcl_getParagraphBodyText(const uno::Reference<text::XTextContent>& xText } template <typename T> -std::map<OUString, OUString> lcl_getRDFStatements(const uno::Reference<frame::XModel>& xModel, +std::map<OUString, OUString> lcl_getRDFStatements(const rtl::Reference<SwXTextDocument>& xModel, const T& xRef) { try @@ -282,7 +282,7 @@ std::map<OUString, OUString> lcl_getRDFStatements(const uno::Reference<frame::XM } /// Returns RDF (key, value) pair associated with the field, if any. -std::pair<OUString, OUString> lcl_getFieldRDFByPrefix(const uno::Reference<frame::XModel>& xModel, +std::pair<OUString, OUString> lcl_getFieldRDFByPrefix(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextField>& xField, std::u16string_view sPrefix) { @@ -297,7 +297,7 @@ std::pair<OUString, OUString> lcl_getFieldRDFByPrefix(const uno::Reference<frame /// Returns RDF (key, value) pair associated with the field, if any. template <typename T> -std::pair<OUString, OUString> lcl_getRDF(const uno::Reference<frame::XModel>& xModel, +std::pair<OUString, OUString> lcl_getRDF(const rtl::Reference<SwXTextDocument>& xModel, const T& xRef, const OUString& sRDFName) { @@ -308,13 +308,13 @@ std::pair<OUString, OUString> lcl_getRDF(const uno::Reference<frame::XModel>& xM /// Returns true iff the field in question is paragraph signature. /// Note: must have associated RDF, since signatures are otherwise just metadata fields. -bool lcl_IsParagraphSignatureField(const uno::Reference<frame::XModel>& xModel, +bool lcl_IsParagraphSignatureField(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextField>& xField) { return (lcl_getRDF(xModel, xField, ParagraphSignatureIdRDFName).first == ParagraphSignatureIdRDFName); } -uno::Reference<text::XTextField> lcl_findFieldByRDF(const uno::Reference<frame::XModel>& xModel, +uno::Reference<text::XTextField> lcl_findFieldByRDF(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph, const OUString& sRDFName, std::u16string_view sRDFValue) @@ -358,7 +358,7 @@ struct SignatureDescr bool isValid() const { return !msSignature.isEmpty(); } }; -SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel, +SignatureDescr lcl_getSignatureDescr(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xParagraph, std::u16string_view sFieldId) { @@ -379,7 +379,7 @@ SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel return aDescr; } -SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel, +SignatureDescr lcl_getSignatureDescr(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField) { @@ -424,7 +424,7 @@ std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const SignatureDes /// Validate and return validation result and signature field display text. std::pair<bool, OUString> -lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, +lcl_MakeParagraphSignatureFieldText(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField, const OString& utf8Text) @@ -434,7 +434,7 @@ lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, } /// Generate the next valid ID for the new signature on this paragraph. -OUString lcl_getNextSignatureId(const uno::Reference<frame::XModel>& xModel, +OUString lcl_getNextSignatureId(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph) { const OUString sFieldId = lcl_getRDF(xModel, xParagraph, ParagraphSignatureLastIdRDFName).second; @@ -442,12 +442,12 @@ OUString lcl_getNextSignatureId(const uno::Reference<frame::XModel>& xModel, } /// Creates and inserts Paragraph Signature Metadata field and creates the RDF entry -uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Reference<frame::XModel>& xModel, +uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph, const OUString& signature, const OUString& usage) { - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel); auto xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); // Add the signature at the end. @@ -516,7 +516,7 @@ bool lcl_DoUpdateParagraphSignatureField(SwDoc& rDoc, /// Updates the signature field text if changed and returns true only iff updated. bool lcl_UpdateParagraphSignatureField(SwDoc& rDoc, - const uno::Reference<frame::XModel>& xModel, + const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField, const OString& utf8Text) @@ -534,7 +534,7 @@ void lcl_RemoveParagraphMetadataField(const uno::Reference<css::text::XTextField /// Returns true iff the field in question is paragraph classification. /// Note: must have associated RDF, since classifications are otherwise just metadata fields. -bool lcl_IsParagraphClassificationField(const uno::Reference<frame::XModel>& xModel, +bool lcl_IsParagraphClassificationField(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextField>& xField, std::u16string_view sKey) { @@ -542,7 +542,7 @@ bool lcl_IsParagraphClassificationField(const uno::Reference<frame::XModel>& xMo return rdfPair.first == ParagraphClassificationNameRDFName && (sKey.empty() || rdfPair.second == sKey); } -uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const uno::Reference<frame::XModel>& xModel, +uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const rtl::Reference<SwXTextDocument>& xModel, const rtl::Reference<SwXParagraph>& xParagraph, std::u16string_view sKey = u"") { @@ -578,10 +578,10 @@ uno::Reference<text::XTextField> lcl_FindParagraphClassificationField(const uno: } /// Creates and inserts Paragraph Classification Metadata field and creates the RDF entry -uno::Reference<text::XTextField> lcl_InsertParagraphClassification(const uno::Reference<frame::XModel>& xModel, +uno::Reference<text::XTextField> lcl_InsertParagraphClassification(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParent) { - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel); auto xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); // Add the classification at the start. @@ -591,7 +591,7 @@ uno::Reference<text::XTextField> lcl_InsertParagraphClassification(const uno::Re /// Updates the paragraph classification field text if changed and returns true only iff updated. bool lcl_UpdateParagraphClassificationField(SwDoc* pDoc, - const uno::Reference<frame::XModel>& xModel, + const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xTextNode, const OUString& sKey, const OUString& sValue, @@ -623,7 +623,7 @@ void lcl_ValidateParagraphSignatures(SwDoc& rDoc, const uno::Reference<text::XTe if (!pDocShell) return; - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); // Check if the paragraph is signed. try @@ -1168,7 +1168,7 @@ void SwEditShell::SetClassification(const OUString& rName, SfxClassificationPoli // We pass xParent and xNodeSubject even though they point to the same thing because the UNO_QUERY is // on a performance-sensitive path. static void lcl_ApplyParagraphClassification(SwDoc* pDoc, - const uno::Reference<frame::XModel>& xModel, + const rtl::Reference<SwXTextDocument>& xModel, const rtl::Reference<SwXParagraph>& xParent, const css::uno::Reference<css::rdf::XResource>& xNodeSubject, std::vector<svx::ClassificationResult> aResults) @@ -1285,12 +1285,12 @@ void SwEditShell::ApplyParagraphClassification(std::vector<svx::ClassificationRe SetParagraphSignatureValidation(bOldValidationFlag); }); - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); rtl::Reference<SwXParagraph> xParent = SwXParagraph::CreateXParagraph(pNode->GetDoc(), pNode, nullptr); lcl_ApplyParagraphClassification(GetDoc(), xModel, xParent, css::uno::Reference<css::rdf::XResource>(xParent), std::move(aResults)); } -static std::vector<svx::ClassificationResult> lcl_CollectParagraphClassification(const uno::Reference<frame::XModel>& xModel, const uno::Reference<text::XTextContent>& xParagraph) +static std::vector<svx::ClassificationResult> lcl_CollectParagraphClassification(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph) { std::vector<svx::ClassificationResult> aResult; @@ -1361,7 +1361,7 @@ std::vector<svx::ClassificationResult> SwEditShell::CollectParagraphClassificati return aResult; rtl::Reference<SwXParagraph> xParent = SwXParagraph::CreateXParagraph(pNode->GetDoc(), pNode, nullptr); - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); return lcl_CollectParagraphClassification(xModel, xParent); } @@ -1688,18 +1688,21 @@ SwUndoParagraphSigning::SwUndoParagraphSigning(SwDoc& rDoc, m_bRemove(bRemove) { // Save the metadata and field content to undo/redo. - uno::Reference<frame::XModel> xModel = m_rDoc.GetDocShell()->GetBaseModel(); - const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, m_xField); - const auto it = aStatements.find(ParagraphSignatureIdRDFName); - if (it != aStatements.end()) - m_signature = it->second; - - const auto it2 = aStatements.find(ParagraphSignatureUsageRDFName); - if (it2 != aStatements.end()) - m_usage = it2->second; - - uno::Reference<css::text::XTextRange> xText(m_xField, uno::UNO_QUERY); - m_display = xText->getString(); + if (SwDocShell* pShell = m_rDoc.GetDocShell()) + { + rtl::Reference<SwXTextDocument> xModel = pShell->GetXTextDocument(); + const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, m_xField); + const auto it = aStatements.find(ParagraphSignatureIdRDFName); + if (it != aStatements.end()) + m_signature = it->second; + + const auto it2 = aStatements.find(ParagraphSignatureUsageRDFName); + if (it2 != aStatements.end()) + m_usage = it2->second; + + uno::Reference<css::text::XTextRange> xText(m_xField, uno::UNO_QUERY); + m_display = xText->getString(); + } } void SwUndoParagraphSigning::UndoImpl(::sw::UndoRedoContext&) @@ -1738,7 +1741,7 @@ void SwUndoParagraphSigning::Insert() m_rDoc.GetIDocumentUndoRedo().DoUndo(isUndoEnabled); }); - m_xField = lcl_InsertParagraphSignature(m_rDoc.GetDocShell()->GetBaseModel(), m_xParent, m_signature, m_usage); + m_xField = lcl_InsertParagraphSignature(m_rDoc.GetDocShell()->GetXTextDocument(), m_xParent, m_signature, m_usage); lcl_DoUpdateParagraphSignatureField(m_rDoc, m_xField, m_display); } @@ -1825,7 +1828,7 @@ void SwEditShell::SignParagraph() rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::PARA_SIGN_ADD, nullptr); - const uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + const rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); uno::Reference<css::text::XTextField> xField = lcl_InsertParagraphSignature(xModel, xParagraph, signature, aUsage); lcl_UpdateParagraphSignatureField(*GetDoc(), xModel, xParagraph, xField, utf8Text); @@ -1855,7 +1858,7 @@ void SwEditShell::ValidateParagraphSignatures(SwTextNode* pNode, bool updateDont if (!pDocShell) return; - uno::Sequence<uno::Reference<css::rdf::XURI>> aGraphNames = SwRDFHelper::getGraphNames(pDocShell->GetBaseModel(), MetaNS); + uno::Sequence<uno::Reference<css::rdf::XURI>> aGraphNames = SwRDFHelper::getGraphNames(pDocShell->GetXTextDocument(), MetaNS); rtl::Reference<SwXParagraph> xParentText = SwXParagraph::CreateXParagraph(*GetDoc(), pNode, nullptr); lcl_ValidateParagraphSignatures(*GetDoc(), xParentText, updateDontRemove, aGraphNames); } @@ -1893,7 +1896,7 @@ void SwEditShell::ValidateAllParagraphSignatures(bool updateDontRemove) uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); if (!xParagraphs.is()) return; - uno::Sequence<uno::Reference<css::rdf::XURI>> aGraphNames = SwRDFHelper::getGraphNames(pDocShell->GetBaseModel(), MetaNS); + uno::Sequence<uno::Reference<css::rdf::XURI>> aGraphNames = SwRDFHelper::getGraphNames(pDocShell->GetXTextDocument(), MetaNS); while (xParagraphs->hasMoreElements()) { uno::Reference<text::XTextContent> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY); @@ -1914,7 +1917,7 @@ static uno::Reference<text::XTextField> lcl_GetParagraphMetadataFieldAtIndex(con if (::sw::Meta* pMeta = rFormatMeta.GetMeta()) { const css::uno::Reference<css::rdf::XResource> xSubject = pMeta->MakeUnoObject(); - uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel(); + rtl::Reference<SwXTextDocument> xModel = pDocSh->GetXTextDocument(); const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, xSubject); if (aStatements.find(ParagraphSignatureIdRDFName) != aStatements.end() || aStatements.find(ParagraphClassificationNameRDFName) != aStatements.end()) @@ -1940,9 +1943,8 @@ void SwEditShell::RestoreMetadataFieldsAndValidateParagraphSignatures() SetParagraphSignatureValidation(bOldValidationFlag); }); - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); - const rtl::Reference<SwXTextDocument> xDoc(dynamic_cast<SwXTextDocument*>(xModel.get())); - rtl::Reference<SwXBodyText> xBodyText = xDoc->getBodyText(); + rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); + rtl::Reference<SwXBodyText> xBodyText = xModel->getBodyText(); if (!xBodyText.is()) return; rtl::Reference<SwXParagraphEnumeration> xParagraphs = xBodyText->createParagraphEnumeration(); @@ -2042,7 +2044,7 @@ void SwEditShell::RestoreMetadataFieldsAndValidateParagraphSignatures() uno::Reference<text::XTextField> xField = lcl_findFieldByRDF(xModel, xParagraph, ParagraphSignatureIdRDFName, pair.first); if (!xField.is()) { - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel); xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); // Add the signature at the end. @@ -2104,7 +2106,7 @@ bool SwEditShell::RemoveParagraphMetadataFieldAtCursor() } static OUString lcl_GetParagraphClassification(SfxClassificationHelper & rHelper, sfx::ClassificationKeyCreator const & rKeyCreator, - const uno::Reference<frame::XModel>& xModel, const rtl::Reference<SwXParagraph>& xParagraph) + const rtl::Reference<SwXTextDocument>& xModel, const rtl::Reference<SwXParagraph>& xParagraph) { uno::Reference<text::XTextField> xTextField; xTextField = lcl_FindParagraphClassificationField(xModel, xParagraph, rKeyCreator.makeCategoryIdentifierKey()); @@ -2138,9 +2140,8 @@ static OUString lcl_GetHighestClassificationParagraphClass(SwPaM* pCursor) SfxClassificationHelper aHelper(pDocShell->getDocProperties()); sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType()); - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); - const rtl::Reference<SwXTextDocument> xDoc(dynamic_cast<SwXTextDocument*>(xModel.get())); - rtl::Reference<SwXBodyText> xBodyText = xDoc->getBodyText(); + rtl::Reference<SwXTextDocument> xModel = pDocShell->GetXTextDocument(); + rtl::Reference<SwXBodyText> xBodyText = xModel->getBodyText(); rtl::Reference<SwXParagraphEnumeration> xParagraphs = xBodyText->createParagraphEnumeration(); while (xParagraphs->hasMoreElements()) @@ -2161,7 +2162,7 @@ void SwEditShell::ClassifyDocPerHighestParagraphClass() return; // Bail out as early as possible if we don't have paragraph classification. - if (!SwRDFHelper::hasMetadataGraph(pDocShell->GetBaseModel(), MetaNS)) + if (!SwRDFHelper::hasMetadataGraph(pDocShell->GetXTextDocument(), MetaNS)) return; uno::Reference<document::XDocumentProperties> xDocumentProperties = pDocShell->getDocProperties(); diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx index 942cb0080abd..f7d8949fceac 100644 --- a/sw/source/core/txtnode/thints.cxx +++ b/sw/source/core/txtnode/thints.cxx @@ -82,6 +82,7 @@ #include <rdfhelper.hxx> #include <hints.hxx> +#include <unotxdoc.hxx> #ifdef DBG_UTIL #define CHECK Check(true); @@ -1287,7 +1288,7 @@ void SwTextNode::DestroyAttr( SwTextAttr* pAttr ) { static constexpr OUStringLiteral metaNS(u"urn:bails"); const css::uno::Reference<css::rdf::XResource> xSubject = pMeta->MakeUnoObject(); - uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel(); + rtl::Reference<SwXTextDocument> xModel = pDocSh->GetXTextDocument(); SwRDFHelper::clearStatements(xModel, metaNS, xSubject); } } diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index f8ed32ae415c..570b1bb7e6c4 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -100,6 +100,7 @@ #include <sal/log.hxx> #include <unotools/ucbstreamhelper.hxx> #include <comphelper/diagnose_ex.hxx> +#include <unotxdoc.hxx> using namespace sax_fastparser; using namespace ::comphelper; @@ -1227,7 +1228,7 @@ void DocxExport::WriteSettings() m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_endnotePr, m_rDoc.GetEndNoteInfo(), XML_endnote ); // Has themeFontLang information - uno::Reference< beans::XPropertySet > xPropSet( pDocShell->GetBaseModel(), uno::UNO_QUERY_THROW ); + rtl::Reference< SwXTextDocument > xPropSet( pDocShell->GetXTextDocument() ); bool bUseGrabBagProtection = false; bool bWriterWantsToProtect = false; @@ -1501,7 +1502,7 @@ void DocxExport::WriteTheme() // See OOXMLDocumentImpl::resolveGlossaryStream void DocxExport::WriteGlossary() { - uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); + rtl::Reference< SwXTextDocument > xPropSet( m_rDoc.GetDocShell()->GetXTextDocument() ); uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; @@ -1664,7 +1665,7 @@ static void lcl_UpdateXmlValues(const SdtData& sdtData, const uno::Reference<css void DocxExport::WriteCustomXml() { - uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); + rtl::Reference< SwXTextDocument > xPropSet( m_rDoc.GetDocShell()->GetXTextDocument() ); uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); if ( !xPropSetInfo->hasPropertyByName( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) ) @@ -1766,7 +1767,7 @@ void DocxExport::WriteCustomXml() void DocxExport::WriteVBA() { - uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY); + rtl::Reference<SwXTextDocument> xStorageBasedDocument(m_rDoc.GetDocShell()->GetXTextDocument()); if (!xStorageBasedDocument.is()) return; @@ -1825,7 +1826,7 @@ void DocxExport::WriteVBA() void DocxExport::WriteEmbeddings() { - uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); + rtl::Reference< SwXTextDocument > xPropSet( m_rDoc.GetDocShell()->GetXTextDocument() ); uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; @@ -2075,7 +2076,7 @@ sal_Int32 DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt sal_Int32 DocxExport::getWordCompatibilityModeFromGrabBag() const { sal_Int32 nWordCompatibilityMode = -1; - uno::Reference< beans::XPropertySet > xPropSet(m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW); + rtl::Reference< SwXTextDocument > xPropSet(m_rDoc.GetDocShell()->GetXTextDocument()); uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); if (xPropSetInfo->hasPropertyByName(UNO_NAME_MISC_OBJ_INTEROPGRABBAG)) { diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx index 1cddf3070bfe..e74ecfa34974 100644 --- a/sw/source/uibase/app/docsh.cxx +++ b/sw/source/uibase/app/docsh.cxx @@ -103,6 +103,7 @@ #include <iodetect.hxx> #include <comphelper/processfactory.hxx> +#include <unotxdoc.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -887,6 +888,11 @@ void SwDocShell::Draw( OutputDevice* pDev, const JobSetup& rSetup, EnableSetModified(); } +rtl::Reference<SwXTextDocument> SwDocShell::GetXTextDocument() const +{ + return dynamic_cast<SwXTextDocument*>(GetBaseModel().get()); +} + void SwDocShell::SetVisArea( const tools::Rectangle &rRect ) { tools::Rectangle aRect( rRect ); diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx index c6376910f1a5..09c1f5ae0994 100644 --- a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx +++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx @@ -46,6 +46,7 @@ #include <inspectorproperties.hrc> #include <strings.hrc> #include <rdfhelper.hxx> +#include <unotxdoc.hxx> namespace sw::sidebar { @@ -439,8 +440,8 @@ static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& uno::UNO_QUERY); const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository(); const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY); - std::map<OUString, OUString> xStatements - = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject); + std::map<OUString, OUString> xStatements = SwRDFHelper::getStatements( + pDocSh->GetXTextDocument(), xRepo->getGraphNames(), xSubject); for (const auto& pair : xStatements) aCurNode.children.push_back(SimplePropToTreeNode(pair.first, uno::Any(pair.second))); } commit 4925d959785830edced1376f9a7c561d9eaadb60 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 28 19:56:25 2025 +0000 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jan 29 10:55:54 2025 +0100 SwXTextDocument::getBodyText can be used instead of getText here and that's already a rtl::Reference to SwXBodyText which is derived from SwXText Change-Id: I071c0711fef911deec4258ef9e6719b721a39de2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180864 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx index 5cb73bf7b8f0..9420380fbbe2 100644 --- a/sw/source/core/unocore/unoobj2.cxx +++ b/sw/source/core/unocore/unoobj2.cxx @@ -74,6 +74,7 @@ #include <frameformats.hxx> #include <algorithm> #include <iterator> +#include <unotxdoc.hxx> using namespace ::com::sun::star; @@ -1344,10 +1345,8 @@ CreateParentXText(SwDoc & rDoc, const SwPosition& rPos) if (SwDocShell *const pDocSh = rDoc.GetDocShell()) { // then it is the body text - const uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel(); - const uno::Reference< text::XTextDocument > xDoc( - xModel, uno::UNO_QUERY); - xParentText = dynamic_cast<SwXText*>(xDoc->getText().get()); + const rtl::Reference<SwXTextDocument> xModel = pDocSh->GetXTextDocument(); + xParentText = xModel->getBodyText(); } } } commit d197333db0fbf6647dce19e20bee265885224a74 Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Tue Jan 28 10:13:11 2025 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jan 29 09:10:11 2025 +0100 [API CHANGE] sd pdfium: add page number when saving/loading pdf pages as images When a pdf file is opened with pdfium and then saved as odg, each page is saved as a draw:image of the pdf. But since no page number info was given, when opening the odg file, all the pages are shown as the first one. This adds a loext:page-number to the saved odg and the logic to load a specific page from an embedded pdf. Added loadGraphicAtPage to XGraphicStorageHandler. Change-Id: I398b7ad7f03cc7fb930a4e7b7620c6f238b41c0d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180815 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/svx/xmlgrhlp.hxx b/include/svx/xmlgrhlp.hxx index 177d1afc4be6..6e84eb340e56 100644 --- a/include/svx/xmlgrhlp.hxx +++ b/include/svx/xmlgrhlp.hxx @@ -56,7 +56,8 @@ private: std::vector< css::uno::Reference< css::io::XOutputStream > > maGrfStms; - std::unordered_map<OUString, css::uno::Reference<css::graphic::XGraphic>> maGraphicObjects; + std::unordered_map<OUString, std::vector<css::uno::Reference<css::graphic::XGraphic>>> + maGraphicObjects; std::unordered_map<Graphic, std::pair<OUString, OUString>> maExportGraphics; SvXMLGraphicHelperMode meCreateMode; @@ -71,8 +72,9 @@ private: ImplGetGraphicStream( const OUString& rPictureStorageName, const OUString& rPictureStreamName ); SVX_DLLPRIVATE static OUString ImplGetGraphicMimeType( std::u16string_view rFileName ); - SVX_DLLPRIVATE Graphic ImplReadGraphic( const OUString& rPictureStorageName, - const OUString& rPictureStreamName ); + SVX_DLLPRIVATE Graphic ImplReadGraphic(const OUString& rPictureStorageName, + const OUString& rPictureStreamName, + sal_Int32 nPage = -1); SvXMLGraphicHelper(); virtual ~SvXMLGraphicHelper() override; @@ -101,6 +103,10 @@ public: virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphic(OUString const & aURL) override; + // XGraphicStorageHandler + virtual css::uno::Reference<css::graphic::XGraphic> + SAL_CALL loadGraphicAtPage(OUString const& aURL, sal_Int32 nPage) override; + virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphicFromOutputStream(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream) override; diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx index 531633b3f738..1f0e0cf99f53 100644 --- a/include/vcl/gfxlink.hxx +++ b/include/vcl/gfxlink.hxx @@ -103,7 +103,7 @@ public: bool IsNative() const; - bool LoadNative( Graphic& rGraphic ) const; + bool LoadNative(Graphic& rGraphic, sal_Int32 nPageNum = -1) const; bool ExportNative( SvStream& rOStream ) const; diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx index fd6c205bd491..2279feb9c499 100644 --- a/include/vcl/graphicfilter.hxx +++ b/include/vcl/graphicfilter.hxx @@ -275,10 +275,11 @@ public: sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat); - ErrCode ImportGraphic( Graphic& rGraphic, std::u16string_view rPath, - SvStream& rStream, - sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW, - sal_uInt16 * pDeterminedFormat = nullptr, GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE ); + ErrCode ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, SvStream& rStream, + sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW, + sal_uInt16* pDeterminedFormat = nullptr, + GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE, + sal_Int32 nPageNum = -1); /// Imports multiple graphics. /// @@ -292,7 +293,8 @@ public: void MakeGraphicsAvailableThreaded(std::vector< Graphic* >& rGraphics); // Setting sizeLimit limits how much will be read from the stream. - Graphic ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit = 0, const Size* pSizeHint = nullptr); + Graphic ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit = 0, + const Size* pSizeHint = nullptr, sal_Int32 nPage = -1); const ErrCode& GetLastError() const { return *mxErrorEx;} void ResetLastError(); @@ -320,7 +322,8 @@ public: static ErrCode readWMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); static ErrCode readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); - static ErrCode readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); + static ErrCode readPDF(SvStream& rStream, Graphic& rGraphic, GfxLinkType& rLinkType, + sal_Int32 nPageIndex = -1); static ErrCode readTIFF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); static ErrCode readWithTypeSerializer(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, std::u16string_view aFilterName); static ErrCode readBMP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index 72508a548293..4a78aa68b156 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -37,10 +37,11 @@ VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, /// Imports a PDF stream as a VectorGraphicData. VCL_DLLPUBLIC bool importPdfVectorGraphicData(SvStream& rStream, - std::shared_ptr<VectorGraphicData>& rVectorGraphicData); + std::shared_ptr<VectorGraphicData>& rVectorGraphicData, + sal_Int32 nPageIndex = -1); /// Imports a PDF stream into rGraphic. -VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic); +VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex = -1); // When inserting a PDF file as an image or pasting PDF data from the clipboard, at least on a // Retina iMac, the resulting rendered image does not look sharp without this surprisingly large diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx index b4616056c4ec..8df68e378629 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -410,7 +410,8 @@ public: mxNumberFormatsSupplier = _xNumberFormatSupplier; } - css::uno::Reference<css::graphic::XGraphic> loadGraphicByURL(OUString const & rURL); + css::uno::Reference<css::graphic::XGraphic> loadGraphicByURL(OUString const& rURL, + sal_Int32 nPageNum = -1); css::uno::Reference<css::graphic::XGraphic> loadGraphicFromBase64(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream); css::uno::Reference< css::io::XOutputStream > GetStreamForGraphicObjectURLFromBase64() const; diff --git a/offapi/com/sun/star/document/XGraphicStorageHandler.idl b/offapi/com/sun/star/document/XGraphicStorageHandler.idl index b36379890243..7390b189394f 100644 --- a/offapi/com/sun/star/document/XGraphicStorageHandler.idl +++ b/offapi/com/sun/star/document/XGraphicStorageHandler.idl @@ -21,6 +21,10 @@ interface XGraphicStorageHandler : com::sun::star::uno::XInterface */ com::sun::star::graphic::XGraphic loadGraphic([in] string aURL); + /** load a specific page from a graphic defined by the URL from the storage + */ + com::sun::star::graphic::XGraphic loadGraphicAtPage([in] string aURL, [in] long nPage); + /** load a graphic from the output stream */ com::sun::star::graphic::XGraphic loadGraphicFromOutputStream([in] com::sun::star::io::XOutputStream xOutputStream); diff --git a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng index a68033d1954e..551a5ee46735 100644 --- a/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng @@ -3896,4 +3896,13 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. </rng:attribute> </rng:optional> </rng:define> + + <!-- TODO no proposal for page number on multipage formats --> + <rng:define name="draw-image-attlist" combine="interleave"> + <rng:optional> + <rng:attribute name="loext:page-number"> + <rng:ref name="integer"/> + </rng:attribute> + </rng:optional> + </rng:define> </rng:grammar> diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx index 03e42c961b13..cccee7ce99f2 100644 --- a/svx/source/xml/xmlgrhlp.cxx +++ b/svx/source/xml/xmlgrhlp.cxx @@ -491,8 +491,8 @@ OUString SvXMLGraphicHelper::ImplGetGraphicMimeType( std::u16string_view rFileNa return OUString(); } -Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName, - const OUString& rPictureStreamName ) +Graphic SvXMLGraphicHelper::ImplReadGraphic(const OUString& rPictureStorageName, + const OUString& rPictureStreamName, sal_Int32 nPage) { Graphic aReturnGraphic; SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName ) ); @@ -500,11 +500,12 @@ Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName { GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter(); std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(aStream.xStream)); - Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream); + Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream, 0, nullptr, nPage); if (!aGraphic.IsNone()) aReturnGraphic = aGraphic; else - rGraphicFilter.ImportGraphic(aReturnGraphic, u"", *pStream); + rGraphicFilter.ImportGraphic(aReturnGraphic, u"", *pStream, GRFILTER_FORMAT_DONTKNOW, + nullptr, GraphicFilterImportFlags::NONE, nPage); } return aReturnGraphic; @@ -566,6 +567,13 @@ OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString& / // XGraphicStorageHandler uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicHelper::loadGraphic(OUString const & rURL) +{ + return loadGraphicAtPage(rURL, -1); +} + +// XGraphicStorageHandler +uno::Reference<graphic::XGraphic> + SAL_CALL SvXMLGraphicHelper::loadGraphicAtPage(OUString const& rURL, sal_Int32 nPage) { std::unique_lock aGuard(m_aMutex); @@ -575,22 +583,36 @@ uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicHelper::loadGraphic(OUStr OUString aUserData; splitUserDataFromURL(rURL, aURLOnly, aUserData); + size_t nIndex = (nPage >= 0 ? nPage : 0); auto aIterator = maGraphicObjects.find(aURLOnly); - if (aIterator != maGraphicObjects.end()) + if (aIterator != maGraphicObjects.end() && aIterator->second.size() > nIndex + && aIterator->second[nIndex].is()) { - return aIterator->second; + return aIterator->second[nIndex]; } OUString aPictureStorageName, aPictureStreamName; if (ImplGetStreamNames(aURLOnly, aPictureStorageName, aPictureStreamName)) { - const GraphicObject aGraphicObject(ImplReadGraphic(aPictureStorageName, aPictureStreamName)); + const GraphicObject aGraphicObject( + ImplReadGraphic(aPictureStorageName, aPictureStreamName, nPage)); if (aGraphicObject.GetType() != GraphicType::NONE) { xGraphic = aGraphicObject.GetGraphic().GetXGraphic(); - maGraphicObjects[aURLOnly] = xGraphic; + if (aIterator != maGraphicObjects.end()) + { + if (aIterator->second.size() <= nIndex) + aIterator->second.resize(nIndex + 1); + aIterator->second[nIndex] = xGraphic; + } + else + { + maGraphicObjects.emplace( + aURLOnly, std::vector<uno::Reference<graphic::XGraphic>>(nIndex + 1)); + maGraphicObjects[aURLOnly][nIndex] = xGraphic; + } } } @@ -958,6 +980,10 @@ protected: virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphic(const OUString& aURL) override; + // ____ XGraphicStorageHandler ____ + virtual css::uno::Reference<css::graphic::XGraphic> + SAL_CALL loadGraphicAtPage(const OUString& aURL, sal_Int32 nPage) override; + virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphicFromOutputStream(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream) override; @@ -1021,6 +1047,13 @@ uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicImportExportHelper::loadG return m_xXMLGraphicHelper->loadGraphic(rURL); } +// ____ XGraphicStorageHandler ____ +uno::Reference<graphic::XGraphic> SAL_CALL +SvXMLGraphicImportExportHelper::loadGraphicAtPage(OUString const& rURL, sal_Int32 nPage) +{ + return m_xXMLGraphicHelper->loadGraphicAtPage(rURL, nPage); +} + uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicImportExportHelper::loadGraphicFromOutputStream(uno::Reference<io::XOutputStream> const & rxOutputStream) { return m_xXMLGraphicHelper->loadGraphicFromOutputStream(rxOutputStream); diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index 2e2b00640a20..9d6acd77e680 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -39,7 +39,7 @@ struct ImpSwapInfo bool mbIsAlpha; sal_uInt32 mnAnimationLoopCount; - sal_Int32 mnPageIndex; + sal_Int32 mnPageIndex = -1; }; class OutputDevice; diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx index a7e0ffe972a4..0939702c57f0 100644 --- a/vcl/source/filter/graphicfilter.cxx +++ b/vcl/source/filter/graphicfilter.cxx @@ -718,7 +718,7 @@ void GraphicFilter::MakeGraphicsAvailableThreaded(std::vector<Graphic*>& graphic } Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit, - const Size* pSizeHint) + const Size* pSizeHint, sal_Int32 nPage) { Graphic aGraphic; sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW; @@ -907,7 +907,10 @@ Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 size pSizeHint = &aLogicSize; } } - aGraphic.SetGfxLink(std::make_shared<GfxLink>(aGraphicContent, eLinkType)); + if (eLinkType == GfxLinkType::NativePdf && nPage >= 0) + aGraphic = Graphic(std::make_shared<GfxLink>(aGraphicContent, eLinkType), nPage); + else + aGraphic.SetGfxLink(std::make_shared<GfxLink>(aGraphicContent, eLinkType)); aGraphic.ImplGetImpGraphic()->setPrepared(bAnimated, pSizeHint); } } @@ -1115,9 +1118,10 @@ ErrCode GraphicFilter::readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkTy return readWMF_EMF(rStream, rGraphic, rLinkType, VectorGraphicDataType::Emf); } -ErrCode GraphicFilter::readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType) +ErrCode GraphicFilter::readPDF(SvStream& rStream, Graphic& rGraphic, GfxLinkType& rLinkType, + sal_Int32 nPageIndex) { - if (vcl::ImportPDF(rStream, rGraphic)) + if (vcl::ImportPDF(rStream, rGraphic, nPageIndex)) { rLinkType = GfxLinkType::NativePdf; return ERRCODE_NONE; @@ -1274,8 +1278,10 @@ ErrCode GraphicFilter::readWEBP(SvStream & rStream, Graphic & rGraphic, GfxLinkT return ERRCODE_GRFILTER_FILTERERROR; } -ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, SvStream& rIStream, - sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags) +ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, + SvStream& rIStream, sal_uInt16 nFormat, + sal_uInt16* pDeterminedFormat, + GraphicFilterImportFlags nImportFlags, sal_Int32 nPageIndex) { OUString aFilterName; sal_uInt64 nStreamBegin; @@ -1375,7 +1381,7 @@ ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPat } else if (aFilterName.equalsIgnoreAsciiCase(IMP_PDF)) { - nStatus = readPDF(rIStream, rGraphic, eLinkType); + nStatus = readPDF(rIStream, rGraphic, eLinkType, nPageIndex); } else if (aFilterName.equalsIgnoreAsciiCase(IMP_TIFF) ) { diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 148a46f5da11..a5f939c7be50 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -102,7 +102,8 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<BitmapEx>& r } bool importPdfVectorGraphicData(SvStream& rStream, - std::shared_ptr<VectorGraphicData>& rVectorGraphicData) + std::shared_ptr<VectorGraphicData>& rVectorGraphicData, + sal_Int32 nPageIndex) { BinaryDataContainer aDataContainer = vcl::pdf::createBinaryDataContainer(rStream); if (aDataContainer.isEmpty()) @@ -111,16 +112,16 @@ bool importPdfVectorGraphicData(SvStream& rStream, return false; } - rVectorGraphicData - = std::make_shared<VectorGraphicData>(aDataContainer, VectorGraphicDataType::Pdf); + rVectorGraphicData = std::make_shared<VectorGraphicData>( + aDataContainer, VectorGraphicDataType::Pdf, nPageIndex); return true; } -bool ImportPDF(SvStream& rStream, Graphic& rGraphic) +bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex) { std::shared_ptr<VectorGraphicData> pVectorGraphicData; - if (!importPdfVectorGraphicData(rStream, pVectorGraphicData)) + if (!importPdfVectorGraphicData(rStream, pVectorGraphicData, nPageIndex)) return false; rGraphic = Graphic(pVectorGraphicData); return true; diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx index c6ca4678b007..aff0e9778980 100644 --- a/vcl/source/gdi/gfxlink.cxx +++ b/vcl/source/gdi/gfxlink.cxx @@ -101,7 +101,7 @@ void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode ) mbPrefMapModeValid = true; } -bool GfxLink::LoadNative( Graphic& rGraphic ) const +bool GfxLink::LoadNative(Graphic& rGraphic, sal_Int32 nPageNum) const { bool bRet = false; @@ -132,7 +132,9 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) const { GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); sal_uInt16 nFormat = rFilter.GetImportFormatNumberForShortName(aShortName); - ErrCode nResult = rFilter.ImportGraphic(rGraphic, u"", aMemoryStream, nFormat); + ErrCode nResult + = rFilter.ImportGraphic(rGraphic, u"", aMemoryStream, nFormat, nullptr, + GraphicFilterImportFlags::NONE, nPageNum); if (nResult == ERRCODE_NONE) bRet = true; } diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index ac36d2c72be4..6c5f8f870154 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -1502,7 +1502,7 @@ bool ImpGraphic::swapIn() if (mbPrepared) { Graphic aGraphic; - if (!mpGfxLink->LoadNative(aGraphic)) + if (!mpGfxLink->LoadNative(aGraphic, getPageNumber())) return false; updateFromLoadedGraphic(aGraphic.ImplGetImpGraphic()); diff --git a/xmloff/qa/unit/data/two-pages.pdf b/xmloff/qa/unit/data/two-pages.pdf new file mode 100644 index 000000000000..838c2d3232b1 Binary files /dev/null and b/xmloff/qa/unit/data/two-pages.pdf differ diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx index 8d89065d4438..525c703c5eaa 100644 --- a/xmloff/qa/unit/draw.cxx +++ b/xmloff/qa/unit/draw.cxx @@ -31,6 +31,7 @@ #include <docmodel/uno/UnoComplexColor.hxx> #include <docmodel/uno/UnoTheme.hxx> #include <docmodel/theme/Theme.hxx> +#include <comphelper/scopeguard.hxx> using namespace ::com::sun::star; @@ -810,6 +811,50 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testTdf157018_ThemeImportDraw) CPPUNIT_ASSERT_EQUAL(Color(0x0A0A0A), pColorSet->getColor(model::ThemeColorType::Hyperlink)); CPPUNIT_ASSERT_EQUAL(Color(0x440000), pColorSet->getColor(model::ThemeColorType::Accent1)); } + +CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testPdfExportAsOdg) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return; + } + +// setenv only works on unix based systems +#ifndef _WIN32 + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + setenv("LO_IMPORT_USE_PDFIUM", "1", false); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + unsetenv("LO_IMPORT_USE_PDFIUM"); + }); + + loadFromFile(u"two-pages.pdf"); + // save and reload as odg + saveAndReload("draw8"); + + // Check that the graphic in the second page of the document is the second page of the pdf + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, + uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDrawPagesSupplier.is()); + uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages()); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(1), uno::UNO_QUERY_THROW); + uno::Reference<drawing::XShape> xImage(xDrawPage->getByIndex(0), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xImage.is()); + uno::Reference<beans::XPropertySet> xShapeProps(xImage, uno::UNO_QUERY); + uno::Reference<graphic::XGraphic> xGraphic; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue("Graphic") >>= xGraphic); + + Graphic aGraphic(xGraphic); + CPPUNIT_ASSERT_EQUAL(1, aGraphic.getPageNumber()); +#endif +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index e6b1aa66ee7f..cd89ce6cd303 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -1302,7 +1302,8 @@ bool SvXMLImport::IsPackageURL( std::u16string_view rURL ) const return true; } -uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const & rURL) +uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const& rURL, + sal_Int32 nPageNum) { uno::Reference<graphic::XGraphic> xGraphic; @@ -1312,7 +1313,7 @@ uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const & { if (IsPackageURL(rURL)) { - xGraphic = mxGraphicStorageHandler->loadGraphic(rURL); + xGraphic = mxGraphicStorageHandler->loadGraphicAtPage(rURL, nPageNum); } else { diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index cbb027829713..0ac3fe2cc475 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -2496,12 +2496,12 @@ void XMLShapeExport::ImpExportGraphicObjectShape( } { + if (sOutMimeType.isEmpty()) + { + GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType); + } if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012) { - if (sOutMimeType.isEmpty()) - { - GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType); - } if (!sOutMimeType.isEmpty()) { // ODF 1.3 OFFICE-3943 GetExport().AddAttribute( @@ -2512,6 +2512,15 @@ void XMLShapeExport::ImpExportGraphicObjectShape( } } + if (sOutMimeType == "application/pdf") + { + Graphic aGraphic(xGraphic); + sal_Int32 nPage = aGraphic.getPageNumber(); + if (nPage >= 0) + GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PAGE_NUMBER, + OUString::number(nPage)); + } + SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true); // optional office:binary-data diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index aaee9668fa37..45929e2fb6f4 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -2358,10 +2358,10 @@ bool SdXMLCaptionShapeContext::processAttribute( const sax_fastparser::FastAttri SdXMLGraphicObjectShapeContext::SdXMLGraphicObjectShapeContext( - SvXMLImport& rImport, - const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList, - uno::Reference< drawing::XShapes > const & rShapes) -: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ) + SvXMLImport& rImport, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList, + uno::Reference<drawing::XShapes> const& rShapes) + : SdXMLShapeContext(rImport, xAttrList, rShapes, false /*bTemporaryShape*/) + , mnPage(-1) { } @@ -2377,6 +2377,9 @@ bool SdXMLGraphicObjectShapeContext::processAttribute( const sax_fastparser::Fas case XML_ELEMENT(LO_EXT, XML_MIME_TYPE): msMimeType = aIter.toString(); break; + case XML_ELEMENT(LO_EXT, XML_PAGE_NUMBER): + mnPage = aIter.toInt32(); + break; default: return SdXMLShapeContext::processAttribute(aIter); } @@ -2429,7 +2432,8 @@ void SdXMLGraphicObjectShapeContext::startFastElement (sal_Int32 nElement, { if( !maURL.isEmpty() ) { - uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicByURL(maURL); + uno::Reference<graphic::XGraphic> xGraphic + = GetImport().loadGraphicByURL(maURL, mnPage); if (xGraphic.is()) { xPropset->setPropertyValue("Graphic", uno::Any(xGraphic)); diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 9a61f4b594de..6a00cb252e5f 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -392,6 +392,7 @@ private: OUString maURL; OUString msMimeType; css::uno::Reference < css::io::XOutputStream > mxBase64Stream; + sal_Int32 mnPage; public: OUString const& getMimeType() const { return msMimeType; }