[Libreoffice-commits] core.git: 3 commits - sc/inc sc/Library_scfilt.mk sc/qa sc/source
Kohei Yoshida
kohei.yoshida at collabora.com
Fri Jul 18 10:14:06 PDT 2014
sc/Library_scfilt.mk | 1
sc/inc/chgtrack.hxx | 2
sc/qa/unit/data/xlsx/track-changes/simple-cell-changes.xlsx |binary
sc/qa/unit/subsequent_export-test.cxx | 28
sc/source/filter/excel/xestream.cxx | 7
sc/source/filter/inc/XclExpChangeTrack.hxx | 70 +
sc/source/filter/inc/revisionfragment.hxx | 79 ++
sc/source/filter/inc/xestream.hxx | 10
sc/source/filter/oox/revisionfragment.cxx | 462 ++++++++++++
sc/source/filter/oox/workbookfragment.cxx | 11
sc/source/filter/xcl97/XclExpChangeTrack.cxx | 313 +++++---
11 files changed, 853 insertions(+), 130 deletions(-)
New commits:
commit 4edbaa38af4025564c0154985705c2785b7ff345
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Fri Jul 18 11:30:07 2014 -0400
bnc#885548: Add test for import / export of revisions for xlsx.
It's the same test as with the xls variant.
Change-Id: Ice3d3c34213cc521e2782ef0f98d28d135c72fbe
diff --git a/sc/qa/unit/data/xlsx/track-changes/simple-cell-changes.xlsx b/sc/qa/unit/data/xlsx/track-changes/simple-cell-changes.xlsx
new file mode 100755
index 0000000..29e8027
Binary files /dev/null and b/sc/qa/unit/data/xlsx/track-changes/simple-cell-changes.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 270c7dc..f91a2de 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -93,7 +93,7 @@ public:
void testCellBordersXLS();
void testCellBordersXLSX();
- void testTrackChangesSimpleXLS();
+ void testTrackChangesSimpleXLSX();
void testSheetTabColorsXLSX();
void testSharedFormulaExportXLS();
@@ -132,7 +132,7 @@ public:
CPPUNIT_TEST(testSheetProtectionXLSX);
CPPUNIT_TEST(testCellBordersXLS);
CPPUNIT_TEST(testCellBordersXLSX);
- CPPUNIT_TEST(testTrackChangesSimpleXLS);
+ CPPUNIT_TEST(testTrackChangesSimpleXLSX);
CPPUNIT_TEST(testSheetTabColorsXLSX);
CPPUNIT_TEST(testSharedFormulaExportXLS);
CPPUNIT_TEST(testSharedFormulaExportXLSX);
@@ -1327,7 +1327,7 @@ OUString toString( const ScBigRange& rRange )
return aBuf.makeStringAndClear();
}
-void ScExportTest::testTrackChangesSimpleXLS()
+void ScExportTest::testTrackChangesSimpleXLSX()
{
struct CheckItem
{
@@ -1450,17 +1450,19 @@ void ScExportTest::testTrackChangesSimpleXLS()
} aTest;
+ // First, test the xls variant.
+
ScDocShellRef xDocSh = loadDoc("track-changes/simple-cell-changes.", XLS);
CPPUNIT_ASSERT(xDocSh.Is());
ScDocument* pDoc = &xDocSh->GetDocument();
bool bGood = aTest.check(*pDoc);
- CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bGood);
+ CPPUNIT_ASSERT_MESSAGE("Initial check failed (xls).", bGood);
ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLS);
xDocSh->DoClose();
pDoc = &xDocSh2->GetDocument();
bGood = aTest.check(*pDoc);
- CPPUNIT_ASSERT_MESSAGE("Check after reload failed.", bGood);
+ CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xls).", bGood);
// fdo#81445 : Check the blank value string to make sure it's "<empty>".
ScChangeTrack* pCT = pDoc->GetChangeTrack();
@@ -1472,6 +1474,22 @@ void ScExportTest::testTrackChangesSimpleXLS()
CPPUNIT_ASSERT_EQUAL(OUString("Cell B2 changed from '<empty>' to '1'"), aDesc);
xDocSh2->DoClose();
+
+ // Now, test the xlsx variant the same way.
+
+ xDocSh = loadDoc("track-changes/simple-cell-changes.", XLSX);
+ CPPUNIT_ASSERT(xDocSh.Is());
+ pDoc = &xDocSh->GetDocument();
+ aTest.check(*pDoc);
+ CPPUNIT_ASSERT_MESSAGE("Initial check failed (xlsx).", bGood);
+
+ xDocSh2 = saveAndReload(xDocSh, XLSX);
+ xDocSh->DoClose();
+ pDoc = &xDocSh2->GetDocument();
+ bGood = aTest.check(*pDoc);
+ CPPUNIT_ASSERT_MESSAGE("Check after reload failed (xlsx).", bGood);
+
+ xDocSh2->DoClose();
}
void ScExportTest::testSheetTabColorsXLSX()
commit fa44673e154ed4fb0b518b8850e2f6e4b9069531
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Thu Jul 17 20:20:16 2014 -0400
bnc#885548: Adjust xlsx export of revisions to get it to work in Excel.
Change-Id: I0058d9ddfea545390e615a3030171a366e333c85
diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index 362ba34..7aaf648 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -831,6 +831,13 @@ const char* XclXmlUtils::ToPsz( bool b )
return b ? "true" : "false";
}
+const char* XclXmlUtils::ToPsz10( bool b )
+{
+ // xlsx seems to use "1" or "0" for boolean values. I wonder it ever uses
+ // the "true" "false" variant.
+ return b ? "1" : "0";
+}
+
sax_fastparser::FSHelperPtr XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int32 nValue )
{
pStream->startElement( nElement, FSEND );
diff --git a/sc/source/filter/inc/XclExpChangeTrack.hxx b/sc/source/filter/inc/XclExpChangeTrack.hxx
index 2ef29b7..12b249f 100644
--- a/sc/source/filter/inc/XclExpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclExpChangeTrack.hxx
@@ -31,6 +31,14 @@
#include <boost/ptr_container/ptr_vector.hpp>
+class ExcXmlRecord : public ExcRecord
+{
+public:
+ virtual sal_Size GetLen() const SAL_OVERRIDE;
+ virtual sal_uInt16 GetNum() const SAL_OVERRIDE;
+ virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+};
+
// XclExpUserBView - one UserBView record for each user
class XclExpUserBView : public ExcRecord
@@ -228,40 +236,61 @@ public:
virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
};
+class XclExpXmlChTrHeaders : public ExcXmlRecord
+{
+ sal_uInt8 maGUID[16];
+public:
+ void SetGUID( const sal_uInt8* pGUID );
+
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+};
+
+class XclExpChTrTabIdBuffer;
+class XclExpChTrAction;
+
+class XclExpXmlChTrHeader : public ExcXmlRecord
+{
+ OUString maUserName;
+ DateTime maDateTime;
+ sal_uInt8 maGUID[16];
+ sal_Int32 mnLogNumber;
+ sal_uInt32 mnMinAction;
+ sal_uInt32 mnMaxAction;
+
+ std::vector<sal_uInt16> maTabBuffer;
+ std::vector<XclExpChTrAction*> maActions;
+
+public:
+ XclExpXmlChTrHeader(
+ const OUString& rUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
+ sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf );
+
+ virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
+ void AppendAction( XclExpChTrAction* pAction );
+};
+
// XclExpChTrInfo - header of action group of a user
class XclExpChTrInfo : public ExcRecord
{
private:
XclExpString sUsername;
- sal_Int32 mnLogNumber;
DateTime aDateTime;
sal_uInt8 aGUID[ 16 ];
virtual void SaveCont( XclExpStream& rStrm ) SAL_OVERRIDE;
public:
- inline XclExpChTrInfo(
- const OUString& rUsername,
- const DateTime& rDateTime,
- const sal_uInt8* pGUID,
- sal_Int32 nLogNumber );
+ XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime,
+ const sal_uInt8* pGUID );
+
virtual ~XclExpChTrInfo();
virtual sal_uInt16 GetNum() const SAL_OVERRIDE;
virtual sal_Size GetLen() const SAL_OVERRIDE;
-
- virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
};
-inline XclExpChTrInfo::XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime, const sal_uInt8* pGUID, sal_Int32 nLogNumber ) :
- sUsername( rUsername ),
- mnLogNumber( nLogNumber ),
- aDateTime( rDateTime )
-{
- memcpy( aGUID, pGUID, 16 );
-}
-
// XclExpChTrTabIdBuffer - buffer for tab id's
class XclExpChTrTabIdBuffer
@@ -296,7 +325,6 @@ class XclExpChTrTabId : public ExcRecord
private:
sal_uInt16* pBuffer;
sal_uInt16 nTabCount;
- bool mbInRevisionHeaders;
inline void Clear() { if( pBuffer ) delete[] pBuffer; pBuffer = NULL; }
@@ -304,16 +332,14 @@ private:
public:
inline XclExpChTrTabId( sal_uInt16 nCount ) :
- pBuffer( NULL ), nTabCount( nCount ), mbInRevisionHeaders( false ) {}
- XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer, bool bInRevisionHeaders = false );
+ pBuffer( NULL ), nTabCount( nCount ) {}
+ XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer );
virtual ~XclExpChTrTabId();
void Copy( const XclExpChTrTabIdBuffer& rBuffer );
virtual sal_uInt16 GetNum() const SAL_OVERRIDE;
virtual sal_Size GetLen() const SAL_OVERRIDE;
-
- virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
};
// XclExpChTrAction - base class for action records
@@ -361,7 +387,6 @@ protected:
// do something after writing the record
virtual void CompleteSaveAction( XclExpStream& rStrm ) const;
- inline sal_uInt32 GetActionNumber() const { return nIndex; }
inline bool GetAccepted() const { return bAccepted; }
public:
@@ -385,6 +410,7 @@ public:
virtual sal_Size GetLen() const SAL_OVERRIDE;
inline XclExpChTrAction* GetAddAction() { return pAddAction; }
+ inline sal_uInt32 GetActionNumber() const { return nIndex; }
};
inline void XclExpChTrAction::Write2DAddress( XclExpStream& rStrm, const ScAddress& rAddress ) const
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index e69e0c7..c705e45 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -277,8 +277,18 @@ public:
static OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
static OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress, const ScTokenArray* pTokenArray );
static OUString ToOUString( const XclExpString& s );
+
+ /**
+ * @return const char* literal "true" for true value, or literal "false"
+ * for false value.
+ */
static const char* ToPsz( bool b );
+ /**
+ * @return literal "1" for true value, or literal "0" for false value.
+ */
+ static const char* ToPsz10( bool b );
+
static sax_fastparser::FSHelperPtr WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int32 nValue );
static sax_fastparser::FSHelperPtr WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int64 nValue );
static sax_fastparser::FSHelperPtr WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, const char* sValue );
diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
index 3aa2a74..b24073f 100644
--- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
@@ -36,7 +36,7 @@ static OString lcl_GuidToOString( sal_uInt8 aGuid[ 16 ] )
{
char sBuf[ 40 ];
snprintf( sBuf, sizeof( sBuf ),
- "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
aGuid[ 0 ], aGuid[ 1 ], aGuid[ 2 ], aGuid[ 3 ], aGuid[ 4 ], aGuid[ 5 ], aGuid[ 6 ], aGuid[ 7 ],
aGuid[ 8 ], aGuid[ 9 ], aGuid[ 10 ], aGuid[ 11 ], aGuid[ 12 ], aGuid[ 13 ], aGuid[ 14 ], aGuid[ 15 ] );
return OString( sBuf );
@@ -365,6 +365,150 @@ void XclExpChTrHeader::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
pHeaders->write( ">" );
}
+void XclExpXmlChTrHeaders::SetGUID( const sal_uInt8* pGUID )
+{
+ memcpy(maGUID, pGUID, 16);
+}
+
+void XclExpXmlChTrHeaders::SaveXml( XclExpXmlStream& rStrm )
+{
+ sax_fastparser::FSHelperPtr pHeaders = rStrm.GetCurrentStream();
+
+ pHeaders->write("<")->writeId(XML_headers);
+
+ rStrm.WriteAttributes(
+ XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+ FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+ XML_guid, lcl_GuidToOString(maGUID).getStr(),
+ XML_lastGuid, NULL, // OOXTODO
+ XML_shared, NULL, // OOXTODO
+ XML_diskRevisions, NULL, // OOXTODO
+ XML_history, NULL, // OOXTODO
+ XML_trackRevisions, NULL, // OOXTODO
+ XML_exclusive, NULL, // OOXTODO
+ XML_revisionId, NULL, // OOXTODO
+ XML_version, NULL, // OOXTODO
+ XML_keepChangeHistory, NULL, // OOXTODO
+ XML_protected, NULL, // OOXTODO
+ XML_preserveHistory, NULL, // OOXTODO
+ FSEND);
+
+ pHeaders->write(">");
+}
+
+XclExpXmlChTrHeader::XclExpXmlChTrHeader(
+ const OUString& rUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
+ sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf ) :
+ maUserName(rUserName), maDateTime(rDateTime), mnLogNumber(nLogNumber),
+ mnMinAction(0), mnMaxAction(0)
+{
+ memcpy(maGUID, pGUID, 16);
+ if (rBuf.GetBufferCount())
+ {
+ maTabBuffer.resize(rBuf.GetBufferCount());
+ rBuf.GetBufferCopy(&maTabBuffer[0]);
+ }
+}
+
+void XclExpXmlChTrHeader::SaveXml( XclExpXmlStream& rStrm )
+{
+ sax_fastparser::FSHelperPtr pHeader = rStrm.GetCurrentStream();
+
+ pHeader->write("<")->writeId(XML_header);
+
+ OUString aRelId;
+ sax_fastparser::FSHelperPtr pRevLogStrm = rStrm.CreateOutputStream(
+ XclXmlUtils::GetStreamName("xl/revisions/", "revisionLog", mnLogNumber),
+ XclXmlUtils::GetStreamName(NULL, "revisionLog", mnLogNumber),
+ rStrm.GetCurrentStream()->getOutputStream(),
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
+ CREATE_OFFICEDOC_RELATION_TYPE("revisionLog"),
+ &aRelId);
+
+ rStrm.WriteAttributes(
+ XML_guid, lcl_GuidToOString(maGUID).getStr(),
+ XML_dateTime, lcl_DateTimeToOString(maDateTime).getStr(),
+ XML_userName, XclXmlUtils::ToOString(maUserName).getStr(),
+ FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
+ FSEND);
+
+ if (mnMinAction)
+ rStrm.WriteAttributes(XML_minRId, OString::number(mnMinAction).getStr(), FSEND);
+
+ if (mnMaxAction)
+ rStrm.WriteAttributes(XML_maxRId, OString::number(mnMaxAction).getStr(), FSEND);
+
+ if (!maTabBuffer.empty())
+ // next available sheet index.
+ rStrm.WriteAttributes(XML_maxSheetId, OString::number(maTabBuffer.back()+1).getStr(), FSEND);
+
+ pHeader->write(">");
+
+ if (!maTabBuffer.empty())
+ {
+ // Write sheet index map.
+ size_t n = maTabBuffer.size();
+ pHeader->startElement(
+ XML_sheetIdMap,
+ XML_count, OString::number(n).getStr(),
+ FSEND);
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ pHeader->singleElement(
+ XML_sheetId,
+ XML_val, OString::number(maTabBuffer[i]).getStr(),
+ FSEND);
+ }
+ pHeader->endElement(XML_sheetIdMap);
+ }
+
+ // Write all revision logs in a separate stream.
+
+ rStrm.PushStream(pRevLogStrm);
+
+ pRevLogStrm->write("<")->writeId(XML_revisions);
+
+ rStrm.WriteAttributes(
+ XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+ FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+ FSEND);
+
+ pRevLogStrm->write(">");
+
+ std::vector<XclExpChTrAction*>::iterator it = maActions.begin(), itEnd = maActions.end();
+ for (; it != itEnd; ++it)
+ {
+ XclExpChTrAction* p = *it;
+ p->SaveXml(rStrm);
+ }
+
+ pRevLogStrm->write("</")->writeId(XML_revisions)->write(">");
+
+ rStrm.PopStream();
+
+ pHeader->write("</")->writeId(XML_header)->write(">");
+}
+
+void XclExpXmlChTrHeader::AppendAction( XclExpChTrAction* pAction )
+{
+ sal_uInt32 nActionNum = pAction->GetActionNumber();
+ if (!mnMinAction || mnMinAction > nActionNum)
+ mnMinAction = nActionNum;
+
+ if (!mnMaxAction || mnMaxAction < nActionNum)
+ mnMaxAction = nActionNum;
+
+ maActions.push_back(pAction);
+}
+
+XclExpChTrInfo::XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime, const sal_uInt8* pGUID ) :
+ sUsername( rUsername ),
+ aDateTime( rDateTime )
+{
+ memcpy( aGUID, pGUID, 16 );
+}
+
XclExpChTrInfo::~XclExpChTrInfo()
{
}
@@ -393,33 +537,6 @@ sal_Size XclExpChTrInfo::GetLen() const
return 158;
}
-void XclExpChTrInfo::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
-{
- sax_fastparser::FSHelperPtr pHeader = rRevisionHeadersStrm.GetCurrentStream();
-
- OUString sRelationshipId;
- sax_fastparser::FSHelperPtr pRevisionLog = rRevisionHeadersStrm.CreateOutputStream(
- XclXmlUtils::GetStreamName( "xl/revisions/", "revisionLog", mnLogNumber ),
- XclXmlUtils::GetStreamName( NULL, "revisionLog", mnLogNumber ),
- rRevisionHeadersStrm.GetCurrentStream()->getOutputStream(),
- "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
- CREATE_OFFICEDOC_RELATION_TYPE("revisionLog"),
- &sRelationshipId );
-
- rRevisionHeadersStrm.WriteAttributes(
- XML_guid, lcl_GuidToOString( aGUID ).getStr(),
- XML_dateTime, lcl_DateTimeToOString( aDateTime ).getStr(),
- XML_maxSheetId, NULL, // OOXTODO
- XML_userName, XclXmlUtils::ToOString( sUsername ).getStr(),
- FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sRelationshipId ).getStr(),
- XML_minRId, NULL, // OOXTODO
- XML_maxRId, NULL, // OOXTODO
- FSEND );
- pHeader->write( ">" );
-
- rRevisionHeadersStrm.PushStream( pRevisionLog );
-}
-
XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) :
nBufSize( nCount ),
nLastId( nCount )
@@ -490,9 +607,8 @@ void XclExpChTrTabIdBuffer::Remove()
nLastId--;
}
-XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer, bool bInRevisionHeaders )
+XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer )
: nTabCount( rBuffer.GetBufferCount() )
- , mbInRevisionHeaders( bInRevisionHeaders )
{
pBuffer = new sal_uInt16[ nTabCount ];
rBuffer.GetBufferCopy( pBuffer );
@@ -532,29 +648,6 @@ sal_Size XclExpChTrTabId::GetLen() const
return nTabCount << 1;
}
-void XclExpChTrTabId::SaveXml( XclExpXmlStream& rRevisionLogStrm )
-{
- if( !mbInRevisionHeaders )
- return;
-
- sax_fastparser::FSHelperPtr pRevisionLog = rRevisionLogStrm.GetCurrentStream();
- rRevisionLogStrm.PopStream();
-
- sax_fastparser::FSHelperPtr pHeader = rRevisionLogStrm.GetCurrentStream();
- pHeader->startElement( XML_sheetIdMap,
- XML_count, OString::number( nTabCount ).getStr(),
- FSEND );
- for( int i = 0; i < nTabCount; ++i )
- {
- pHeader->singleElement( XML_sheetId,
- XML_val, OString::number( pBuffer[ i ] ).getStr(),
- FSEND );
- }
- pHeader->endElement( XML_sheetIdMap );
-
- rRevisionLogStrm.PushStream( pRevisionLog );
-}
-
// ! does not copy additional actions
XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) :
ExcRecord( rCopy ),
@@ -1093,11 +1186,12 @@ void XclExpChTrInsert::SaveXml( XclExpXmlStream& rRevisionLogStrm )
XML_ua, XclXmlUtils::ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
XML_ra, NULL, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
XML_sId, OString::number( GetTabId( aRange.aStart.Tab() ) ).getStr(),
- XML_eol, NULL, // OOXTODO: not supported?
+ XML_eol, XclXmlUtils::ToPsz10(mbEndOfList),
XML_ref, XclXmlUtils::ToOString( aRange ).getStr(),
XML_action, lcl_GetAction( nOpCode ),
XML_edge, NULL, // OOXTODO: ???
FSEND );
+
// OOXTODO: does this handle XML_rfmt, XML_undo?
XclExpChTrAction* pAction = GetAddAction();
while( pAction != NULL )
@@ -1279,14 +1373,6 @@ void XclExpChTr0x014A::SaveXml( XclExpXmlStream& rStrm )
pStream->endElement( XML_rfmt );
}
-class ExcXmlRecord : public ExcRecord
-{
-public:
- virtual sal_Size GetLen() const SAL_OVERRIDE;
- virtual sal_uInt16 GetNum() const SAL_OVERRIDE;
- virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
-};
-
sal_Size ExcXmlRecord::GetLen() const
{
return 0;
@@ -1406,54 +1492,79 @@ XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) :
}
// build record list
- pHeader = new XclExpChTrHeader;
- maRecList.push_back( new StartXmlElement( XML_headers, StartXmlElement::WRITE_NAMESPACES ) );
- maRecList.push_back( pHeader );
- maRecList.push_back( new XclExpChTr0x0195 );
- maRecList.push_back( new XclExpChTr0x0194( *pTempChangeTrack ) );
-
- OUString sLastUsername;
- DateTime aLastDateTime( DateTime::EMPTY );
- sal_uInt32 nIndex = 1;
- sal_Int32 nLogNumber = 1;
- while( !aActionStack.empty() )
+ if (GetOutput() == EXC_OUTPUT_BINARY)
{
- XclExpChTrAction* pAction = aActionStack.top();
- aActionStack.pop();
-
- if( (nIndex == 1) || pAction->ForceInfoRecord() ||
- (pAction->GetUsername() != sLastUsername) ||
- (pAction->GetDateTime() != aLastDateTime) )
+ pHeader = new XclExpChTrHeader;
+ maRecList.push_back( pHeader );
+ maRecList.push_back( new XclExpChTr0x0195 );
+ maRecList.push_back( new XclExpChTr0x0194( *pTempChangeTrack ) );
+
+ OUString sLastUsername;
+ DateTime aLastDateTime( DateTime::EMPTY );
+ sal_uInt32 nIndex = 1;
+ sal_Int32 nLogNumber = 1;
+ while( !aActionStack.empty() )
{
- if( nIndex != 1 )
+ XclExpChTrAction* pAction = aActionStack.top();
+ aActionStack.pop();
+
+ if( (nIndex == 1) || pAction->ForceInfoRecord() ||
+ (pAction->GetUsername() != sLastUsername) ||
+ (pAction->GetDateTime() != aLastDateTime) )
{
- maRecList.push_back( new EndXmlElement( XML_revisions ) );
- maRecList.push_back( new EndHeaderElement() );
+ lcl_GenerateGUID( aGUID, bValidGUID );
+ sLastUsername = pAction->GetUsername();
+ aLastDateTime = pAction->GetDateTime();
+
+ nLogNumber++;
+ maRecList.push_back( new XclExpChTrInfo(sLastUsername, aLastDateTime, aGUID) );
+ maRecList.push_back( new XclExpChTrTabId(pAction->GetTabIdBuffer()) );
+ pHeader->SetGUID( aGUID );
}
+ pAction->SetIndex( nIndex );
+ maRecList.push_back( pAction );
+ }
+
+ pHeader->SetGUID( aGUID );
+ pHeader->SetCount( nIndex - 1 );
+ maRecList.push_back( new ExcEof );
+ }
+ else
+ {
+ XclExpXmlChTrHeaders* pHeaders = new XclExpXmlChTrHeaders;
+ maRecList.push_back(pHeaders);
- lcl_GenerateGUID( aGUID, bValidGUID );
- sLastUsername = pAction->GetUsername();
- aLastDateTime = pAction->GetDateTime();
+ OUString sLastUsername;
+ DateTime aLastDateTime(DateTime::EMPTY);
+ sal_uInt32 nIndex = 1;
+ sal_Int32 nLogNumber = 1;
+ XclExpXmlChTrHeader* pCurHeader = NULL;
- maRecList.push_back( new StartXmlElement( XML_header, 0 ) );
- maRecList.push_back( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID, nLogNumber++ ) );
- maRecList.push_back( new XclExpChTrTabId( pAction->GetTabIdBuffer(), true ) );
- maRecList.push_back( new StartXmlElement( XML_revisions, StartXmlElement::WRITE_NAMESPACES | StartXmlElement::CLOSE_ELEMENT ) );
- pHeader->SetGUID( aGUID );
+ while (!aActionStack.empty())
+ {
+ XclExpChTrAction* pAction = aActionStack.top();
+ aActionStack.pop();
+
+ if( (nIndex == 1) || pAction->ForceInfoRecord() ||
+ (pAction->GetUsername() != sLastUsername) ||
+ (pAction->GetDateTime() != aLastDateTime) )
+ {
+ lcl_GenerateGUID( aGUID, bValidGUID );
+ sLastUsername = pAction->GetUsername();
+ aLastDateTime = pAction->GetDateTime();
+
+ pCurHeader = new XclExpXmlChTrHeader(sLastUsername, aLastDateTime, aGUID, nLogNumber, pAction->GetTabIdBuffer());
+ maRecList.push_back(pCurHeader);
+ nLogNumber++;
+ pHeaders->SetGUID(aGUID);
+ }
+ pAction->SetIndex(nIndex);
+ pCurHeader->AppendAction(pAction);
}
- pAction->SetIndex( nIndex );
- maRecList.push_back( pAction );
- }
- pHeader->SetGUID( aGUID );
- pHeader->SetCount( nIndex - 1 );
- if( nLogNumber > 1 )
- {
- maRecList.push_back( new EndXmlElement( XML_revisions ) );
- maRecList.push_back( new EndHeaderElement() );
+ pHeaders->SetGUID(aGUID);
+ maRecList.push_back(new EndXmlElement(XML_headers));
}
- maRecList.push_back( new EndXmlElement( XML_headers ) );
- maRecList.push_back( new ExcEof );
}
XclExpChangeTrack::~XclExpChangeTrack()
commit b92fdaa1a40bd54d279b4ac2faf19bf15468cc2f
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date: Wed Jul 16 19:59:35 2014 -0400
bnc#885548: Initial work on importing revisions from xlsx.
Change-Id: Ie0528490d024093cbabf38541fe70be96a9caa2e
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index d5ca533..f01e317 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -199,6 +199,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
sc/source/filter/oox/pivottablefragment \
sc/source/filter/oox/querytablebuffer \
sc/source/filter/oox/querytablefragment \
+ sc/source/filter/oox/revisionfragment \
sc/source/filter/oox/richstringcontext \
sc/source/filter/oox/richstring \
sc/source/filter/oox/scenariobuffer \
diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx
index f036f79..f898368 100644
--- a/sc/inc/chgtrack.hxx
+++ b/sc/inc/chgtrack.hxx
@@ -1099,7 +1099,7 @@ public:
sal_uLong nOldFormat, ScDocument* pRefDoc = NULL );
// after new value was set in the document,
// old value from pOldCell, format from Doc
- void AppendContent( const ScAddress& rPos, const ScCellValue& rOldCell );
+ SC_DLLPUBLIC void AppendContent( const ScAddress& rPos, const ScCellValue& rOldCell );
// after new values were set in the document,
// old values from RefDoc/UndoDoc.
// All contents with a cell in RefDoc
diff --git a/sc/source/filter/inc/revisionfragment.hxx b/sc/source/filter/inc/revisionfragment.hxx
new file mode 100644
index 0000000..473549e
--- /dev/null
+++ b/sc/source/filter/inc/revisionfragment.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SC_OOX_XLS_REVISIONFRAGMENT_HXX
+#define INCLUDED_SC_OOX_XLS_REVISIONFRAGMENT_HXX
+
+#include <excelhandlers.hxx>
+
+class ScChangeTrack;
+
+namespace oox { namespace xls {
+
+class RevisionHeadersFragment : public WorkbookFragmentBase
+{
+ struct Impl;
+ Impl* mpImpl;
+
+public:
+ explicit RevisionHeadersFragment(
+ const WorkbookHelper& rHelper, const OUString& rFragmentPath );
+
+ virtual ~RevisionHeadersFragment();
+
+protected:
+ virtual oox::core::ContextHandlerRef onCreateContext(
+ sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
+
+ virtual void onStartElement( const AttributeList& rAttribs ) SAL_OVERRIDE;
+ virtual void onCharacters( const OUString& rChars ) SAL_OVERRIDE;
+ virtual void onEndElement() SAL_OVERRIDE;
+
+ virtual void finalizeImport() SAL_OVERRIDE;
+
+private:
+ void importHeaders( const AttributeList& rAttribs );
+ void importHeader( const AttributeList& rAttribs );
+};
+
+class RevisionLogFragment : public WorkbookFragmentBase
+{
+ struct Impl;
+ Impl* mpImpl;
+
+public:
+ explicit RevisionLogFragment(
+ const WorkbookHelper& rHelper, const OUString& rFragmentPath, ScChangeTrack& rChangeTrack );
+
+ virtual ~RevisionLogFragment();
+
+protected:
+ virtual oox::core::ContextHandlerRef onCreateContext(
+ sal_Int32 nElement, const AttributeList& rAttribs ) SAL_OVERRIDE;
+
+ virtual void onStartElement( const AttributeList& rAttribs ) SAL_OVERRIDE;
+ virtual void onCharacters( const OUString& rChars ) SAL_OVERRIDE;
+ virtual void onEndElement() SAL_OVERRIDE;
+
+ virtual void finalizeImport() SAL_OVERRIDE;
+
+private:
+ void importCommon( const AttributeList& rAttribs );
+ void importRcc( const AttributeList& rAttribs );
+ void importRrc( const AttributeList& rAttribs );
+
+ void pushRevision();
+};
+
+}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/sc/source/filter/oox/revisionfragment.cxx b/sc/source/filter/oox/revisionfragment.cxx
new file mode 100644
index 0000000..dd8cc4b
--- /dev/null
+++ b/sc/source/filter/oox/revisionfragment.cxx
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <revisionfragment.hxx>
+#include <oox/core/relations.hxx>
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/core/fastparser.hxx>
+#include <o3tl/heap_ptr.hxx>
+#include <svl/sharedstringpool.hxx>
+#include <sax/tools/converter.hxx>
+#include <editeng/editobj.hxx>
+
+#include <chgtrack.hxx>
+#include <document.hxx>
+#include <compiler.hxx>
+#include <editutil.hxx>
+#include <formulacell.hxx>
+#include <chgviset.hxx>
+#include <richstringcontext.hxx>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <com/sun/star/util/DateTime.hpp>
+
+using namespace com::sun::star;
+
+namespace oox { namespace xls {
+
+namespace {
+
+enum RevisionType
+{
+ REV_UNKNOWN = 0,
+ REV_CELLCHANGE,
+ REV_INSERTROW,
+ REV_DELETEROW,
+ REV_INSERTCOL,
+ REV_DELETECOL
+};
+
+/**
+ * For nc (new cell) or oc (old cell) elements under rcc (cell content
+ * revision).
+ */
+class RCCCellValueContext : public WorkbookContextBase
+{
+ sal_Int32 mnSheetIndex;
+ ScAddress& mrPos;
+ ScCellValue& mrCellValue;
+ sal_Int32 mnType;
+
+ RichStringRef mxRichString;
+
+public:
+ RCCCellValueContext(
+ RevisionLogFragment& rParent, sal_Int32 nSheetIndex, ScAddress& rPos, ScCellValue& rCellValue ) :
+ WorkbookContextBase(rParent),
+ mnSheetIndex(nSheetIndex),
+ mrPos(rPos),
+ mrCellValue(rCellValue),
+ mnType(-1) {}
+
+protected:
+ virtual oox::core::ContextHandlerRef onCreateContext(
+ sal_Int32 nElement, const AttributeList& /*rAttribs*/ ) SAL_OVERRIDE
+ {
+ if (nElement == XLS_TOKEN(is))
+ {
+ mxRichString.reset(new RichString(*this));
+ return new RichStringContext(*this, mxRichString);
+ }
+
+ return this;
+ }
+
+ virtual void onStartElement( const AttributeList& rAttribs ) SAL_OVERRIDE
+ {
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(nc):
+ case XLS_TOKEN(oc):
+ importCell(rAttribs);
+ break;
+ default:
+ ;
+ }
+ }
+
+ virtual void onCharacters( const OUString& rChars ) SAL_OVERRIDE
+ {
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(v):
+ {
+ if (mnType == XML_n || mnType == XML_b)
+ mrCellValue.set(rChars.toDouble());
+ }
+ break;
+ case XLS_TOKEN(t):
+ {
+ if (mnType == XML_inlineStr)
+ {
+ ScDocument& rDoc = getScDocument();
+ svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
+ mrCellValue.set(rPool.intern(rChars));
+ }
+ }
+ break;
+ case XLS_TOKEN(f):
+ {
+ // formula string
+ ScDocument& rDoc = getScDocument();
+ ScCompiler aComp(&rDoc, mrPos);
+ aComp.SetGrammar(formula::FormulaGrammar::GRAM_OOXML);
+ ScTokenArray* pArray = aComp.CompileString(rChars);
+ if (!pArray)
+ break;
+
+ mrCellValue.set(new ScFormulaCell(&rDoc, mrPos, pArray));
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ virtual void onEndElement() SAL_OVERRIDE
+ {
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(nc):
+ case XLS_TOKEN(oc):
+ {
+ if (mrCellValue.isEmpty() && mxRichString)
+ {
+ // The value is a rich text string.
+ ScDocument& rDoc = getScDocument();
+ EditTextObject* pTextObj = mxRichString->convert(rDoc.GetEditEngine(), NULL);
+ if (pTextObj)
+ {
+ svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
+ pTextObj->NormalizeString(rPool);
+ mrCellValue.set(pTextObj);
+ }
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+private:
+ void importCell( const AttributeList& rAttribs )
+ {
+ mnType = rAttribs.getToken(XML_t, XML_n);
+ OUString aRefStr = rAttribs.getString(XML_r, OUString());
+ if (!aRefStr.isEmpty())
+ {
+ mrPos.Parse(aRefStr, NULL, formula::FormulaGrammar::CONV_XL_OOX);
+ if (mnSheetIndex != -1)
+ mrPos.SetTab(mnSheetIndex-1);
+ }
+ }
+};
+
+struct RevisionMetadata
+{
+ OUString maUserName;
+ DateTime maDateTime;
+
+ RevisionMetadata() : maDateTime(DateTime::EMPTY) {}
+ RevisionMetadata( const RevisionMetadata& r ) :
+ maUserName(r.maUserName), maDateTime(r.maDateTime) {}
+};
+
+}
+
+typedef std::map<OUString, RevisionMetadata> RevDataType;
+
+struct RevisionHeadersFragment::Impl
+{
+ RevDataType maRevData;
+
+ Impl() {}
+};
+
+RevisionHeadersFragment::RevisionHeadersFragment(
+ const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
+ WorkbookFragmentBase(rHelper, rFragmentPath),
+ mpImpl(new Impl) {}
+
+RevisionHeadersFragment::~RevisionHeadersFragment()
+{
+ delete mpImpl;
+}
+
+oox::core::ContextHandlerRef RevisionHeadersFragment::onCreateContext(
+ sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
+{
+ return this;
+}
+
+void RevisionHeadersFragment::onStartElement( const AttributeList& rAttribs )
+{
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(headers):
+ importHeaders(rAttribs);
+ break;
+ case XLS_TOKEN(header):
+ importHeader(rAttribs);
+ break;
+ case XLS_TOKEN(sheetIdMap):
+ break;
+ case XLS_TOKEN(sheetId):
+ break;
+ default:
+ ;
+ }
+}
+
+void RevisionHeadersFragment::onCharacters( const OUString& /*rChars*/ ) {}
+
+void RevisionHeadersFragment::onEndElement()
+{
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(headers):
+ break;
+ case XLS_TOKEN(header):
+ break;
+ case XLS_TOKEN(sheetIdMap):
+ break;
+ case XLS_TOKEN(sheetId):
+ break;
+ default:
+ ;
+ }
+}
+
+void RevisionHeadersFragment::finalizeImport()
+{
+ ScDocument& rDoc = getScDocument();
+ o3tl::heap_ptr<ScChangeTrack> pCT(new ScChangeTrack(&rDoc));
+ pCT->SetUseFixDateTime(true);
+
+ const oox::core::Relations& rRels = getRelations();
+ RevDataType::const_iterator it = mpImpl->maRevData.begin(), itEnd = mpImpl->maRevData.end();
+ for (; it != itEnd; ++it)
+ {
+ OUString aPath = rRels.getFragmentPathFromRelId(it->first);
+ if (aPath.isEmpty())
+ continue;
+
+ // Parse each reivison log fragment.
+ const RevisionMetadata& rData = it->second;
+ pCT->SetUser(rData.maUserName);
+ pCT->SetFixDateTimeLocal(rData.maDateTime);
+ boost::scoped_ptr<oox::core::FastParser> xParser(getOoxFilter().createParser());
+ rtl::Reference<oox::core::FragmentHandler> xFragment(new RevisionLogFragment(*this, aPath, *pCT));
+ importOoxFragment(xFragment, *xParser);
+ }
+
+ rDoc.SetChangeTrack(pCT.release());
+
+ // Turn on visibility of tracked changes.
+ ScChangeViewSettings aSettings;
+ aSettings.SetShowChanges(true);
+ rDoc.SetChangeViewSettings(aSettings);
+}
+
+void RevisionHeadersFragment::importHeaders( const AttributeList& /*rAttribs*/ )
+{
+ // Nothing for now.
+}
+
+void RevisionHeadersFragment::importHeader( const AttributeList& rAttribs )
+{
+ OUString aRId = rAttribs.getString(R_TOKEN(id), OUString());
+ if (aRId.isEmpty())
+ // All bets are off if we don't have a relation ID.
+ return;
+
+ RevisionMetadata aMetadata;
+ OUString aDateTimeStr = rAttribs.getString(XML_dateTime, OUString());
+ if (!aDateTimeStr.isEmpty())
+ {
+ util::DateTime aDateTime;
+ sax::Converter::parseDateTime(aDateTime, 0, aDateTimeStr);
+ Date aDate(aDateTime.Day, aDateTime.Month, aDateTime.Year);
+ Time aTime(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds, aDateTime.NanoSeconds);
+ aMetadata.maDateTime.SetDate(aDate.GetDate());
+ aMetadata.maDateTime.SetTime(aTime.GetTime());
+ }
+
+ aMetadata.maUserName = rAttribs.getString(XML_userName, OUString());
+
+ mpImpl->maRevData.insert(RevDataType::value_type(aRId, aMetadata));
+}
+
+struct RevisionLogFragment::Impl
+{
+ ScChangeTrack& mrChangeTrack;
+
+ sal_Int32 mnRevIndex;
+ sal_Int32 mnSheetIndex;
+
+ RevisionType meType;
+
+ // rcc
+ ScAddress maOldCellPos;
+ ScAddress maNewCellPos;
+ ScCellValue maOldCellValue;
+ ScCellValue maNewCellValue;
+
+ // rrc
+ ScRange maRange;
+
+ bool mbEndOfList;
+
+ Impl( ScChangeTrack& rChangeTrack ) :
+ mrChangeTrack(rChangeTrack),
+ mnRevIndex(-1),
+ mnSheetIndex(-1),
+ meType(REV_UNKNOWN),
+ mbEndOfList(false) {}
+};
+
+RevisionLogFragment::RevisionLogFragment(
+ const WorkbookHelper& rHelper, const OUString& rFragmentPath, ScChangeTrack& rChangeTrack ) :
+ WorkbookFragmentBase(rHelper, rFragmentPath),
+ mpImpl(new Impl(rChangeTrack)) {}
+
+RevisionLogFragment::~RevisionLogFragment()
+{
+ delete mpImpl;
+}
+
+oox::core::ContextHandlerRef RevisionLogFragment::onCreateContext(
+ sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
+{
+ switch (nElement)
+ {
+ case XLS_TOKEN(nc):
+ return new RCCCellValueContext(*this, mpImpl->mnSheetIndex, mpImpl->maNewCellPos, mpImpl->maNewCellValue);
+ case XLS_TOKEN(oc):
+ return new RCCCellValueContext(*this, mpImpl->mnSheetIndex, mpImpl->maOldCellPos, mpImpl->maOldCellValue);
+ default:
+ ;
+ }
+ return this;
+}
+
+void RevisionLogFragment::onStartElement( const AttributeList& rAttribs )
+{
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(rcc):
+ mpImpl->maNewCellPos.SetInvalid();
+ mpImpl->maOldCellPos.SetInvalid();
+ mpImpl->maNewCellValue.clear();
+ mpImpl->maOldCellValue.clear();
+ importRcc(rAttribs);
+ break;
+ case XLS_TOKEN(rrc):
+ importRrc(rAttribs);
+ break;
+ default:
+ ;
+ }
+}
+
+void RevisionLogFragment::onCharacters( const OUString& /*rChars*/ ) {}
+
+void RevisionLogFragment::onEndElement()
+{
+ switch (getCurrentElement())
+ {
+ case XLS_TOKEN(rcc):
+ case XLS_TOKEN(rrc):
+ pushRevision();
+ break;
+ default:
+ ;
+ }
+}
+
+void RevisionLogFragment::finalizeImport() {}
+
+void RevisionLogFragment::importCommon( const AttributeList& rAttribs )
+{
+ mpImpl->mnRevIndex = rAttribs.getInteger(XML_rId, -1);
+ mpImpl->mnSheetIndex = rAttribs.getInteger(XML_sId, -1);
+}
+
+void RevisionLogFragment::importRcc( const AttributeList& rAttribs )
+{
+ importCommon(rAttribs);
+
+ mpImpl->meType = REV_CELLCHANGE;
+}
+
+void RevisionLogFragment::importRrc( const AttributeList& rAttribs )
+{
+ importCommon(rAttribs);
+
+ if (mpImpl->mnSheetIndex == -1)
+ // invalid sheet index, or sheet index not given.
+ return;
+
+ mpImpl->meType = REV_UNKNOWN;
+ sal_Int32 nAction = rAttribs.getToken(XML_action, -1);
+ if (nAction == -1)
+ return;
+
+ OUString aRefStr = rAttribs.getString(XML_ref, OUString());
+ mpImpl->maRange.Parse(aRefStr, &getScDocument(), formula::FormulaGrammar::CONV_XL_OOX);
+ if (!mpImpl->maRange.IsValid())
+ return;
+
+ switch (nAction)
+ {
+ case XML_insertRow:
+ mpImpl->meType = REV_INSERTROW;
+ mpImpl->maRange.aEnd.SetCol(MAXCOL);
+ mpImpl->maRange.aStart.SetTab(mpImpl->mnSheetIndex-1);
+ mpImpl->maRange.aEnd.SetTab(mpImpl->mnSheetIndex-1);
+ break;
+ default:
+ // Unknown action type. Ignore it.
+ return;
+ }
+
+ mpImpl->mbEndOfList = rAttribs.getBool(XML_eol, false);
+}
+
+void RevisionLogFragment::pushRevision()
+{
+ switch (mpImpl->meType)
+ {
+ case REV_CELLCHANGE:
+ mpImpl->mrChangeTrack.AppendContentOnTheFly(
+ mpImpl->maNewCellPos, mpImpl->maOldCellValue, mpImpl->maNewCellValue);
+ break;
+ case REV_INSERTROW:
+ mpImpl->mrChangeTrack.AppendInsert(mpImpl->maRange, mpImpl->mbEndOfList);
+ break;
+ default:
+ ;
+ }
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index 088cebc..d7ffaab 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -36,6 +36,7 @@
#include "pivotcachebuffer.hxx"
#include "sharedstringsbuffer.hxx"
#include "sharedstringsfragment.hxx"
+#include "revisionfragment.hxx"
#include "stylesfragment.hxx"
#include "tablebuffer.hxx"
#include "themebuffer.hxx"
@@ -293,7 +294,7 @@ public:
}
};
-static void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVector& rSheets )
+void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVector& rSheets )
{
sal_Int32 nThreads = std::min( rSheets.size(), (size_t) 4 /* FIXME: ncpus/2 */ );
@@ -490,6 +491,14 @@ void WorkbookFragment::finalizeImport()
// final conversions, e.g. calculation settings and view settings
finalizeWorkbookImport();
+
+ OUString aRevHeadersPath = getFragmentPathFromFirstType(CREATE_OFFICEDOC_RELATION_TYPE("revisionHeaders"));
+ if (!aRevHeadersPath.isEmpty())
+ {
+ boost::scoped_ptr<oox::core::FastParser> xParser(getOoxFilter().createParser());
+ rtl::Reference<oox::core::FragmentHandler> xFragment(new RevisionHeadersFragment(*this, aRevHeadersPath));
+ importOoxFragment(xFragment, *xParser);
+ }
}
// private --------------------------------------------------------------------
More information about the Libreoffice-commits
mailing list