fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / oox / revisionfragment.cxx
blobe4ca60819958ff6f65e3ef479c5584884de9ecf8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
12 #include <memory>
14 #include <revisionfragment.hxx>
15 #include <oox/core/relations.hxx>
16 #include <oox/core/xmlfilterbase.hxx>
17 #include <oox/core/fastparser.hxx>
18 #include <svl/sharedstringpool.hxx>
19 #include <sax/tools/converter.hxx>
20 #include <editeng/editobj.hxx>
22 #include <chgtrack.hxx>
23 #include <document.hxx>
24 #include <compiler.hxx>
25 #include <editutil.hxx>
26 #include <formulacell.hxx>
27 #include <chgviset.hxx>
28 #include <richstringcontext.hxx>
30 #include <boost/scoped_ptr.hpp>
32 #include <com/sun/star/util/DateTime.hpp>
34 using namespace com::sun::star;
36 namespace oox { namespace xls {
38 namespace {
40 enum RevisionType
42 REV_UNKNOWN = 0,
43 REV_CELLCHANGE,
44 REV_INSERTROW,
45 REV_DELETEROW,
46 REV_INSERTCOL,
47 REV_DELETECOL
50 /**
51 * For nc (new cell) or oc (old cell) elements under rcc (cell content
52 * revision).
54 class RCCCellValueContext : public WorkbookContextBase
56 sal_Int32 mnSheetIndex;
57 ScAddress& mrPos;
58 ScCellValue& mrCellValue;
59 sal_Int32 mnType;
61 RichStringRef mxRichString;
63 public:
64 RCCCellValueContext(
65 RevisionLogFragment& rParent, sal_Int32 nSheetIndex, ScAddress& rPos, ScCellValue& rCellValue ) :
66 WorkbookContextBase(rParent),
67 mnSheetIndex(nSheetIndex),
68 mrPos(rPos),
69 mrCellValue(rCellValue),
70 mnType(-1) {}
72 protected:
73 virtual oox::core::ContextHandlerRef onCreateContext(
74 sal_Int32 nElement, const AttributeList& /*rAttribs*/ ) SAL_OVERRIDE
76 if (nElement == XLS_TOKEN(is))
78 mxRichString.reset(new RichString(*this));
79 return new RichStringContext(*this, mxRichString);
82 return this;
85 virtual void onStartElement( const AttributeList& rAttribs ) SAL_OVERRIDE
87 switch (getCurrentElement())
89 case XLS_TOKEN(nc):
90 case XLS_TOKEN(oc):
91 importCell(rAttribs);
92 break;
93 default:
98 virtual void onCharacters( const OUString& rChars ) SAL_OVERRIDE
100 switch (getCurrentElement())
102 case XLS_TOKEN(v):
104 if (mnType == XML_n || mnType == XML_b)
105 mrCellValue.set(rChars.toDouble());
107 break;
108 case XLS_TOKEN(t):
110 if (mnType == XML_inlineStr)
112 ScDocument& rDoc = getScDocument();
113 svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
114 mrCellValue.set(rPool.intern(rChars));
117 break;
118 case XLS_TOKEN(f):
120 // formula string
121 ScDocument& rDoc = getScDocument();
122 ScCompiler aComp(&rDoc, mrPos);
123 aComp.SetGrammar(formula::FormulaGrammar::GRAM_OOXML);
124 ScTokenArray* pArray = aComp.CompileString(rChars);
125 if (!pArray)
126 break;
128 mrCellValue.set(new ScFormulaCell(&rDoc, mrPos, pArray));
130 break;
131 default:
136 virtual void onEndElement() SAL_OVERRIDE
138 switch (getCurrentElement())
140 case XLS_TOKEN(nc):
141 case XLS_TOKEN(oc):
143 if (mrCellValue.isEmpty() && mxRichString)
145 // The value is a rich text string.
146 ScDocument& rDoc = getScDocument();
147 EditTextObject* pTextObj = mxRichString->convert(rDoc.GetEditEngine(), NULL);
148 if (pTextObj)
150 svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
151 pTextObj->NormalizeString(rPool);
152 mrCellValue.set(pTextObj);
156 break;
157 default:
162 private:
163 void importCell( const AttributeList& rAttribs )
165 mnType = rAttribs.getToken(XML_t, XML_n);
166 OUString aRefStr = rAttribs.getString(XML_r, OUString());
167 if (!aRefStr.isEmpty())
169 mrPos.Parse(aRefStr, NULL, formula::FormulaGrammar::CONV_XL_OOX);
170 if (mnSheetIndex != -1)
171 mrPos.SetTab(mnSheetIndex-1);
176 struct RevisionMetadata
178 OUString maUserName;
179 DateTime maDateTime;
181 RevisionMetadata() : maDateTime(DateTime::EMPTY) {}
182 RevisionMetadata( const RevisionMetadata& r ) :
183 maUserName(r.maUserName), maDateTime(r.maDateTime) {}
188 typedef std::map<OUString, RevisionMetadata> RevDataType;
190 struct RevisionHeadersFragment::Impl
192 RevDataType maRevData;
194 Impl() {}
197 RevisionHeadersFragment::RevisionHeadersFragment(
198 const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
199 WorkbookFragmentBase(rHelper, rFragmentPath),
200 mpImpl(new Impl) {}
202 RevisionHeadersFragment::~RevisionHeadersFragment()
204 delete mpImpl;
207 oox::core::ContextHandlerRef RevisionHeadersFragment::onCreateContext(
208 sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
210 return this;
213 void RevisionHeadersFragment::onStartElement( const AttributeList& rAttribs )
215 switch (getCurrentElement())
217 case XLS_TOKEN(headers):
218 break;
219 case XLS_TOKEN(header):
220 importHeader(rAttribs);
221 break;
222 case XLS_TOKEN(sheetIdMap):
223 break;
224 case XLS_TOKEN(sheetId):
225 break;
226 default:
231 void RevisionHeadersFragment::onCharacters( const OUString& /*rChars*/ ) {}
233 void RevisionHeadersFragment::onEndElement()
235 switch (getCurrentElement())
237 case XLS_TOKEN(headers):
238 break;
239 case XLS_TOKEN(header):
240 break;
241 case XLS_TOKEN(sheetIdMap):
242 break;
243 case XLS_TOKEN(sheetId):
244 break;
245 default:
250 void RevisionHeadersFragment::finalizeImport()
252 ScDocument& rDoc = getScDocument();
253 std::unique_ptr<ScChangeTrack> pCT(new ScChangeTrack(&rDoc));
254 OUString aSelfUser = pCT->GetUser(); // owner of this document.
255 pCT->SetUseFixDateTime(true);
257 const oox::core::Relations& rRels = getRelations();
258 RevDataType::const_iterator it = mpImpl->maRevData.begin(), itEnd = mpImpl->maRevData.end();
259 for (; it != itEnd; ++it)
261 OUString aPath = rRels.getFragmentPathFromRelId(it->first);
262 if (aPath.isEmpty())
263 continue;
265 // Parse each reivison log fragment.
266 const RevisionMetadata& rData = it->second;
267 pCT->SetUser(rData.maUserName);
268 pCT->SetFixDateTimeLocal(rData.maDateTime);
269 boost::scoped_ptr<oox::core::FastParser> xParser(getOoxFilter().createParser());
270 rtl::Reference<oox::core::FragmentHandler> xFragment(new RevisionLogFragment(*this, aPath, *pCT));
271 importOoxFragment(xFragment, *xParser);
274 pCT->SetUser(aSelfUser); // set the default user to the document owner.
275 pCT->SetUseFixDateTime(false);
276 rDoc.SetChangeTrack(pCT.release());
278 // Turn on visibility of tracked changes.
279 ScChangeViewSettings aSettings;
280 aSettings.SetShowChanges(true);
281 rDoc.SetChangeViewSettings(aSettings);
284 void RevisionHeadersFragment::importHeader( const AttributeList& rAttribs )
286 OUString aRId = rAttribs.getString(R_TOKEN(id), OUString());
287 if (aRId.isEmpty())
288 // All bets are off if we don't have a relation ID.
289 return;
291 RevisionMetadata aMetadata;
292 OUString aDateTimeStr = rAttribs.getString(XML_dateTime, OUString());
293 if (!aDateTimeStr.isEmpty())
295 util::DateTime aDateTime;
296 sax::Converter::parseDateTime(aDateTime, 0, aDateTimeStr);
297 Date aDate(aDateTime);
298 tools::Time aTime(aDateTime);
299 aMetadata.maDateTime.SetDate(aDate.GetDate());
300 aMetadata.maDateTime.SetTime(aTime.GetTime());
303 aMetadata.maUserName = rAttribs.getString(XML_userName, OUString());
305 mpImpl->maRevData.insert(RevDataType::value_type(aRId, aMetadata));
308 struct RevisionLogFragment::Impl
310 ScChangeTrack& mrChangeTrack;
312 sal_Int32 mnRevIndex;
313 sal_Int32 mnSheetIndex;
315 RevisionType meType;
317 // rcc
318 ScAddress maOldCellPos;
319 ScAddress maNewCellPos;
320 ScCellValue maOldCellValue;
321 ScCellValue maNewCellValue;
323 // rrc
324 ScRange maRange;
326 bool mbEndOfList;
328 Impl( ScChangeTrack& rChangeTrack ) :
329 mrChangeTrack(rChangeTrack),
330 mnRevIndex(-1),
331 mnSheetIndex(-1),
332 meType(REV_UNKNOWN),
333 mbEndOfList(false) {}
336 RevisionLogFragment::RevisionLogFragment(
337 const WorkbookHelper& rHelper, const OUString& rFragmentPath, ScChangeTrack& rChangeTrack ) :
338 WorkbookFragmentBase(rHelper, rFragmentPath),
339 mpImpl(new Impl(rChangeTrack)) {}
341 RevisionLogFragment::~RevisionLogFragment()
343 delete mpImpl;
346 oox::core::ContextHandlerRef RevisionLogFragment::onCreateContext(
347 sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
349 switch (nElement)
351 case XLS_TOKEN(nc):
352 return new RCCCellValueContext(*this, mpImpl->mnSheetIndex, mpImpl->maNewCellPos, mpImpl->maNewCellValue);
353 case XLS_TOKEN(oc):
354 return new RCCCellValueContext(*this, mpImpl->mnSheetIndex, mpImpl->maOldCellPos, mpImpl->maOldCellValue);
355 default:
358 return this;
361 void RevisionLogFragment::onStartElement( const AttributeList& rAttribs )
363 switch (getCurrentElement())
365 case XLS_TOKEN(rcc):
366 mpImpl->maNewCellPos.SetInvalid();
367 mpImpl->maOldCellPos.SetInvalid();
368 mpImpl->maNewCellValue.clear();
369 mpImpl->maOldCellValue.clear();
370 importRcc(rAttribs);
371 break;
372 case XLS_TOKEN(rrc):
373 importRrc(rAttribs);
374 break;
375 default:
380 void RevisionLogFragment::onCharacters( const OUString& /*rChars*/ ) {}
382 void RevisionLogFragment::onEndElement()
384 switch (getCurrentElement())
386 case XLS_TOKEN(rcc):
387 case XLS_TOKEN(rrc):
388 pushRevision();
389 break;
390 default:
395 void RevisionLogFragment::finalizeImport() {}
397 void RevisionLogFragment::importCommon( const AttributeList& rAttribs )
399 mpImpl->mnRevIndex = rAttribs.getInteger(XML_rId, -1);
400 mpImpl->mnSheetIndex = rAttribs.getInteger(XML_sId, -1);
403 void RevisionLogFragment::importRcc( const AttributeList& rAttribs )
405 importCommon(rAttribs);
407 mpImpl->meType = REV_CELLCHANGE;
410 void RevisionLogFragment::importRrc( const AttributeList& rAttribs )
412 importCommon(rAttribs);
414 if (mpImpl->mnSheetIndex == -1)
415 // invalid sheet index, or sheet index not given.
416 return;
418 mpImpl->meType = REV_UNKNOWN;
419 sal_Int32 nAction = rAttribs.getToken(XML_action, -1);
420 if (nAction == -1)
421 return;
423 OUString aRefStr = rAttribs.getString(XML_ref, OUString());
424 mpImpl->maRange.Parse(aRefStr, &getScDocument(), formula::FormulaGrammar::CONV_XL_OOX);
425 if (!mpImpl->maRange.IsValid())
426 return;
428 switch (nAction)
430 case XML_insertRow:
431 mpImpl->meType = REV_INSERTROW;
432 mpImpl->maRange.aEnd.SetCol(MAXCOL);
433 mpImpl->maRange.aStart.SetTab(mpImpl->mnSheetIndex-1);
434 mpImpl->maRange.aEnd.SetTab(mpImpl->mnSheetIndex-1);
435 break;
436 default:
437 // Unknown action type. Ignore it.
438 return;
441 mpImpl->mbEndOfList = rAttribs.getBool(XML_eol, false);
444 void RevisionLogFragment::pushRevision()
446 switch (mpImpl->meType)
448 case REV_CELLCHANGE:
449 mpImpl->mrChangeTrack.AppendContentOnTheFly(
450 mpImpl->maNewCellPos, mpImpl->maOldCellValue, mpImpl->maNewCellValue);
451 break;
452 case REV_INSERTROW:
453 mpImpl->mrChangeTrack.AppendInsert(mpImpl->maRange, mpImpl->mbEndOfList);
454 break;
455 default:
462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */