Hi guys, I attach a back-port of Lubos' patch from master fixing this for 3.4.5 - I'd love a 2nd review to get it included before Wed ;-)
One slight annoyance is that what we export as docx with this patch is re-imported with broken styles: ie. the comments are all strike-through (by 3.4). However, that seems to be an un-related import bug, MSO/LibO 3.5 etc. all render the comments with the correct style. And, regardless of the rendering, this avoids annoying comment data loss. HTH, Michael. -- michael.me...@suse.com <><, Pseudo Engineer, itinerant idiot
>From 9d6d74733ba66e6aa2264c549fac47699c8acf59 Mon Sep 17 00:00:00 2001 From: Michael Meeks <michael.me...@suse.com> Date: Tue, 13 Dec 2011 09:29:32 +0000 Subject: [PATCH] docx: Back-port Lubos' comment export work fdo#33463 --- sw/inc/docufld.hxx | 1 + sw/source/filter/ww8/attributeoutputbase.hxx | 3 + sw/source/filter/ww8/docxattributeoutput.cxx | 50 +++++++++++++++-- sw/source/filter/ww8/docxattributeoutput.hxx | 8 +++ sw/source/filter/ww8/docxexport.cxx | 76 +++++++++++++++++++++++++- sw/source/filter/ww8/docxexport.hxx | 5 ++ sw/source/filter/ww8/wrtw8nds.cxx | 2 + 7 files changed, 138 insertions(+), 7 deletions(-) diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx index 1818bec..3240aa2 100644 --- a/sw/inc/docufld.hxx +++ b/sw/inc/docufld.hxx @@ -532,6 +532,7 @@ public: virtual String Expand() const; virtual SwField* Copy() const; + inline const DateTime GetDateTime() const { return aDateTime; } inline const Date GetDate() const { return aDateTime.GetDate(); } inline const Time GetTime() const { return aDateTime.GetTime(); } diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 84e58f7..92385fd 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -173,6 +173,9 @@ public: /// docx requires footnoteRef/endnoteRef tag at the beginning of each of them virtual void FootnoteEndnoteRefTag() {}; + /// for docx w:commentReference + virtual void WritePostitFieldReference() {}; + /// Output text (inside a run). virtual void RunText( const String& rText, rtl_TextEncoding eCharSet ) = 0; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 693549c..5dfb281 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -548,7 +548,7 @@ void DocxAttributeOutput::EndRun() } // Write the hyperlink and toc fields starts - for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt ) + for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ) { // Add the fields starts for hyperlinks, TOCs and index marks if ( pIt->bOpen && !pIt->pField ) @@ -557,10 +557,11 @@ void DocxAttributeOutput::EndRun() // Remove the field if no end needs to be written if ( !pIt->bClose ) { - m_Fields.erase( pIt ); - --pIt; + pIt = m_Fields.erase( pIt ); + continue; } } + ++pIt; } DoWriteBookmarks( ); @@ -3212,9 +3213,40 @@ void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ ) OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()\n" ); } -void DocxAttributeOutput::PostitField( const SwField* /* pFld*/ ) +void DocxAttributeOutput::PostitField( const SwField* pFld ) { - OSL_TRACE( "TODO DocxAttributeOutput::PostitField()\n" ); + assert( dynamic_cast< const SwPostItField* >( pFld )); + m_postitFields.push_back( static_cast< const SwPostItField* >( pFld )); +} + +void DocxAttributeOutput::WritePostitFieldReference() +{ + while( m_postitFieldsMaxId < m_postitFields.size()) + { + OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId )); + m_pSerializer->singleElementNS( XML_w, XML_commentReference, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND ); + ++m_postitFieldsMaxId; + } +} + +void DocxAttributeOutput::WritePostitFields() +{ + for( unsigned int i = 0; + i < m_postitFields.size(); + ++i ) + { + OString idstr = OString::valueOf( sal_Int32( i )); + const SwPostItField* f = m_postitFields[ i ]; + m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, XML_id ), idstr.getStr(), + FSNS( XML_w, XML_author ), rtl::OUStringToOString( f->GetPar1(), RTL_TEXTENCODING_UTF8 ).getStr(), + FSNS( XML_w, XML_date ), impl_DateTimeToOString(f->GetDateTime()).getStr(), FSEND ); + // Check for the text object existing, it seems that it can be NULL when saving a newly created + // comment without giving focus back to the main document. As GetTxt() is empty in that case as well, + // that is probably a bug in the Writer core. + if( f->GetTextObject() != NULL ) + GetExport().WriteOutliner( *f->GetTextObject(), TXT_ATN ); + m_pSerializer->endElementNS( XML_w, XML_comment ); + } } bool DocxAttributeOutput::DropdownField( const SwField* pFld ) @@ -4118,7 +4150,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_nTableDepth( 0 ), m_bParagraphOpened( false ), m_nColBreakStatus( COLBRK_NONE ), - m_pParentFrame( NULL ) + m_pParentFrame( NULL ), + m_postitFieldsMaxId( 0 ) { } @@ -4154,4 +4187,9 @@ bool DocxAttributeOutput::HasEndnotes() return !m_pEndnotesList->isEmpty(); } +bool DocxAttributeOutput::HasPostitFields() const +{ + return !m_postitFields.empty(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 0875b46..3c80b8f 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -102,6 +102,8 @@ public: virtual void FootnoteEndnoteRefTag(); + virtual void WritePostitFieldReference(); + /// Output text (inside a run). virtual void RunText( const String& rText, rtl_TextEncoding eCharSet = RTL_TEXTENCODING_UTF8 ); @@ -579,6 +581,9 @@ private: const sw::Frame *m_pParentFrame; + std::vector< const SwPostItField* > m_postitFields; + unsigned int m_postitFieldsMaxId; + public: DocxAttributeOutput( DocxExport &rExport, ::sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML ); @@ -602,6 +607,9 @@ public: /// Output the content of the footnotes.xml resp. endnotes.xml void FootnotesEndnotes( bool bFootnotes ); + + bool HasPostitFields() const; + void WritePostitFields(); }; #endif // _DOCXATTRIBUTEOUTPUT_HXX_ diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 33312da..0b29aea 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -53,6 +53,9 @@ #include <frmfmt.hxx> #include <section.hxx> +#include <editeng/editobj.hxx> +#include <editeng/outlobj.hxx> + #include <docary.hxx> #include <numrule.hxx> #include <charfmt.hxx> @@ -337,7 +340,9 @@ void DocxExport::ExportDocument_Impl() WriteMainText(); WriteFootnotesEndnotes(); - + + WritePostitFields(); + WriteNumbering(); WriteFonts(); @@ -515,6 +520,26 @@ void DocxExport::WriteFootnotesEndnotes() } } +void DocxExport::WritePostitFields() +{ + if ( m_pAttrOutput->HasPostitFields() ) + { + m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), + S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" ), + S( "comments.xml" ) ); + + ::sax_fastparser::FSHelperPtr pPostitFS = + m_pFilter->openFragmentStreamWithSerializer( S( "word/comments.xml" ), + S( "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" ) ); + + pPostitFS->startElementNS( XML_w, XML_comments, MainXmlNamespaces( pPostitFS )); + m_pAttrOutput->SetSerializer( pPostitFS ); + m_pAttrOutput->WritePostitFields(); + m_pAttrOutput->SetSerializer( m_pDocumentFS ); + pPostitFS->endElementNS( XML_w, XML_comments ); + } +} + void DocxExport::WriteNumbering() { if ( !pUsedNumTbl ) @@ -716,6 +741,55 @@ bool DocxExport::ignoreAttributeForStyles( sal_uInt16 nWhich ) const return MSWordExportBase::ignoreAttributeForStyles( nWhich ); } +void DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp) +{ + const EditTextObject& rEditObj = rParaObj.GetTextObject(); + MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp ); + + sal_uInt16 nPara = rEditObj.GetParagraphCount(); + for( sal_uInt16 n = 0; n < nPara; ++n ) + { + if( n ) + aAttrIter.NextPara( n ); + + AttrOutput().StartParagraph( ww8::WW8TableNodeInfo::Pointer_t()); + rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet(); + String aStr( rEditObj.GetText( n )); + xub_StrLen nAktPos = 0; + xub_StrLen nEnd = aStr.Len(); + do { + AttrOutput().StartRun( NULL ); + xub_StrLen nNextAttr = aAttrIter.WhereNext(); + rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet(); + + if( nNextAttr > nEnd ) + nNextAttr = nEnd; + + bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos ); + if( !bTxtAtr ) + { + if( nAktPos == 0 && nNextAttr - nAktPos == aStr.Len()) + AttrOutput().RunText( aStr, eChrSet ); + else + { + String tmp( aStr.Copy( nAktPos, nNextAttr - nAktPos )); + AttrOutput().RunText( tmp, eChrSet ); + } + } + AttrOutput().StartRunProperties(); + aAttrIter.OutAttr( nAktPos ); + AttrOutput().EndRunProperties( NULL ); + + nAktPos = nNextAttr; + eChrSet = eNextChrSet; + aAttrIter.NextPos(); + AttrOutput().EndRun(); + } while( nAktPos < nEnd ); +// aAttrIter.OutParaAttr(false); + AttrOutput().EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t()); + } +} + DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam ) : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ), m_pFilter( pFilter ), diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index ee84dcd..3eaec51 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -152,6 +152,8 @@ public: /// Returns the relationd id rtl::OString OutputChart( com::sun::star::uno::Reference< com::sun::star::frame::XModel >& xModel, sal_Int32 nCount ); + void WriteOutliner(const OutlinerParaObject& rOutliner, sal_uInt8 nTyp); + protected: /// Format-dependant part of the actual export. virtual void ExportDocument_Impl(); @@ -190,6 +192,9 @@ private: /// Write footnotes.xml and endnotes.xml. void WriteFootnotesEndnotes(); + /// Write comments.xml + void WritePostitFields(); + /// Write the numbering table. virtual void WriteNumbering(); diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 02659bf..fae1dbc 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -2020,6 +2020,8 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode ) } } + AttrOutput().WritePostitFieldReference(); + AttrOutput().EndRun(); nAktPos = nNextAttr; -- 1.7.3.4
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice