Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <sax/tools/converter.hxx>
31 : :
32 : : #include "SchXMLTableContext.hxx"
33 : : #include "SchXMLParagraphContext.hxx"
34 : : #include "SchXMLTextListContext.hxx"
35 : : #include "SchXMLImport.hxx"
36 : : #include "SchXMLTools.hxx"
37 : : #include "transporttypes.hxx"
38 : : #include "XMLStringBufferImportContext.hxx"
39 : : #include <rtl/math.hxx>
40 : : #include "xmloff/xmlnmspe.hxx"
41 : : #include <xmloff/xmltoken.hxx>
42 : : #include <xmloff/nmspmap.hxx>
43 : : #include <com/sun/star/frame/XModel.hpp>
44 : : #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
45 : : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
46 : : #include <com/sun/star/chart2/XChartDocument.hpp>
47 : : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
48 : : #include <com/sun/star/chart2/XInternalDataProvider.hpp>
49 : : #include <com/sun/star/chart/ChartSeriesAddress.hpp>
50 : : #include <com/sun/star/beans/XPropertySet.hpp>
51 : : #include <com/sun/star/beans/XPropertySetInfo.hpp>
52 : : #include <com/sun/star/beans/PropertyAttribute.hpp>
53 : :
54 : : #include <com/sun/star/chart2/XDiagram.hpp>
55 : : #include <com/sun/star/chart2/XAxis.hpp>
56 : : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
57 : : #include <com/sun/star/chart2/AxisType.hpp>
58 : :
59 : : #include <vector>
60 : : #include <algorithm>
61 : :
62 : : using namespace com::sun::star;
63 : : using namespace ::xmloff::token;
64 : : using ::com::sun::star::uno::Sequence;
65 : : using ::com::sun::star::uno::Reference;
66 : : using ::rtl::OUString;
67 : :
68 : : namespace
69 : : {
70 : :
71 : : const char aLabelPrefix[] = "label ";
72 : : const char aCategoriesRange[] = "categories";
73 : :
74 : : typedef ::std::multimap< ::rtl::OUString, ::rtl::OUString >
75 : : lcl_tOriginalRangeToInternalRangeMap;
76 : :
77 : : struct lcl_ApplyCellToData : public ::std::unary_function< SchXMLCell, void >
78 : : {
79 : 24 : lcl_ApplyCellToData( Sequence< double > & rOutData ) :
80 : : m_rData( rOutData ),
81 : : m_nIndex( 0 ),
82 : 24 : m_nSize( rOutData.getLength())
83 : : {
84 : 24 : ::rtl::math::setNan( &m_fNaN );
85 : 24 : }
86 : :
87 : 72 : void operator() ( const SchXMLCell & rCell )
88 : : {
89 [ + - ]: 72 : if( m_nIndex < m_nSize )
90 : : {
91 [ + - ]: 72 : if( rCell.eType == SCH_CELL_TYPE_FLOAT )
92 : 72 : m_rData[m_nIndex] = rCell.fValue;
93 : : else
94 : 0 : m_rData[m_nIndex] = m_fNaN;
95 : : }
96 : 72 : ++m_nIndex;
97 : 72 : }
98 : :
99 : 24 : sal_Int32 getCurrentIndex() const
100 : : {
101 : 24 : return m_nIndex;
102 : : }
103 : :
104 : : private:
105 : : Sequence< double > & m_rData;
106 : : sal_Int32 m_nIndex;
107 : : sal_Int32 m_nSize;
108 : : double m_fNaN;
109 : : };
110 : :
111 : 6 : void lcl_fillRangeMapping(
112 : : const SchXMLTable & rTable,
113 : : lcl_tOriginalRangeToInternalRangeMap & rOutRangeMap,
114 : : chart::ChartDataRowSource eDataRowSource )
115 : : {
116 [ + - ]: 6 : sal_Int32 nRowOffset = ( rTable.bHasHeaderRow ? 1 : 0 );
117 [ + - ]: 6 : sal_Int32 nColOffset = ( rTable.bHasHeaderColumn ? 1 : 0 );
118 : :
119 : 6 : const OUString lcl_aCategoriesRange(aCategoriesRange);
120 : 6 : const OUString lcl_aLabelPrefix(aLabelPrefix);
121 : :
122 : : // Fill range mapping
123 : 6 : const size_t nTableRowCount( rTable.aData.size());
124 [ + + ]: 36 : for( size_t nRow = 0; nRow < nTableRowCount; ++nRow )
125 : : {
126 : 30 : const ::std::vector< SchXMLCell > & rRow( rTable.aData[nRow] );
127 : 30 : const size_t nTableColCount( rRow.size());
128 [ + + ]: 150 : for( size_t nCol = 0; nCol < nTableColCount; ++nCol )
129 : : {
130 : 120 : const OUString aRangeId( rRow[nCol].aRangeId );
131 [ - + ]: 120 : if( !aRangeId.isEmpty())
132 : : {
133 [ # # ]: 0 : if( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
134 : : {
135 [ # # ][ # # ]: 0 : if( nCol == 0 && rTable.bHasHeaderColumn )
136 : : {
137 : : OSL_ASSERT( static_cast< sal_Int32 >( nRow ) == nRowOffset );
138 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
139 [ # # ]: 0 : aRangeId, lcl_aCategoriesRange ));
140 : : }
141 : : else
142 : : {
143 : 0 : OUString aColNumStr = OUString::valueOf( static_cast< sal_Int32 >( nCol - nColOffset ));
144 [ # # ][ # # ]: 0 : if( nRow == 0 && rTable.bHasHeaderRow )
145 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
146 [ # # ]: 0 : aRangeId, lcl_aLabelPrefix + aColNumStr ));
147 : : else
148 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
149 [ # # ]: 0 : aRangeId, aColNumStr ));
150 : : }
151 : : }
152 : : else // eDataRowSource == chart::ChartDataRowSource_ROWS
153 : : {
154 [ # # ][ # # ]: 0 : if( nRow == 0 && rTable.bHasHeaderRow )
155 : : {
156 : : OSL_ASSERT( static_cast< sal_Int32 >( nCol ) == nColOffset );
157 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
158 [ # # ]: 0 : aRangeId, lcl_aCategoriesRange ));
159 : : }
160 : : else
161 : : {
162 : 0 : OUString aRowNumStr = OUString::valueOf( static_cast< sal_Int32 >( nRow - nRowOffset ));
163 [ # # ][ # # ]: 0 : if( nCol == 0 && rTable.bHasHeaderColumn )
164 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
165 [ # # ]: 0 : aRangeId, lcl_aLabelPrefix + aRowNumStr ));
166 : : else
167 : : rOutRangeMap.insert( lcl_tOriginalRangeToInternalRangeMap::value_type(
168 [ # # ]: 0 : aRangeId, aRowNumStr ));
169 : : }
170 : : }
171 : : }
172 : 120 : }
173 : 6 : }
174 : 6 : }
175 : :
176 : : Reference< chart2::data::XDataSequence >
177 : 0 : lcl_reassignDataSequence(
178 : : const Reference< chart2::data::XDataSequence > & xSequence,
179 : : const Reference< chart2::data::XDataProvider > & xDataProvider,
180 : : lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
181 : : const OUString & rRange )
182 : : {
183 : 0 : Reference< chart2::data::XDataSequence > xResult( xSequence );
184 [ # # ]: 0 : lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
185 [ # # ]: 0 : if( aIt != rRangeMap.end())
186 : : {
187 : : // set sequence with correct data
188 [ # # ][ # # ]: 0 : xResult.set( xDataProvider->createDataSequenceByRangeRepresentation( aIt->second ));
[ # # ]
189 : : // remove translation, because it was used
190 [ # # ]: 0 : rRangeMap.erase( aIt );
191 : : }
192 : :
193 : 0 : return xResult;
194 : : }
195 : :
196 : 42 : bool lcl_mapContainsRange(
197 : : lcl_tOriginalRangeToInternalRangeMap & rRangeMap,
198 : : const OUString & rRange )
199 : : {
200 [ + - ]: 42 : lcl_tOriginalRangeToInternalRangeMap::iterator aIt( rRangeMap.find( rRange ));
201 : 42 : return ( aIt != rRangeMap.end());
202 : : }
203 : :
204 : 42 : bool lcl_tableOfRangeMatches(
205 : : const ::rtl::OUString & rRange,
206 : : const ::rtl::OUString & rTableName )
207 : : {
208 : : // both strings are non-empty and the table name is part of the range
209 : 42 : return ( !rRange.isEmpty() &&
210 : 42 : !rTableName.isEmpty() &&
211 [ + - ]: 84 : (rRange.indexOf( rTableName ) != -1 ));
[ + - + - ]
212 : : }
213 : :
214 : : template< typename T >
215 : 0 : ::std::vector< T > lcl_SequenceToVector( const uno::Sequence< T > & rSequence )
216 : : {
217 : 0 : ::std::vector< T > aResult( rSequence.getLength());
218 [ # # ]: 0 : ::std::copy( rSequence.getConstArray(), rSequence.getConstArray() + rSequence.getLength(),
219 : : aResult.begin());
220 : 0 : return aResult;
221 : : }
222 : :
223 : : } // anonymous namespace
224 : :
225 : :
226 : : // ----------------------------------------
227 : : // class SchXMLTableContext
228 : : // ----------------------------------------
229 : :
230 : 6 : SchXMLTableContext::SchXMLTableContext( SchXMLImportHelper& rImpHelper,
231 : : SvXMLImport& rImport,
232 : : const rtl::OUString& rLName,
233 : : SchXMLTable& aTable ) :
234 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLName ),
235 : : mrImportHelper( rImpHelper ),
236 : : mrTable( aTable ),
237 : : mbHasRowPermutation( false ),
238 [ + - ][ + - ]: 6 : mbHasColumnPermutation( false )
239 : : {
240 : 6 : mrTable.nColumnIndex = -1;
241 : 6 : mrTable.nMaxColumnIndex = -1;
242 : 6 : mrTable.nRowIndex = -1;
243 : 6 : mrTable.aData.clear();
244 : 6 : }
245 : :
246 [ + - ][ + - ]: 6 : SchXMLTableContext::~SchXMLTableContext()
247 : : {
248 [ - + ]: 12 : }
249 : :
250 : 24 : SvXMLImportContext *SchXMLTableContext::CreateChildContext(
251 : : sal_uInt16 nPrefix,
252 : : const rtl::OUString& rLocalName,
253 : : const uno::Reference< xml::sax::XAttributeList >& )
254 : : {
255 : 24 : SvXMLImportContext* pContext = 0;
256 : 24 : const SvXMLTokenMap& rTokenMap = mrImportHelper.GetTableElemTokenMap();
257 : :
258 [ + + - + : 24 : switch( rTokenMap.Get( nPrefix, rLocalName ))
+ - - ]
259 : : {
260 : : case XML_TOK_TABLE_HEADER_COLS:
261 : 6 : mrTable.bHasHeaderColumn = true;
262 : : // fall through intended
263 : : case XML_TOK_TABLE_COLUMNS:
264 [ + - ]: 12 : pContext = new SchXMLTableColumnsContext( GetImport(), rLocalName, mrTable );
265 : 12 : break;
266 : :
267 : : case XML_TOK_TABLE_COLUMN:
268 [ # # ]: 0 : pContext = new SchXMLTableColumnContext( GetImport(), rLocalName, mrTable );
269 : 0 : break;
270 : :
271 : : case XML_TOK_TABLE_HEADER_ROWS:
272 : 6 : mrTable.bHasHeaderRow = true;
273 : : // fall through intended
274 : : case XML_TOK_TABLE_ROWS:
275 [ + - ]: 12 : pContext = new SchXMLTableRowsContext( mrImportHelper, GetImport(), rLocalName, mrTable );
276 : 12 : break;
277 : :
278 : : case XML_TOK_TABLE_ROW:
279 [ # # ]: 0 : pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
280 : 0 : break;
281 : :
282 : : default:
283 [ # # ]: 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
284 : : }
285 : :
286 : 24 : return pContext;
287 : : }
288 : :
289 : 6 : void SchXMLTableContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
290 : : {
291 : : // get table-name
292 [ + - ]: 6 : sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
293 : :
294 [ + + ]: 12 : for( sal_Int16 i = 0; i < nAttrCount; i++ )
295 : : {
296 [ + - ][ + - ]: 6 : rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
297 : 6 : rtl::OUString aLocalName;
298 [ + - ]: 6 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
299 [ + - ]: 6 : if ( nPrefix == XML_NAMESPACE_TABLE )
300 : : {
301 [ + - ][ + - ]: 6 : if ( IsXMLToken( aLocalName, XML_NAME ) )
302 : : {
303 [ + - ][ + - ]: 6 : mrTable.aTableNameOfFile = xAttrList->getValueByIndex( i );
304 : : }
305 [ # # ][ # # ]: 0 : else if ( IsXMLToken( aLocalName, XML_PROTECTED ) )
306 : : {
307 [ # # ][ # # ]: 0 : if ( IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) )
[ # # ][ # # ]
308 : : {
309 : 0 : mrTable.bProtected = true;
310 : : }
311 : : }
312 : : }
313 : 6 : }
314 : 6 : }
315 : :
316 : 6 : void SchXMLTableContext::EndElement()
317 : : {
318 [ - + ]: 6 : if( mbHasColumnPermutation )
319 : : {
320 : : OSL_ASSERT( !mbHasRowPermutation );
321 [ # # ]: 0 : ::std::vector< sal_Int32 > aPermutation( lcl_SequenceToVector( maColumnPermutation ));
322 : : OSL_ASSERT( !aPermutation.empty());
323 [ # # ]: 0 : if( aPermutation.empty())
324 : : return;
325 : :
326 : : // permute the values of all rows according to aPermutation
327 [ # # ][ # # ]: 0 : for( ::std::vector< ::std::vector< SchXMLCell > >::iterator aRowIt( mrTable.aData.begin());
328 : 0 : aRowIt != mrTable.aData.end(); ++aRowIt )
329 : : {
330 : 0 : bool bModified = false;
331 [ # # ]: 0 : ::std::vector< SchXMLCell > aModifiedRow;
332 : 0 : const size_t nPermSize = aPermutation.size();
333 : : OSL_ASSERT( static_cast< sal_Int32 >( nPermSize ) - 1 == *(::std::max_element( aPermutation.begin(), aPermutation.end())));
334 : 0 : const size_t nRowSize = aRowIt->size();
335 [ # # ]: 0 : const size_t nDestSize = ::std::min( nPermSize, nRowSize );
336 [ # # ]: 0 : for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
337 : : {
338 [ # # ]: 0 : const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
339 [ # # ][ # # ]: 0 : if( nSourceIndex != nDestinationIndex &&
340 : : nSourceIndex < nRowSize )
341 : : {
342 : : // copy original on first real permutation
343 [ # # ]: 0 : if( !bModified )
344 : : {
345 : : OSL_ASSERT( aModifiedRow.empty());
346 [ # # ]: 0 : aModifiedRow.reserve( aRowIt->size());
347 [ # # ][ # # ]: 0 : ::std::copy( aRowIt->begin(), aRowIt->end(), ::std::back_inserter( aModifiedRow ));
348 : : OSL_ASSERT( !aModifiedRow.empty());
349 : : }
350 : : OSL_ASSERT( nDestinationIndex < aModifiedRow.size());
351 [ # # ]: 0 : aModifiedRow[ nDestinationIndex ] = (*aRowIt)[ nSourceIndex ];
352 : 0 : bModified = true;
353 : : }
354 : : }
355 : : // copy back
356 [ # # ]: 0 : if( bModified )
357 [ # # ]: 0 : ::std::copy( aModifiedRow.begin(), aModifiedRow.end(), aRowIt->begin());
358 [ # # ]: 0 : }
359 : : }
360 [ - + ]: 6 : else if( mbHasRowPermutation )
361 : : {
362 [ # # ]: 0 : ::std::vector< sal_Int32 > aPermutation( lcl_SequenceToVector( maRowPermutation ));
363 : : OSL_ASSERT( !aPermutation.empty());
364 [ # # ]: 0 : if( aPermutation.empty())
365 : : return;
366 : :
367 : 0 : bool bModified = false;
368 : 0 : const size_t nPermSize = aPermutation.size();
369 : : OSL_ASSERT( static_cast< sal_Int32 >( nPermSize ) - 1 == *(::std::max_element( aPermutation.begin(), aPermutation.end())));
370 : 0 : const size_t nTableRowCount = mrTable.aData.size();
371 [ # # ]: 0 : const size_t nDestSize = ::std::min( nPermSize, nTableRowCount );
372 [ # # ]: 0 : ::std::vector< ::std::vector< SchXMLCell > > aDestination;
373 [ # # ]: 0 : for( size_t nDestinationIndex = 0; nDestinationIndex < nDestSize; ++nDestinationIndex )
374 : : {
375 [ # # ]: 0 : const size_t nSourceIndex = static_cast< size_t >( aPermutation[ nDestinationIndex ] );
376 [ # # ][ # # ]: 0 : if( nSourceIndex != nDestinationIndex &&
377 : : nSourceIndex < nTableRowCount )
378 : : {
379 : : // copy original on first real permutation
380 [ # # ]: 0 : if( !bModified )
381 : : {
382 : : OSL_ASSERT( aDestination.empty());
383 [ # # ]: 0 : aDestination.reserve( mrTable.aData.size());
384 [ # # ][ # # ]: 0 : ::std::copy( mrTable.aData.begin(), mrTable.aData.end(), ::std::back_inserter( aDestination ));
385 : : OSL_ASSERT( !aDestination.empty());
386 : : }
387 : : OSL_ASSERT( nDestinationIndex < aDestination.size());
388 [ # # ]: 0 : aDestination[ nDestinationIndex ] = mrTable.aData[ nSourceIndex ];
389 : 0 : bModified = true;
390 : : }
391 : : }
392 [ # # ]: 0 : if( bModified )
393 : : {
394 : : // copy back
395 [ # # ]: 0 : ::std::copy( aDestination.begin(), aDestination.end(), mrTable.aData.begin());
396 [ # # ]: 6 : }
397 : : }
398 : : }
399 : :
400 : 0 : void SchXMLTableContext::setRowPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
401 : : {
402 : 0 : maRowPermutation = rPermutation;
403 : 0 : mbHasRowPermutation = ( rPermutation.getLength() > 0 );
404 : :
405 [ # # ][ # # ]: 0 : if( mbHasRowPermutation && mbHasColumnPermutation )
406 : : {
407 : 0 : mbHasColumnPermutation = false;
408 : 0 : maColumnPermutation.realloc( 0 );
409 : : }
410 : 0 : }
411 : :
412 : 0 : void SchXMLTableContext::setColumnPermutation( const uno::Sequence< sal_Int32 > & rPermutation )
413 : : {
414 : 0 : maColumnPermutation = rPermutation;
415 : 0 : mbHasColumnPermutation = ( rPermutation.getLength() > 0 );
416 : :
417 [ # # ][ # # ]: 0 : if( mbHasColumnPermutation && mbHasRowPermutation )
418 : : {
419 : 0 : mbHasRowPermutation = false;
420 : 0 : maRowPermutation.realloc( 0 );
421 : : }
422 : 0 : }
423 : :
424 : : // ========================================
425 : : // classes for columns
426 : : // ========================================
427 : :
428 : : // ----------------------------------------
429 : : // class SchXMLTableColumnsContext
430 : : // ----------------------------------------
431 : :
432 : 12 : SchXMLTableColumnsContext::SchXMLTableColumnsContext(
433 : : SvXMLImport& rImport,
434 : : const rtl::OUString& rLocalName,
435 : : SchXMLTable& aTable ) :
436 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
437 : 12 : mrTable( aTable )
438 : : {
439 : 12 : }
440 : :
441 : 12 : SchXMLTableColumnsContext::~SchXMLTableColumnsContext()
442 : : {
443 [ - + ]: 24 : }
444 : :
445 : 12 : SvXMLImportContext* SchXMLTableColumnsContext::CreateChildContext(
446 : : sal_uInt16 nPrefix,
447 : : const rtl::OUString& rLocalName,
448 : : const uno::Reference< xml::sax::XAttributeList >& )
449 : : {
450 : 12 : SvXMLImportContext* pContext = 0;
451 : :
452 [ + - + - ]: 24 : if( nPrefix == XML_NAMESPACE_TABLE &&
[ + - ]
453 : 12 : IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
454 : : {
455 [ + - ]: 12 : pContext = new SchXMLTableColumnContext( GetImport(), rLocalName, mrTable );
456 : : }
457 : : else
458 [ # # ]: 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
459 : :
460 : 12 : return pContext;
461 : : }
462 : :
463 : : // ----------------------------------------
464 : : // class SchXMLTableColumnContext
465 : : // ----------------------------------------
466 : :
467 : 12 : SchXMLTableColumnContext::SchXMLTableColumnContext(
468 : : SvXMLImport& rImport,
469 : : const rtl::OUString& rLocalName,
470 : : SchXMLTable& aTable ) :
471 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
472 : 12 : mrTable( aTable )
473 : : {
474 : 12 : }
475 : :
476 : 12 : void SchXMLTableColumnContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
477 : : {
478 : : // get number-columns-repeated attribute
479 [ + - ]: 12 : sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
480 : 12 : sal_Int32 nRepeated = 1;
481 : 12 : bool bHidden = false;
482 : :
483 [ + + ]: 18 : for( sal_Int16 i = 0; i < nAttrCount; i++ )
484 : : {
485 [ + - ][ + - ]: 6 : rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
486 : 6 : rtl::OUString aLocalName;
487 [ + - ]: 6 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
488 : :
489 [ + - ][ + - ]: 12 : if( nPrefix == XML_NAMESPACE_TABLE &&
[ + - ]
490 [ + - ]: 6 : IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
491 : : {
492 [ + - ][ + - ]: 6 : rtl::OUString aValue = xAttrList->getValueByIndex( i );
493 [ + - ]: 6 : if( !aValue.isEmpty())
494 : 6 : nRepeated = aValue.toInt32();
495 : : }
496 [ # # ][ # # ]: 0 : else if( nPrefix == XML_NAMESPACE_TABLE &&
[ # # ]
497 [ # # ]: 0 : IsXMLToken( aLocalName, XML_VISIBILITY ) )
498 : : {
499 [ # # ][ # # ]: 0 : rtl::OUString aVisibility = xAttrList->getValueByIndex( i );
500 [ # # ]: 0 : bHidden = aVisibility.equals( GetXMLToken( XML_COLLAPSE ) );
501 : : }
502 : 6 : }
503 : :
504 : 12 : sal_Int32 nOldCount = mrTable.nNumberOfColsEstimate;
505 : 12 : sal_Int32 nNewCount = nOldCount + nRepeated;
506 : 12 : mrTable.nNumberOfColsEstimate = nNewCount;
507 : :
508 [ - + ]: 12 : if( bHidden )
509 : : {
510 : : //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
511 [ # # ]: 0 : sal_Int32 nColOffset = ( mrTable.bHasHeaderColumn ? 1 : 0 );
512 [ # # ]: 0 : for( sal_Int32 nN = nOldCount; nN<nNewCount; nN++ )
513 : : {
514 : 0 : sal_Int32 nHiddenColumnIndex = nN-nColOffset;
515 [ # # ]: 0 : if( nHiddenColumnIndex>=0 )
516 [ # # ]: 0 : mrTable.aHiddenColumns.push_back(nHiddenColumnIndex);
517 : : }
518 : : }
519 : 12 : }
520 : :
521 : 12 : SchXMLTableColumnContext::~SchXMLTableColumnContext()
522 : : {
523 [ - + ]: 24 : }
524 : :
525 : : // ========================================
526 : : // classes for rows
527 : : // ========================================
528 : :
529 : : // ----------------------------------------
530 : : // class SchXMLTableRowsContext
531 : : // ----------------------------------------
532 : :
533 : 12 : SchXMLTableRowsContext::SchXMLTableRowsContext(
534 : : SchXMLImportHelper& rImpHelper,
535 : : SvXMLImport& rImport,
536 : : const rtl::OUString& rLocalName,
537 : : SchXMLTable& aTable ) :
538 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
539 : : mrImportHelper( rImpHelper ),
540 : 12 : mrTable( aTable )
541 : : {
542 : 12 : }
543 : :
544 : 12 : SchXMLTableRowsContext::~SchXMLTableRowsContext()
545 : : {
546 [ - + ]: 24 : }
547 : :
548 : 30 : SvXMLImportContext* SchXMLTableRowsContext::CreateChildContext(
549 : : sal_uInt16 nPrefix,
550 : : const rtl::OUString& rLocalName,
551 : : const uno::Reference< xml::sax::XAttributeList >& )
552 : : {
553 : 30 : SvXMLImportContext* pContext = 0;
554 : :
555 [ + - + - ]: 60 : if( nPrefix == XML_NAMESPACE_TABLE &&
[ + - ]
556 : 30 : IsXMLToken( rLocalName, XML_TABLE_ROW ) )
557 : : {
558 [ + - ]: 30 : pContext = new SchXMLTableRowContext( mrImportHelper, GetImport(), rLocalName, mrTable );
559 : : }
560 : : else
561 : : {
562 [ # # ]: 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
563 : : }
564 : :
565 : 30 : return pContext;
566 : : }
567 : :
568 : : // ----------------------------------------
569 : : // class SchXMLTableRowContext
570 : : // ----------------------------------------
571 : :
572 : 30 : SchXMLTableRowContext::SchXMLTableRowContext(
573 : : SchXMLImportHelper& rImpHelper,
574 : : SvXMLImport& rImport,
575 : : const rtl::OUString& rLocalName,
576 : : SchXMLTable& aTable ) :
577 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
578 : : mrImportHelper( rImpHelper ),
579 : 30 : mrTable( aTable )
580 : : {
581 : 30 : mrTable.nColumnIndex = -1;
582 : 30 : mrTable.nRowIndex++;
583 : :
584 [ + - ]: 30 : std::vector< SchXMLCell > aNewRow;
585 [ + - ]: 30 : aNewRow.reserve( mrTable.nNumberOfColsEstimate );
586 [ + + ]: 60 : while( mrTable.aData.size() <= (unsigned long)mrTable.nRowIndex )
587 [ + - ]: 60 : mrTable.aData.push_back( aNewRow );
588 : 30 : }
589 : :
590 : 30 : SchXMLTableRowContext::~SchXMLTableRowContext()
591 : : {
592 [ - + ]: 60 : }
593 : :
594 : 120 : SvXMLImportContext* SchXMLTableRowContext::CreateChildContext(
595 : : sal_uInt16 nPrefix,
596 : : const rtl::OUString& rLocalName,
597 : : const uno::Reference< xml::sax::XAttributeList >& )
598 : : {
599 : 120 : SvXMLImportContext* pContext = 0;
600 : :
601 : : // <table:table-cell> element
602 [ + - + - ]: 240 : if( nPrefix == XML_NAMESPACE_TABLE &&
[ + - ]
603 : 120 : IsXMLToken(rLocalName, XML_TABLE_CELL ) )
604 : : {
605 [ + - ]: 120 : pContext = new SchXMLTableCellContext( mrImportHelper, GetImport(), rLocalName, mrTable );
606 : : }
607 : : else
608 : : {
609 [ # # ]: 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
610 : : }
611 : :
612 : 120 : return pContext;
613 : : }
614 : :
615 : : //---------------------------------------------------------------------------------------------------
616 : : //---------------------------------------------------------------------------------------------------
617 : :
618 : : class SchXMLRangeSomewhereContext : public SvXMLImportContext
619 : : {
620 : : //#i113950# previously the range was exported to attribute text:id,
621 : : //but that attribute does not allow arbitrary strings anymore
622 : : //so we need to find an alternative to save that range info for copy/paste scenario ...
623 : : //-> use description at an empty group element for now
624 : :
625 : : private:
626 : : ::rtl::OUString& mrRangeString;
627 : : ::rtl::OUStringBuffer maRangeStringBuffer;
628 : :
629 : : public:
630 : : SchXMLRangeSomewhereContext( SvXMLImport& rImport,
631 : : sal_uInt16 nPrefix,
632 : : const ::rtl::OUString& rLocalName,
633 : : ::rtl::OUString& rRangeString );
634 : : virtual ~SchXMLRangeSomewhereContext();
635 : :
636 : : virtual SvXMLImportContext* CreateChildContext(
637 : : sal_uInt16 nPrefix,
638 : : const ::rtl::OUString& rLocalName,
639 : : const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList );
640 : : virtual void EndElement();
641 : : };
642 : :
643 : : //---------------------------------------------------------------------------------------------------
644 : : //---------------------------------------------------------------------------------------------------
645 : :
646 : : // ========================================
647 : : // classes for cells and their content
648 : : // ========================================
649 : :
650 : : // ----------------------------------------
651 : : // class SchXMLTableCellContext
652 : : // ----------------------------------------
653 : :
654 : 120 : SchXMLTableCellContext::SchXMLTableCellContext(
655 : : SchXMLImportHelper& rImpHelper,
656 : : SvXMLImport& rImport,
657 : : const rtl::OUString& rLocalName,
658 : : SchXMLTable& aTable ) :
659 : : SvXMLImportContext( rImport, XML_NAMESPACE_TABLE, rLocalName ),
660 : : mrImportHelper( rImpHelper ),
661 : 120 : mrTable( aTable )
662 : : {
663 : 120 : }
664 : :
665 : 120 : SchXMLTableCellContext::~SchXMLTableCellContext()
666 : : {
667 [ - + ]: 240 : }
668 : :
669 : 120 : void SchXMLTableCellContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
670 : : {
671 [ + - ][ + - ]: 120 : sal_Int16 nAttrCount = xAttrList.is()? xAttrList->getLength(): 0;
[ + - ]
672 : 120 : rtl::OUString aValue;
673 : 120 : rtl::OUString aLocalName;
674 : 120 : rtl::OUString aCellContent;
675 : 120 : SchXMLCellType eValueType = SCH_CELL_TYPE_UNKNOWN;
676 [ + - ]: 120 : const SvXMLTokenMap& rAttrTokenMap = mrImportHelper.GetCellAttrTokenMap();
677 : :
678 [ + + ]: 306 : for( sal_Int16 i = 0; i < nAttrCount; i++ )
679 : : {
680 [ + - ][ + - ]: 186 : rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
681 [ + - ]: 186 : sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
682 : :
683 [ + - ]: 186 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ))
[ + + - ]
684 : : {
685 : : case XML_TOK_CELL_VAL_TYPE:
686 [ + - ][ + - ]: 114 : aValue = xAttrList->getValueByIndex( i );
687 [ + + ][ + - ]: 114 : if( IsXMLToken( aValue, XML_FLOAT ) )
688 : 72 : eValueType = SCH_CELL_TYPE_FLOAT;
689 [ + - ][ + - ]: 42 : else if( IsXMLToken( aValue, XML_STRING ) )
690 : 42 : eValueType = SCH_CELL_TYPE_STRING;
691 : 114 : break;
692 : :
693 : : case XML_TOK_CELL_VALUE:
694 [ + - ][ + - ]: 72 : aCellContent = xAttrList->getValueByIndex( i );
695 : 72 : break;
696 : : }
697 : 186 : }
698 : :
699 : 120 : mbReadText = sal_True;
700 [ + - ]: 120 : SchXMLCell aCell;
701 : 120 : aCell.eType = eValueType;
702 : :
703 [ + + ]: 120 : if( eValueType == SCH_CELL_TYPE_FLOAT )
704 : : {
705 : : double fData;
706 : : // the result may be false if a NaN is read, but that's ok
707 [ + - ]: 72 : ::sax::Converter::convertDouble( fData, aCellContent );
708 : :
709 : 72 : aCell.fValue = fData;
710 : : // dont read text from following <text:p> or <text:list> element
711 : 72 : mbReadText = sal_False;
712 : : }
713 : :
714 [ + - ]: 120 : mrTable.aData[ mrTable.nRowIndex ].push_back( aCell );
715 : 120 : mrTable.nColumnIndex++;
716 [ + + ]: 120 : if( mrTable.nMaxColumnIndex < mrTable.nColumnIndex )
717 [ + - ]: 120 : mrTable.nMaxColumnIndex = mrTable.nColumnIndex;
718 : 120 : }
719 : :
720 : 114 : SvXMLImportContext* SchXMLTableCellContext::CreateChildContext(
721 : : sal_uInt16 nPrefix,
722 : : const rtl::OUString& rLocalName,
723 : : const uno::Reference< xml::sax::XAttributeList >& )
724 : : {
725 : 114 : SvXMLImportContext* pContext = 0;
726 : :
727 : : // <text:list> element
728 [ + - ][ - + ]: 114 : if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_LIST ) && mbReadText )
[ # # ][ - + ]
729 : : {
730 : 0 : SchXMLCell& rCell = mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ];
731 [ # # ]: 0 : rCell.aComplexString = Sequence< OUString >();
732 : 0 : rCell.eType = SCH_CELL_TYPE_COMPLEX_STRING;
733 [ # # ]: 0 : pContext = new SchXMLTextListContext( GetImport(), rLocalName, rCell.aComplexString );
734 : 0 : mbReadText = sal_False;//don't apply text from <text:p>
735 : : }
736 : : // <text:p> element - read text (and range from text:id old version)
737 [ + - ][ + - ]: 114 : else if( nPrefix == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_P ) )
[ + - ]
738 : : {
739 [ + - ]: 114 : pContext = new SchXMLParagraphContext( GetImport(), rLocalName, maCellContent, &maRangeId );
740 : : }
741 : : // <draw:g> element - read range
742 [ # # ][ # # ]: 0 : else if( nPrefix == XML_NAMESPACE_DRAW && IsXMLToken( rLocalName, XML_G ) )
[ # # ]
743 : : {
744 : : //#i113950# previously the range was exported to attribute text:id, but that attribute does not allow arbitrary strings anymore
745 : : //so we need to find an alternative to save that range info for copy/paste scenario ... -> use description at an empty group element for now
746 [ # # ]: 0 : pContext = new SchXMLRangeSomewhereContext( GetImport(), nPrefix, rLocalName, maRangeId );
747 : : }
748 : : else
749 : : {
750 [ # # ]: 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
751 : : }
752 : :
753 : 114 : return pContext;
754 : : }
755 : :
756 : 120 : void SchXMLTableCellContext::EndElement()
757 : : {
758 [ + + ][ + + ]: 120 : if( mbReadText && !maCellContent.isEmpty() ) //apply text from <text:p> element
[ + + ]
759 : 42 : mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aString = maCellContent;
760 [ - + ]: 120 : if( !maRangeId.isEmpty())
761 : 0 : mrTable.aData[ mrTable.nRowIndex ][ mrTable.nColumnIndex ].aRangeId = maRangeId;
762 : 120 : }
763 : :
764 : : // ========================================
765 : :
766 : 42 : void lcl_ApplyCellToComplexLabel( const SchXMLCell& rCell, Sequence< uno::Any >& rComplexLabel )
767 : : {
768 [ + - ]: 42 : if( rCell.eType == SCH_CELL_TYPE_STRING )
769 : : {
770 : 42 : rComplexLabel.realloc(1);
771 [ + - ]: 42 : rComplexLabel[0] = uno::makeAny( rCell.aString );
772 : : }
773 [ # # ][ # # ]: 0 : else if( rCell.aComplexString.getLength() && rCell.eType == SCH_CELL_TYPE_COMPLEX_STRING )
[ # # ]
774 : : {
775 : 0 : sal_Int32 nCount = rCell.aComplexString.getLength();
776 : 0 : rComplexLabel.realloc( nCount );
777 [ # # ]: 0 : for( sal_Int32 nN=0; nN<nCount; nN++)
778 [ # # ]: 0 : rComplexLabel[nN] = uno::makeAny((rCell.aComplexString)[nN]);
779 : : }
780 [ # # ]: 0 : else if( rCell.eType == SCH_CELL_TYPE_FLOAT )
781 : : {
782 : 0 : rComplexLabel.realloc(1);
783 [ # # ]: 0 : rComplexLabel[0] = uno::makeAny( rCell.fValue );
784 : : }
785 : 42 : }
786 : :
787 : 6 : void SchXMLTableHelper::applyTableToInternalDataProvider(
788 : : const SchXMLTable& rTable,
789 : : uno::Reference< chart2::XChartDocument > xChartDoc )
790 : : {
791 : : // apply all data read from the local table to the internal data provider
792 [ + - ][ + - ]: 6 : if( !xChartDoc.is() || !xChartDoc->hasInternalDataProvider() )
[ + - ][ - + ]
[ + - ]
793 : : return;
794 [ + - ][ + - ]: 6 : Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider() );
795 [ - + ]: 6 : if( !xDataProv.is() )
796 : : return;
797 : :
798 : : //prepare the read local table data
799 : 6 : sal_Int32 nNumRows( static_cast< sal_Int32 >( rTable.aData.size()));
800 : 6 : sal_Int32 nRowOffset = 0;
801 [ + - ]: 6 : if( rTable.bHasHeaderRow )
802 : : {
803 : 6 : --nNumRows;
804 : 6 : nRowOffset = 1;
805 : : }
806 : 6 : sal_Int32 nNumColumns( rTable.nMaxColumnIndex + 1 );
807 : 6 : sal_Int32 nColOffset = 0;
808 [ + - ]: 6 : if( rTable.bHasHeaderColumn )
809 : : {
810 : 6 : --nNumColumns;
811 : 6 : nColOffset = 1;
812 : : }
813 : :
814 [ + - ]: 6 : Sequence< Sequence< double > > aDataInRows( nNumRows );
815 [ + - ]: 6 : Sequence< Sequence< uno::Any > > aComplexRowDescriptions( nNumRows );
816 [ + - ]: 6 : Sequence< Sequence< uno::Any > > aComplexColumnDescriptions( nNumColumns );
817 [ + + ]: 30 : for( sal_Int32 i=0; i<nNumRows; ++i )
818 [ + - ][ + - ]: 24 : aDataInRows[i].realloc( nNumColumns );
819 : :
820 [ + - ][ + - ]: 6 : if( rTable.aData.begin() != rTable.aData.end())
821 : : {
822 : : //apply column labels
823 [ + - ]: 6 : if( rTable.bHasHeaderRow )
824 : : {
825 [ + - ]: 6 : const ::std::vector< SchXMLCell >& rFirstRow = rTable.aData.front();
826 : 6 : const sal_Int32 nColumnLabelsSize = aComplexColumnDescriptions.getLength();
827 [ + - ]: 6 : const sal_Int32 nMax = ::std::min< sal_Int32 >( nColumnLabelsSize, static_cast< sal_Int32 >( rFirstRow.size()) - nColOffset );
828 : : OSL_ASSERT( nMax == nColumnLabelsSize );
829 [ + + ]: 24 : for( sal_Int32 i=0; i<nMax; ++i )
830 [ + - ][ + - ]: 18 : lcl_ApplyCellToComplexLabel( rFirstRow[i+nColOffset], aComplexColumnDescriptions[i] );
831 : : }
832 : :
833 [ + - ]: 6 : std::vector< ::std::vector< SchXMLCell > >::const_iterator aRowIter( rTable.aData.begin() + nRowOffset );
834 : 6 : std::vector< ::std::vector< SchXMLCell > >::const_iterator aEnd( rTable.aData.end() );
835 [ + - ][ + + ]: 30 : for( sal_Int32 nRow = 0; aRowIter != aEnd && nRow < nNumRows; ++aRowIter, ++nRow )
[ + - ][ + + ]
836 : : {
837 : 24 : const ::std::vector< SchXMLCell >& rRow = *aRowIter;
838 [ + - ]: 24 : if( !rRow.empty() )
839 : : {
840 : : // row label
841 [ + - ]: 24 : if( rTable.bHasHeaderColumn )
842 [ + - ][ + - ]: 24 : lcl_ApplyCellToComplexLabel( rRow.front(), aComplexRowDescriptions[nRow] );
[ + - ]
843 : :
844 : : // values
845 [ + - ]: 24 : Sequence< double >& rTargetRow = aDataInRows[nRow];
846 [ + - ][ + - ]: 24 : lcl_ApplyCellToData aApplyCellToData = ::std::for_each( rRow.begin() + nColOffset, rRow.end(), lcl_ApplyCellToData( rTargetRow ) );
[ + - ]
847 : 24 : double fNaN = 0.0;
848 : 24 : ::rtl::math::setNan( &fNaN );
849 [ - + ]: 24 : for( sal_Int32 nCurrentIndex = aApplyCellToData.getCurrentIndex(); nCurrentIndex<nNumColumns; nCurrentIndex++ )
850 [ # # ]: 0 : rTargetRow[nCurrentIndex] = fNaN;//#i110615#
851 : : }
852 : : }
853 : : }
854 : :
855 : : //apply the collected data to the chart
856 [ + - ]: 6 : Reference< chart2::XAnyDescriptionAccess > xDataAccess( xDataProv, uno::UNO_QUERY );
857 [ - + ]: 6 : if( !xDataAccess.is() )
858 : : return;
859 : :
860 [ + - ][ + - ]: 6 : xDataAccess->setData( aDataInRows );
861 [ + - ]: 6 : if( rTable.bHasHeaderColumn )
862 [ + - ][ + - ]: 6 : xDataAccess->setAnyRowDescriptions( aComplexRowDescriptions );
863 [ + - ]: 6 : if( rTable.bHasHeaderRow )
864 [ + - ][ + - ]: 6 : xDataAccess->setAnyColumnDescriptions( aComplexColumnDescriptions );
865 : :
866 [ - + ]: 6 : if ( rTable.bProtected )
867 : : {
868 : : try
869 : : {
870 [ # # ]: 0 : Reference< beans::XPropertySet > xProps( xChartDoc, uno::UNO_QUERY_THROW );
871 [ # # ][ # # ]: 0 : xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableDataTableDialog" ) ), uno::makeAny( sal_True ) );
[ # # ][ # # ]
872 [ # # ][ # # ]: 6 : xProps->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableComplexChartTypes" ) ), uno::makeAny( sal_True ) );
[ # # ][ # # ]
[ # # ]
873 : : }
874 [ # # ]: 0 : catch ( uno::Exception& )
875 : : {
876 : : }
877 [ - + ][ + - ]: 6 : }
[ - + ][ + - ]
[ - + ][ + - ]
[ - + ][ + - ]
878 : : }
879 : :
880 : 6 : void SchXMLTableHelper::switchRangesFromOuterToInternalIfNecessary(
881 : : const SchXMLTable& rTable,
882 : : const tSchXMLLSequencesPerIndex & rLSequencesPerIndex,
883 : : uno::Reference< chart2::XChartDocument > xChartDoc,
884 : : chart::ChartDataRowSource eDataRowSource )
885 : : {
886 [ + - ][ + - ]: 6 : if( ! (xChartDoc.is() && xChartDoc->hasInternalDataProvider()))
[ + - ][ - + ]
[ + - ]
887 : 6 : return;
888 : :
889 : : // If the range-strings are valid (starting with "local-table") they should
890 : : // be interpreted like given, otherwise (when the ranges refer to Calc- or
891 : : // Writer-ranges, but the container is not available like when pasting a
892 : : // chart from Calc to Impress) the range is ignored, and every object gets
893 : : // one table column in the order of appearance, which is: 1. categories,
894 : : // 2. data series: 2.a) domains, 2.b) values (main-role, usually y-values)
895 : :
896 [ + - ][ + - ]: 6 : Reference< chart2::data::XDataProvider > xDataProv( xChartDoc->getDataProvider());
897 : :
898 : : // create a mapping from original ranges to new ranges
899 [ + - ]: 6 : lcl_tOriginalRangeToInternalRangeMap aRangeMap;
900 : :
901 [ + - ]: 6 : lcl_fillRangeMapping( rTable, aRangeMap, eDataRowSource );
902 : :
903 : 6 : const OUString lcl_aCategoriesRange(aCategoriesRange);
904 : :
905 : 6 : bool bCategoriesApplied = false;
906 : : // translate ranges (using the map created before)
907 [ + + ]: 96 : for( tSchXMLLSequencesPerIndex::const_iterator aLSeqIt( rLSequencesPerIndex.begin());
908 : 48 : aLSeqIt != rLSequencesPerIndex.end(); ++aLSeqIt )
909 : : {
910 [ + - ]: 42 : if( aLSeqIt->second.is())
911 : : {
912 : : // values/error bars/categories
913 [ + + - + ]: 60 : if( aLSeqIt->first.second == SCH_XML_PART_VALUES ||
[ + + ]
914 : 18 : aLSeqIt->first.second == SCH_XML_PART_ERROR_BARS )
915 : : {
916 [ + - ][ + - ]: 24 : Reference< chart2::data::XDataSequence > xSeq( aLSeqIt->second->getValues());
917 : 24 : OUString aRange;
918 [ + - ][ - + ]: 72 : if( xSeq.is() &&
[ - + ][ + - ]
919 [ + - ]: 24 : SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
920 [ + - ]: 24 : lcl_mapContainsRange( aRangeMap, aRange ))
921 : : {
922 : : Reference< chart2::data::XDataSequence > xNewSeq(
923 [ # # ]: 0 : lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
924 [ # # ][ # # ]: 0 : if( xNewSeq != xSeq )
925 : : {
926 : : SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
927 [ # # ][ # # ]: 0 : Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
[ # # ]
928 [ # # ][ # # ]: 0 : aLSeqIt->second->setValues( xNewSeq );
929 : 0 : }
930 : : }
931 : : else
932 : : {
933 [ + - ]: 24 : if( lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
934 : : {
935 [ + + ]: 24 : if( aLSeqIt->first.first == SCH_XML_CATEGORIES_INDEX )
936 : 6 : bCategoriesApplied = true;
937 : : }
938 : : else
939 : : {
940 [ # # ]: 0 : if( aLSeqIt->first.first == SCH_XML_CATEGORIES_INDEX )
941 : : {
942 [ # # ][ # # ]: 0 : Reference< beans::XPropertySet > xOldSequenceProp( aLSeqIt->second->getValues(), uno::UNO_QUERY );
[ # # ]
943 : : Reference< chart2::data::XDataSequence > xNewSequence(
944 [ # # ]: 0 : xDataProv->createDataSequenceByRangeRepresentation(
945 [ # # ][ # # ]: 0 : OUString(RTL_CONSTASCII_USTRINGPARAM("categories"))));
946 : : SchXMLTools::copyProperties(
947 [ # # ][ # # ]: 0 : xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
948 [ # # ][ # # ]: 0 : aLSeqIt->second->setValues( xNewSequence );
949 : 0 : bCategoriesApplied = true;
950 : : }
951 : : else
952 : : {
953 [ # # ][ # # ]: 0 : Reference< beans::XPropertySet > xOldSequenceProp( aLSeqIt->second->getValues(), uno::UNO_QUERY );
[ # # ]
954 : 0 : OUString aRep( OUString::valueOf( aLSeqIt->first.first ));
955 : : Reference< chart2::data::XDataSequence > xNewSequence(
956 [ # # ][ # # ]: 0 : xDataProv->createDataSequenceByRangeRepresentation( aRep ));
957 : : SchXMLTools::copyProperties(
958 [ # # ][ # # ]: 0 : xOldSequenceProp, Reference< beans::XPropertySet >( xNewSequence, uno::UNO_QUERY ));
959 [ # # ][ # # ]: 0 : aLSeqIt->second->setValues( xNewSequence );
960 : : }
961 : : }
962 : 24 : }
963 : : }
964 : : else // labels
965 : : {
966 : : OSL_ASSERT( aLSeqIt->first.second == SCH_XML_PART_LABEL );
967 : : // labels
968 [ + - ][ + - ]: 18 : Reference< chart2::data::XDataSequence > xSeq( aLSeqIt->second->getLabel());
969 : 18 : OUString aRange;
970 [ + - ][ - + ]: 54 : if( xSeq.is() &&
[ - + ][ + - ]
971 [ + - ]: 18 : SchXMLTools::getXMLRangePropertyFromDataSequence( xSeq, aRange, /* bClearProp = */ true ) &&
972 [ + - ]: 18 : lcl_mapContainsRange( aRangeMap, aRange ))
973 : : {
974 : : Reference< chart2::data::XDataSequence > xNewSeq(
975 [ # # ]: 0 : lcl_reassignDataSequence( xSeq, xDataProv, aRangeMap, aRange ));
976 [ # # ][ # # ]: 0 : if( xNewSeq != xSeq )
977 : : {
978 : : SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
979 [ # # ][ # # ]: 0 : Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
[ # # ]
980 [ # # ][ # # ]: 0 : aLSeqIt->second->setLabel( xNewSeq );
981 : 0 : }
982 : : }
983 [ - + ]: 18 : else if( ! lcl_tableOfRangeMatches( aRange, rTable.aTableNameOfFile ))
984 : : {
985 [ # # ]: 0 : OUString aRep( RTL_CONSTASCII_USTRINGPARAM("label "));
986 : 0 : aRep += OUString::valueOf( aLSeqIt->first.first );
987 : :
988 : : Reference< chart2::data::XDataSequence > xNewSeq(
989 [ # # ][ # # ]: 0 : xDataProv->createDataSequenceByRangeRepresentation( aRep ));
990 : : SchXMLTools::copyProperties( Reference< beans::XPropertySet >( xSeq, uno::UNO_QUERY ),
991 [ # # ][ # # ]: 0 : Reference< beans::XPropertySet >( xNewSeq, uno::UNO_QUERY ));
[ # # ]
992 [ # # ][ # # ]: 0 : aLSeqIt->second->setLabel( xNewSeq );
993 : 18 : }
994 : : }
995 : : }
996 : : }
997 : :
998 : : // there exist files with own data without a categories element but with row
999 : : // descriptions. The row descriptions were used as categories even without
1000 : : // the categories element
1001 [ - + ]: 6 : if( ! bCategoriesApplied )
1002 : : {
1003 : : SchXMLTools::CreateCategories(
1004 : : xDataProv, xChartDoc, OUString(RTL_CONSTASCII_USTRINGPARAM("categories")),
1005 [ # # ][ # # ]: 0 : 0 /* nCooSysIndex */, 0 /* nDimension */ );
1006 : : }
1007 : :
1008 : : //i91578 display of hidden values (copy paste scenario; use hidden flag during migration to locale table upon paste )
1009 : : //remove series that consist only of hidden columns
1010 [ + - ]: 6 : Reference< chart2::XInternalDataProvider > xInternalDataProvider( xDataProv, uno::UNO_QUERY );
1011 [ + - ][ - + ]: 6 : if( xInternalDataProvider.is() && !rTable.aHiddenColumns.empty() )
[ - + ]
1012 : : {
1013 : : try
1014 : : {
1015 [ # # ][ # # ]: 0 : Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xChartDoc->getFirstDiagram(), uno::UNO_QUERY_THROW );
[ # # ]
1016 [ # # ][ # # ]: 0 : Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1017 [ # # ]: 0 : for( sal_Int32 nC=0; nC<aCooSysSeq.getLength(); ++nC )
1018 : : {
1019 [ # # ][ # # ]: 0 : Reference< chart2::XChartTypeContainer > xCooSysContainer( aCooSysSeq[nC], uno::UNO_QUERY_THROW );
1020 [ # # ][ # # ]: 0 : Sequence< Reference< chart2::XChartType > > aChartTypeSeq( xCooSysContainer->getChartTypes());
1021 [ # # ]: 0 : for( sal_Int32 nT=0; nT<aChartTypeSeq.getLength(); ++nT )
1022 : : {
1023 [ # # ][ # # ]: 0 : Reference< chart2::XDataSeriesContainer > xSeriesContainer( aChartTypeSeq[nT], uno::UNO_QUERY );
1024 [ # # ]: 0 : if(!xSeriesContainer.is())
1025 : 0 : continue;
1026 [ # # ][ # # ]: 0 : Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xSeriesContainer->getDataSeries() );
1027 [ # # ]: 0 : std::vector< Reference< chart2::XDataSeries > > aRemainingSeries;
1028 : :
1029 [ # # ]: 0 : for( sal_Int32 nS = 0; nS < aSeriesSeq.getLength(); nS++ )
1030 : : {
1031 [ # # ][ # # ]: 0 : Reference< chart2::data::XDataSource > xDataSource( aSeriesSeq[nS], uno::UNO_QUERY );
1032 [ # # ]: 0 : if( xDataSource.is() )
1033 : : {
1034 : 0 : bool bHasUnhiddenColumns = false;
1035 : 0 : rtl::OUString aRange;
1036 [ # # ][ # # ]: 0 : uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences() );
1037 [ # # ]: 0 : for( sal_Int32 nN=0; nN< aSequences.getLength(); ++nN )
1038 : : {
1039 [ # # ]: 0 : Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aSequences[nN] );
1040 [ # # ]: 0 : if(!xLabeledSequence.is())
1041 : 0 : continue;
1042 [ # # ][ # # ]: 0 : Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1043 [ # # ]: 0 : if( xValues.is() )
1044 : : {
1045 [ # # ][ # # ]: 0 : aRange = xValues->getSourceRangeRepresentation();
1046 [ # # ][ # # ]: 0 : if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aRange.toInt32() ) == rTable.aHiddenColumns.end() )
[ # # ]
1047 : 0 : bHasUnhiddenColumns = true;
1048 : : }
1049 [ # # ]: 0 : if( !bHasUnhiddenColumns )
1050 : : {
1051 [ # # ][ # # ]: 0 : Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1052 [ # # ]: 0 : if( xLabel.is() )
1053 : : {
1054 [ # # ][ # # ]: 0 : aRange = xLabel->getSourceRangeRepresentation();
1055 : 0 : sal_Int32 nSearchIndex = 0;
1056 : 0 : OUString aSecondToken = aRange.getToken( 1, ' ', nSearchIndex );
1057 [ # # ][ # # ]: 0 : if( ::std::find( rTable.aHiddenColumns.begin(), rTable.aHiddenColumns.end(), aSecondToken.toInt32() ) == rTable.aHiddenColumns.end() )
[ # # ]
1058 : 0 : bHasUnhiddenColumns = true;
1059 : 0 : }
1060 : : }
1061 [ # # ]: 0 : }
1062 [ # # ]: 0 : if( bHasUnhiddenColumns )
1063 [ # # ][ # # ]: 0 : aRemainingSeries.push_back( aSeriesSeq[nS] );
[ # # ]
1064 : : }
1065 : 0 : }
1066 : :
1067 [ # # ]: 0 : if( static_cast<sal_Int32>(aRemainingSeries.size()) != aSeriesSeq.getLength() )
1068 : : {
1069 : : //remove the series that have only hidden data
1070 [ # # ]: 0 : Sequence< Reference< chart2::XDataSeries > > aRemainingSeriesSeq( aRemainingSeries.size());
1071 [ # # ][ # # ]: 0 : ::std::copy( aRemainingSeries.begin(), aRemainingSeries.end(), aRemainingSeriesSeq.getArray());
1072 [ # # ][ # # ]: 0 : xSeriesContainer->setDataSeries( aRemainingSeriesSeq );
1073 : :
1074 : : //remove unused sequences
1075 [ # # ]: 0 : Reference< chart2::data::XDataSource > xDataSource( xChartDoc, uno::UNO_QUERY );
1076 [ # # ]: 0 : if( xDataSource.is() )
1077 : : {
1078 : : //first detect which collumns are really used
1079 [ # # ]: 0 : std::map< sal_Int32, bool > aUsageMap;
1080 : 0 : rtl::OUString aRange;
1081 [ # # ][ # # ]: 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aUsedSequences( xDataSource->getDataSequences() );
1082 [ # # ]: 0 : for( sal_Int32 nN=0; nN< aUsedSequences.getLength(); ++nN )
1083 : : {
1084 [ # # ]: 0 : Reference< chart2::data::XLabeledDataSequence > xLabeledSequence( aUsedSequences[nN] );
1085 [ # # ]: 0 : if(!xLabeledSequence.is())
1086 : 0 : continue;
1087 [ # # ][ # # ]: 0 : Reference< chart2::data::XDataSequence > xValues( xLabeledSequence->getValues() );
1088 [ # # ]: 0 : if( xValues.is() )
1089 : : {
1090 [ # # ][ # # ]: 0 : aRange = xValues->getSourceRangeRepresentation();
1091 : 0 : sal_Int32 nIndex = aRange.toInt32();
1092 [ # # ][ # # ]: 0 : if( nIndex!=0 || !aRange.equals(lcl_aCategoriesRange) )
[ # # ]
1093 [ # # ]: 0 : aUsageMap[nIndex] = true;
1094 : : }
1095 [ # # ][ # # ]: 0 : Reference< chart2::data::XDataSequence > xLabel( xLabeledSequence->getLabel() );
1096 [ # # ]: 0 : if( xLabel.is() )
1097 : : {
1098 [ # # ][ # # ]: 0 : aRange = xLabel->getSourceRangeRepresentation();
1099 : 0 : sal_Int32 nSearchIndex = 0;
1100 : 0 : OUString aSecondToken = aRange.getToken( 1, ' ', nSearchIndex );
1101 [ # # ]: 0 : if( !aSecondToken.isEmpty() )
1102 [ # # ]: 0 : aUsageMap[aSecondToken.toInt32()] = true;
1103 : : }
1104 [ # # ]: 0 : }
1105 : :
1106 [ # # ]: 0 : ::std::vector< sal_Int32 > aSequenceIndexesToDelete;
1107 [ # # # # ]: 0 : for( ::std::vector< sal_Int32 >::const_iterator aIt(
[ # # ]
1108 : 0 : rTable.aHiddenColumns.begin()); aIt != rTable.aHiddenColumns.end(); ++aIt )
1109 : : {
1110 [ # # ]: 0 : sal_Int32 nSequenceIndex = *aIt;
1111 [ # # ][ # # ]: 0 : if( aUsageMap.find(nSequenceIndex) != aUsageMap.end() )
[ # # ]
1112 : 0 : continue;
1113 [ # # ]: 0 : aSequenceIndexesToDelete.push_back(nSequenceIndex);
1114 : : }
1115 : :
1116 : : // delete unnecessary sequences of the internal data
1117 : : // iterate using greatest index first, so that deletion does not
1118 : : // shift other sequences that will be deleted later
1119 [ # # ]: 0 : ::std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
1120 [ # # # # ]: 0 : for( ::std::vector< sal_Int32 >::reverse_iterator aIt(
[ # # ]
1121 : 0 : aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
1122 : : {
1123 [ # # ][ # # ]: 0 : if( *aIt != -1 )
1124 [ # # ][ # # ]: 0 : xInternalDataProvider->deleteSequence( *aIt );
[ # # ]
1125 [ # # ]: 0 : }
1126 [ # # ]: 0 : }
1127 : : }
1128 [ # # ][ # # ]: 0 : }
1129 [ # # ][ # # ]: 0 : }
[ # # ]
1130 : : }
1131 [ # # ]: 0 : catch( const uno::Exception & )
1132 : : {
1133 : : }
1134 : 6 : }
1135 : : }
1136 : :
1137 : : //---------------------------------------------------------------------------------------------------
1138 : :
1139 : 0 : SchXMLRangeSomewhereContext::SchXMLRangeSomewhereContext( SvXMLImport& rImport,
1140 : : sal_uInt16 nPrefix,
1141 : : const OUString& rLocalName,
1142 : : OUString& rRangeString ) :
1143 : : SvXMLImportContext( rImport, nPrefix, rLocalName ),
1144 : 0 : mrRangeString( rRangeString )
1145 : : {
1146 : 0 : }
1147 : :
1148 : 0 : SchXMLRangeSomewhereContext::~SchXMLRangeSomewhereContext()
1149 : : {
1150 [ # # ]: 0 : }
1151 : :
1152 : 0 : SvXMLImportContext* SchXMLRangeSomewhereContext::CreateChildContext(
1153 : : sal_uInt16 nPrefix,
1154 : : const OUString& rLocalName,
1155 : : const uno::Reference< xml::sax::XAttributeList >& )
1156 : : {
1157 [ # # ][ # # ]: 0 : if( XML_NAMESPACE_SVG == nPrefix && IsXMLToken( rLocalName, XML_DESC ) )
[ # # ]
1158 : : {
1159 : : return new XMLStringBufferImportContext(
1160 [ # # ]: 0 : GetImport(), nPrefix, rLocalName, maRangeStringBuffer );
1161 : : }
1162 [ # # ]: 0 : return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1163 : : }
1164 : :
1165 : 0 : void SchXMLRangeSomewhereContext::EndElement()
1166 : : {
1167 : 0 : mrRangeString = maRangeStringBuffer.makeStringAndClear();
1168 : 0 : }
1169 : :
1170 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|