LibreOffice Module xmloff (master)  1
XMLTableImport.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
24 #include <com/sun/star/table/XTableRows.hpp>
25 #include <com/sun/star/table/XMergeableCell.hpp>
26 #include <com/sun/star/table/XMergeableCellRange.hpp>
27 #include <com/sun/star/table/XTable.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
32 #include <com/sun/star/style/XStyle.hpp>
33 #include <comphelper/sequence.hxx>
34 #include <tools/diagnose_ex.h>
35 
37 #include <xmloff/xmlprmap.hxx>
38 #include <xmloff/txtimp.hxx>
39 #include <xmloff/xmlimp.hxx>
40 #include <xmloff/namespacemap.hxx>
41 #include <xmloff/xmlstyle.hxx>
42 #include <xmloff/prstylei.hxx>
43 
44 #include <xmloff/xmlnamespace.hxx>
45 #include <xmloff/xmluconv.hxx>
46 #include "table.hxx"
47 
48 #include <osl/diagnose.h>
49 #include <sal/log.hxx>
50 
51 #include <memory>
52 
53 using namespace ::xmloff::token;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::table;
57 using namespace ::com::sun::star::xml::sax;
58 using namespace ::com::sun::star::text;
59 using namespace ::com::sun::star::style;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::container;
62 
63 namespace {
64 
65 struct ColumnInfo
66 {
67  OUString msStyleName;
68  OUString msDefaultCellStyleName;
69 };
70 
71 class XMLProxyContext : public SvXMLImportContext
72 {
73 public:
74  XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent, sal_uInt16 nPrfx, const OUString& rLName );
75 
76  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList ) override;
77 
78 private:
80 };
81 
82 struct MergeInfo
83 {
84  sal_Int32 mnStartColumn;
85  sal_Int32 mnStartRow;
86  sal_Int32 mnEndColumn;
87  sal_Int32 mnEndRow;
88 
89  MergeInfo( sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nColumnSpan, sal_Int32 nRowSpan )
90  : mnStartColumn( nStartColumn ), mnStartRow( nStartRow ), mnEndColumn( nStartColumn + nColumnSpan - 1 ), mnEndRow( nStartRow + nRowSpan - 1 ) {};
91 };
92 
93 }
94 
95 typedef std::vector< std::shared_ptr< MergeInfo > > MergeInfoVector;
96 
98 {
99 public:
100  XMLTableImportContext( const rtl::Reference< XMLTableImport >& xThis, sal_uInt16 nPrfx, const OUString& rLName, Reference< XColumnRowRange > const & xColumnRowRange );
101 
102  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList ) override;
103 
104  virtual void StartElement( const Reference< XAttributeList >& xAttrList ) override;
105 
106  virtual void EndElement() override;
107 
108  void InitColumns();
109 
110  SvXMLImportContextRef ImportColumn( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList );
111  SvXMLImportContext * ImportRow( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList );
112  SvXMLImportContextRef ImportCell( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList );
113 
114  OUString GetDefaultCellStyleName() const;
115 
116  css::uno::Reference< css::table::XTable > mxTable;
117  Reference< XTableColumns > mxColumns;
118  Reference< XTableRows > mxRows;
119 
120  std::vector< std::shared_ptr< ColumnInfo > > maColumnInfos;
121  sal_Int32 mnCurrentRow;
122  sal_Int32 mnCurrentColumn;
123 
124  // default cell style name for the current row
126 
128 };
129 
130 namespace {
131 
132 class XMLCellImportContext : public SvXMLImportContext
133 {
134 public:
135  XMLCellImportContext( SvXMLImport& rImport,
136  const Reference< XMergeableCell >& xCell,
137  const OUString& sDefaultCellStyleName,
138  sal_uInt16 nPrfx, const OUString& rLName,
139  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList );
140 
141  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList ) override;
142 
143  virtual void EndElement() override;
144 
145  sal_Int32 getColumnSpan() const { return mnColSpan; }
146  sal_Int32 getRowSpan() const { return mnRowSpan; }
147  sal_Int32 getRepeated() const { return mnRepeated; }
148 
149  Reference< XMergeableCell > mxCell;
150  Reference< XTextCursor > mxCursor;
151  Reference< XTextCursor > mxOldCursor;
152  bool mbListContextPushed;
153 
154  sal_Int32 mnColSpan, mnRowSpan, mnRepeated;
155 };
156 
157 class XMLTableTemplateContext : public SvXMLStyleContext
158 {
159 public:
160  XMLTableTemplateContext( SvXMLImport& rImport );
161 
162  // Create child element.
163  virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
164  sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
165 
166  virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
167 
168  virtual void CreateAndInsert( bool bOverwrite ) override;
169 protected:
170  virtual void SetAttribute( sal_uInt16 nPrefixKey,
171  const OUString& rLocalName,
172  const OUString& rValue ) override;
173 private:
174  XMLTableTemplate maTableTemplate;
175  OUString msTemplateStyleName;
176 };
177 
178 }
179 
180 
181 XMLProxyContext::XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent, sal_uInt16 nPrfx, const OUString& rLName )
182 : SvXMLImportContext( rImport, nPrfx, rLName )
183 , mxParent( xParent )
184 {
185 }
186 
187 SvXMLImportContextRef XMLProxyContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
188 {
189  if( mxParent.is() )
190  return mxParent->CreateChildContext( nPrefix, rLocalName, xAttrList );
191  return nullptr;
192 }
193 
194 
196 : mrImport( rImport )
197 {
198  bool bWriter = false;
199  // check if called by Writer
200  Reference<XMultiServiceFactory> xFac(rImport.GetModel(), UNO_QUERY);
201  if (xFac.is()) try
202  {
203  Sequence<OUString> sSNS = xFac->getAvailableServiceNames();
204  bWriter = comphelper::findValue(sSNS, "com.sun.star.style.TableStyle") != -1;
205  }
206  catch(const Exception&)
207  {
208  SAL_WARN("xmloff.table", "Error while checking available service names");
209  }
210 
211  if (bWriter)
212  {
214  }
215  else
216  {
217  mxCellImportPropertySetMapper = new SvXMLImportPropertyMapper( xCellPropertySetMapper.get(), rImport );
219  mxCellImportPropertySetMapper->ChainImportMapper(new SvXMLImportPropertyMapper(new XMLPropertySetMapper(getCellPropertiesMap(), xFactoryRef.get(), true), rImport));
220  }
221 
222  rtl::Reference < XMLPropertySetMapper > xRowMapper( new XMLPropertySetMapper( getRowPropertiesMap(), xFactoryRef.get(), false ) );
223  mxRowImportPropertySetMapper = new SvXMLImportPropertyMapper( xRowMapper, rImport );
224 
225  rtl::Reference < XMLPropertySetMapper > xColMapper( new XMLPropertySetMapper( getColumnPropertiesMap(), xFactoryRef.get(), false ) );
226  mxColumnImportPropertySetMapper = new SvXMLImportPropertyMapper( xColMapper, rImport );
227 }
228 
230 {
231 }
232 
233 SvXMLImportContext* XMLTableImport::CreateTableContext( sal_uInt16 nPrfx, const OUString& rLName, Reference< XColumnRowRange > const & xColumnRowRange )
234 {
235  rtl::Reference< XMLTableImport > xThis( this );
236  return new XMLTableImportContext( xThis, nPrfx, rLName, xColumnRowRange );
237 }
238 
239 SvXMLStyleContext* XMLTableImport::CreateTableTemplateContext( sal_Int32 /*nElement*/, const Reference< XFastAttributeList >& /*xAttrList*/ )
240 {
241  return new XMLTableTemplateContext( mrImport );
242 }
243 
244 void XMLTableImport::addTableTemplate( const OUString& rsStyleName, XMLTableTemplate& xTableTemplate )
245 {
246  auto xPtr = std::make_shared<XMLTableTemplate>();
247  xPtr->swap( xTableTemplate );
248  maTableTemplates[rsStyleName] = xPtr;
249 }
250 
251 void XMLTableImport::insertTabletemplate(const OUString& rsStyleName, bool bOverwrite)
252 {
253  XMLTableTemplateMap::iterator it = maTableTemplates.find(rsStyleName);
254  if (it == maTableTemplates.end())
255  return;
256 
257  try
258  {
259  Reference<XStyleFamiliesSupplier> xFamiliesSupp(mrImport.GetModel(), UNO_QUERY_THROW);
260  Reference<XNameAccess> xFamilies(xFamiliesSupp->getStyleFamilies());
261 
262  Reference<XNameContainer> xTableFamily(xFamilies->getByName("TableStyles"), UNO_QUERY_THROW);
263  Reference<XIndexAccess> xCellFamily(xFamilies->getByName("CellStyles"), UNO_QUERY_THROW);
264 
265  const OUString sTemplateName(it->first);
266  Reference<XMultiServiceFactory> xFactory(mrImport.GetModel(), UNO_QUERY_THROW);
267  Reference<XNameReplace> xTemplate(xFactory->createInstance("com.sun.star.style.TableStyle"), UNO_QUERY_THROW);
268 
269  std::shared_ptr<XMLTableTemplate> xT(it->second);
270 
271  for (const auto& rStyle : *xT) try
272  {
273  const OUString sPropName(rStyle.first);
274  const OUString sStyleName(rStyle.second);
275  // Internally unassigned cell styles are stored by display name.
276  // However table-template elements reference cell styles by its encoded name.
277  // This loop is looking for cell style by their encoded names.
278  sal_Int32 nCount = xCellFamily->getCount();
279  for (sal_Int32 i=0; i < nCount; ++i)
280  {
281  Any xCellStyle = xCellFamily->getByIndex(i);
282  OUString sEncodedStyleName = mrImport.GetMM100UnitConverter().encodeStyleName(
283  xCellStyle.get<Reference<XStyle>>()->getName());
284  if (sEncodedStyleName == sStyleName)
285  {
286  xTemplate->replaceByName(sPropName, xCellStyle);
287  break;
288  }
289  }
290  }
291  catch (Exception const &)
292  {
293  TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()");
294  }
295 
296  if (xTemplate.is())
297  {
298  if (xTableFamily->hasByName(sTemplateName) && bOverwrite)
299  xTableFamily->replaceByName(sTemplateName, Any(xTemplate));
300  else
301  xTableFamily->insertByName(sTemplateName, Any(xTemplate));
302  }
303  }
304  catch (Exception&)
305  {
306  TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()");
307  }
308 }
309 
311 {
312  if( maTableTemplates.empty() )
313  return;
314 
315  try
316  {
317  Reference< XStyleFamiliesSupplier > xFamiliesSupp( mrImport.GetModel(), UNO_QUERY_THROW );
318  Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
319 
320  Reference< XNameContainer > xTableFamily( xFamilies->getByName( "table" ), UNO_QUERY_THROW );
321  Reference< XNameAccess > xCellFamily( xFamilies->getByName( "cell" ), UNO_QUERY_THROW );
322 
323  Reference< XSingleServiceFactory > xFactory( xTableFamily, UNO_QUERY_THROW );
324 
325  for( const auto& rTemplate : maTableTemplates ) try
326  {
327  const OUString sTemplateName( rTemplate.first );
328  Reference< XNameReplace > xTemplate( xFactory->createInstance(), UNO_QUERY_THROW );
329 
330  std::shared_ptr< XMLTableTemplate > xT( rTemplate.second );
331 
332  for( const auto& rStyle : *xT ) try
333  {
334  const OUString sPropName( rStyle.first );
335  const OUString sStyleName( rStyle.second );
336  xTemplate->replaceByName( sPropName, xCellFamily->getByName( sStyleName ) );
337  }
338  catch( Exception& )
339  {
340  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
341  }
342 
343  if( xTemplate.is() )
344  {
345  if( xTableFamily->hasByName( sTemplateName ) )
346  xTableFamily->replaceByName( sTemplateName, Any( xTemplate ) );
347  else
348  xTableFamily->insertByName( sTemplateName, Any( xTemplate ) );
349  }
350 
351  }
352  catch( Exception& )
353  {
354  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
355  }
356  }
357  catch( Exception& )
358  {
359  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
360  }
361 }
362 
363 
364 XMLTableImportContext::XMLTableImportContext( const rtl::Reference< XMLTableImport >& xImporter, sal_uInt16 nPrfx, const OUString& rLName, Reference< XColumnRowRange > const & xColumnRowRange )
365 : SvXMLImportContext( xImporter->mrImport, nPrfx, rLName )
366 , mxTable( xColumnRowRange, UNO_QUERY )
367 , mxColumns( xColumnRowRange->getColumns() )
368 , mxRows( xColumnRowRange->getRows() )
369 , mnCurrentRow( -1 )
370 , mnCurrentColumn( -1 )
371 {
372 }
373 
374 SvXMLImportContextRef XMLTableImportContext::ImportColumn( sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const Reference< XAttributeList >& xAttrList )
375 {
376  if( mxColumns.is() && (mnCurrentRow == -1) ) try
377  {
378  auto xInfo = std::make_shared<ColumnInfo>();
379 
380  sal_Int32 nRepeated = 1;
381 
382  // read attributes for the table-column
383  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
384  for(sal_Int16 i=0; i < nAttrCount; i++)
385  {
386  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
387  const OUString sValue( xAttrList->getValueByIndex( i ) );
388  OUString aLocalName;
389 
390  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
391  if( XML_NAMESPACE_TABLE == nPrefix2 )
392  {
393  if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
394  {
395  nRepeated = sValue.toInt32();
396  }
397  else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
398  {
399  xInfo->msStyleName = sValue;
400  }
401  else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
402  {
403  xInfo->msDefaultCellStyleName = sValue;
404  }
405  }
406  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
407  IsXMLToken(aLocalName, XML_ID) )
408  {
409 //FIXME: TODO
410  }
411  }
412 
413  if( nRepeated <= 1 )
414  {
415  maColumnInfos.push_back( xInfo );
416  }
417  else
418  {
419  maColumnInfos.insert( maColumnInfos.end(), nRepeated, xInfo );
420  }
421  }
422  catch( Exception& )
423  {
424  OSL_FAIL("xmloff::XMLTableImportContext::ImportTableColumn(), exception caught!");
425  }
426 
427  return nullptr;
428 }
429 
431 {
432  if( !mxColumns.is() )
433  return;
434 
435  try
436  {
437  const sal_Int32 nCount1 = mxColumns->getCount();
438  const sal_Int32 nCount2 = sal::static_int_cast< sal_Int32 >( maColumnInfos.size() );
439  if( nCount1 < nCount2 )
440  mxColumns->insertByIndex( nCount1, nCount2 - nCount1 );
441 
442  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
443 
444  for( sal_Int32 nCol = 0; nCol < nCount2; nCol++ )
445  {
446  std::shared_ptr< ColumnInfo > xInfo( maColumnInfos[nCol] );
447 
448  if( pAutoStyles && !xInfo->msStyleName.isEmpty() )
449  {
450  const XMLPropStyleContext* pStyle =
451  dynamic_cast< const XMLPropStyleContext* >(
452  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_COLUMN, xInfo->msStyleName) );
453 
454  if( pStyle )
455  {
456  Reference< XPropertySet > xColProps( mxColumns->getByIndex(nCol), UNO_QUERY_THROW );
457  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xColProps );
458  }
459  }
460 
461  }
462  }
463  catch( Exception& )
464  {
465  OSL_FAIL("xmloff::XMLTableImportContext::ImportTableColumn(), exception caught!");
466  }
467 }
468 
469 SvXMLImportContext * XMLTableImportContext::ImportRow( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
470 {
471  if( mxRows.is() )
472  {
473  mnCurrentRow++;
474  if( mnCurrentRow == 0 )
475  InitColumns(); // first init columns
476 
477  mnCurrentColumn = -1;
478 
479  const sal_Int32 nRowCount = mxRows->getCount();
480  if( ( nRowCount - 1) < mnCurrentRow )
481  {
482  const sal_Int32 nCount = mnCurrentRow - nRowCount + 1;
483  mxRows->insertByIndex( nRowCount, nCount );
484  }
485 
486  Reference< XPropertySet > xRowSet( mxRows->getByIndex(mnCurrentRow), UNO_QUERY );
487 
488  OUString sStyleName;
489 
490  // read attributes for the table-row
491  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
492  for(sal_Int16 i=0; i < nAttrCount; i++)
493  {
494  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
495  const OUString sValue( xAttrList->getValueByIndex( i ) );
496  OUString aLocalName;
497 
498  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
499  if( nPrefix2 == XML_NAMESPACE_TABLE )
500  {
501  if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
502  {
503  sStyleName = sValue;
504  }
505  else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
506  {
507  msDefaultCellStyleName = sValue;
508  }
509  }
510  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
511  IsXMLToken(aLocalName, XML_ID) )
512  {
513  (void) sValue;
514 //FIXME: TODO
515  }
516  }
517 
518  if( !sStyleName.isEmpty() )
519  {
520  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
521  if( pAutoStyles )
522  {
523  const XMLPropStyleContext* pStyle =
524  dynamic_cast< const XMLPropStyleContext* >(
525  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_ROW, sStyleName) );
526 
527  if( pStyle )
528  {
529  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xRowSet );
530  }
531  }
532  }
533  }
534 
535  SvXMLImportContextRef xThis( this );
536  return new XMLProxyContext( GetImport(), xThis, nPrefix, rLocalName );
537 }
538 
539 SvXMLImportContextRef XMLTableImportContext::ImportCell( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
540 {
541  mnCurrentColumn++;
542  if( mxColumns.is() ) try
543  {
544  if( mxColumns->getCount() <= mnCurrentColumn )
545  mxColumns->insertByIndex( mxColumns->getCount(), mnCurrentColumn - mxColumns->getCount() + 1 );
546 
547  Reference< XMergeableCell > xCell( mxTable->getCellByPosition( mnCurrentColumn, mnCurrentRow ), UNO_QUERY_THROW );
548  XMLCellImportContext* pCellContext = new XMLCellImportContext( GetImport(), xCell, GetDefaultCellStyleName(), nPrefix, rLocalName, xAttrList );
549 
550  const sal_Int32 nColumnSpan = pCellContext->getColumnSpan();
551  const sal_Int32 nRowSpan = pCellContext->getRowSpan();
552  if( (nColumnSpan > 1) || (nRowSpan > 1) )
553  maMergeInfos.push_back( std::make_shared< MergeInfo >( mnCurrentColumn, mnCurrentRow, nColumnSpan, nRowSpan ) );
554 
555  const sal_Int32 nRepeated = pCellContext->getRepeated();
556  if( nRepeated > 1 )
557  {
558  OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), import of repeated Cells not implemented (TODO)");
559  mnCurrentColumn += nRepeated - 1;
560  }
561 
562  return pCellContext;
563  }
564  catch( Exception& )
565  {
566  OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), exception caught!");
567  }
568 
569  return nullptr;
570 }
571 
572 SvXMLImportContextRef XMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
573 {
574  if( nPrefix == XML_NAMESPACE_TABLE )
575  {
576  if( IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
577  return ImportColumn( nPrefix, rLocalName, xAttrList );
578  else if( IsXMLToken( rLocalName, XML_TABLE_ROW ) )
579  return ImportRow( nPrefix, rLocalName, xAttrList );
580  else if( IsXMLToken( rLocalName, XML_TABLE_CELL ) || IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) )
581  return ImportCell( nPrefix, rLocalName, xAttrList );
582  else if( IsXMLToken( rLocalName, XML_TABLE_COLUMNS ) || IsXMLToken( rLocalName, XML_TABLE_ROWS ) )
583  {
584  SvXMLImportContextRef xThis( this );
585  return new XMLProxyContext( GetImport(), xThis, nPrefix, rLocalName );
586  }
587  }
588 
589  return nullptr;
590 }
591 
592 void XMLTableImportContext::StartElement( const Reference< XAttributeList >& /*xAttrList*/ )
593 {
594 }
595 
597 {
598  for( const std::shared_ptr< MergeInfo >& xInfo : maMergeInfos )
599  {
600  if( xInfo ) try
601  {
602  Reference< XCellRange > xRange( mxTable->getCellRangeByPosition( xInfo->mnStartColumn, xInfo->mnStartRow, xInfo->mnEndColumn, xInfo->mnEndRow ) );
603  Reference< XMergeableCellRange > xCursor( mxTable->createCursorByRange( xRange ), UNO_QUERY_THROW );
604  xCursor->merge();
605  }
606  catch( Exception& )
607  {
608  OSL_FAIL("XMLTableImportContext::EndElement(), exception caught while merging cells!");
609  }
610  }
611 }
612 
614 {
615  OUString sStyleName( msDefaultCellStyleName );
616 
617  // if there is still no style name, try default style name from column
618  if( (sStyleName.isEmpty()) && (mnCurrentColumn < sal::static_int_cast<sal_Int32>(maColumnInfos.size())) )
620 
621  return sStyleName;
622 }
623 
624 // XMLCellImportContext
625 
626 XMLCellImportContext::XMLCellImportContext( SvXMLImport& rImport, const Reference< XMergeableCell >& xCell, const OUString& sDefaultCellStyleName, sal_uInt16 nPrfx, const OUString& rLName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList )
627 : SvXMLImportContext( rImport, nPrfx, rLName )
628 , mxCell( xCell )
629 , mbListContextPushed( false )
630 , mnColSpan( 1 )
631 , mnRowSpan( 1 )
632 , mnRepeated( 1 )
633 {
634  OUString sStyleName;
635 
636  // read attributes for the table-cell
637  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
638  for(sal_Int16 i=0; i < nAttrCount; i++)
639  {
640  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
641  const OUString sValue( xAttrList->getValueByIndex( i ) );
642  OUString aLocalName;
643 
644  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
645  if( XML_NAMESPACE_TABLE == nPrefix2 )
646  {
647  if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
648  {
649  mnRepeated = sValue.toInt32();
650  }
651  else if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_SPANNED ) )
652  {
653  mnColSpan = sValue.toInt32();
654  }
655  else if( IsXMLToken( aLocalName, XML_NUMBER_ROWS_SPANNED ) )
656  {
657  mnRowSpan = sValue.toInt32();
658  }
659  else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
660  {
661  sStyleName = sValue;
662  }
663  }
664  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
665  IsXMLToken(aLocalName, XML_ID) )
666  {
667 //FIXME: TODO
668  }
669 //FIXME: RDFa (table:table-cell)
670  }
671 
672  // if there is no style name at the cell, try default style name from row
673  if( sStyleName.isEmpty() )
674  sStyleName = sDefaultCellStyleName;
675 
676  if( sStyleName.isEmpty() )
677  return;
678 
679  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
680  if( !pAutoStyles )
681  return;
682 
683  const XMLPropStyleContext* pStyle =
684  dynamic_cast< const XMLPropStyleContext* >(
685  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL, sStyleName) );
686 
687  if( pStyle )
688  {
689  Reference< XPropertySet > xCellSet( mxCell, UNO_QUERY );
690  if( xCellSet.is() )
691  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xCellSet );
692  }
693 }
694 
695 SvXMLImportContextRef XMLCellImportContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
696 {
697  // create text cursor on demand
698  if( !mxCursor.is() )
699  {
700  Reference< XText > xText( mxCell, UNO_QUERY );
701  if( xText.is() )
702  {
703  rtl::Reference < XMLTextImportHelper > xTxtImport( GetImport().GetTextImport() );
704  mxOldCursor = xTxtImport->GetCursor();
705  mxCursor = xText->createTextCursor();
706  if( mxCursor.is() )
707  xTxtImport->SetCursor( mxCursor );
708 
709  // remember old list item and block (#91964#) and reset them
710  // for the text frame
711  xTxtImport->PushListContext();
712  mbListContextPushed = true;
713  }
714  }
715 
716  SvXMLImportContext * pContext = nullptr;
717 
718  // if we have a text cursor, lets try to import some text
719  if( mxCursor.is() )
720  {
721  pContext = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nPrefix, rLocalName, xAttrList );
722  }
723 
724  return pContext;
725 }
726 
727 void XMLCellImportContext::EndElement()
728 {
729  if(mxCursor.is())
730  {
731  // delete addition newline
732  mxCursor->gotoEnd( false );
733  mxCursor->goLeft( 1, true );
734  mxCursor->setString( "" );
735 
736  // reset cursor
737  GetImport().GetTextImport()->ResetCursor();
738  }
739 
740  if(mxOldCursor.is())
741  GetImport().GetTextImport()->SetCursor( mxOldCursor );
742 
743  // reinstall old list item (if necessary) #91964#
744  if (mbListContextPushed) {
745  GetImport().GetTextImport()->PopListContext();
746  }
747 }
748 
749 
750 XMLTableTemplateContext::XMLTableTemplateContext( SvXMLImport& rImport )
752 {
753 }
754 
755 void XMLTableTemplateContext::SetAttribute( sal_uInt16 nPrefixKey,
756  const OUString& rLocalName,
757  const OUString& rValue )
758 {
759  if( (nPrefixKey == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_STYLE_NAME ))
760  // Writer specific: according to oasis odf 1.2 prefix should be "table" and element name should be "name"
761  || (nPrefixKey == XML_NAMESPACE_TABLE && IsXMLToken( rLocalName, XML_NAME )))
762  {
763  msTemplateStyleName = rValue;
764  }
765 }
766 
767 void XMLTableTemplateContext::endFastElement(sal_Int32 )
768 {
769  rtl::Reference< XMLTableImport > xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() );
770  if( xTableImport.is() )
771  xTableImport->addTableTemplate( msTemplateStyleName, maTableTemplate );
772 }
773 
774 void XMLTableTemplateContext::CreateAndInsert(bool bOverwrite)
775 {
776  rtl::Reference<XMLTableImport> xTableImport(GetImport().GetShapeImport()->GetShapeTableImport());
777  if(xTableImport.is())
778  xTableImport->insertTabletemplate(msTemplateStyleName, bOverwrite);
779 }
780 
781 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableTemplateContext::createFastChildContext(
782  sal_Int32 nElement,
783  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
784 {
785  if( IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
786  {
787  const TableStyleElement* pElements = getTableStyleMap();
788  sal_Int32 nLocalName = nElement & TOKEN_MASK;
789  while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName)
790  pElements++;
791 
792  if( pElements->meElement != XML_TOKEN_END )
793  {
794  for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
795  {
796  switch (aIter.getToken())
797  {
798  case XML_ELEMENT(TEXT, XML_STYLE_NAME):
800  maTableTemplate[pElements->msStyleName] = aIter.toString();
801  break;
802  default:
803  SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString());
804  }
805  }
806  }
807  } else if (IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT)) // Writer specific cell styles
808  {
810  sal_Int32 nLocalName = nElement & TOKEN_MASK;
811  while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName)
812  pElements++;
813 
814  if (pElements->meElement != XML_TOKEN_END)
815  {
816  for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
817  {
818  switch (aIter.getToken())
819  {
820  case XML_ELEMENT(TEXT, XML_STYLE_NAME):
822  maTableTemplate[pElements->msStyleName] = aIter.toString();
823  break;
824  default:
825  SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString());
826  }
827  }
828  }
829  }
830 
831  return nullptr;
832 }
833 
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
rtl::Reference< SvXMLImportPropertyMapper > mxColumnImportPropertySetMapper
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
virtual void EndElement()
EndElement is called before a context will be destructed, but after an elements context has been pars...
Definition: xmlictxt.cxx:62
friend class XMLTableImportContext
const TableStyleElement * getTableStyleMap()
virtual void StartElement(const Reference< XAttributeList > &xAttrList) override
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
::xmloff::token::XMLTokenEnum meElement
Definition: table.hxx:29
WeakReference< XInterface > mxParent
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:402
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
std::map< OUString, OUString > XMLTableTemplate
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
OUString GetDefaultCellStyleName() const
void insertTabletemplate(const OUString &rsStyleName, bool bOverwrite)
Inserts to the doc template with given name.
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const Reference< XAttributeList > &xAttrList) override
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
char const sTemplateName[]
const XMLPropertyMapEntry * getCellPropertiesMap()
XMLTableImport(SvXMLImport &rImport, const rtl::Reference< XMLPropertySetMapper > &xCellPropertySetMapper, const rtl::Reference< XMLPropertyHandlerFactory > &xFactoryRef)
MergeInfoVector maMergeInfos
XMLTableImportContext(const rtl::Reference< XMLTableImport > &xThis, sal_uInt16 nPrfx, const OUString &rLName, Reference< XColumnRowRange > const &xColumnRowRange)
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
XmlStyleFamily
Definition: families.hxx:47
sal_Int32 mnColSpan
int nCount
static OUString getPrefixAndNameFromToken(sal_Int32 nToken)
Definition: xmlimp.cxx:2025
XMLTableTemplateMap maTableTemplates
OUString msStyleName
constexpr sal_uInt16 XML_NAMESPACE_XML
rtl::Reference< SvXMLImportPropertyMapper > mxCellImportPropertySetMapper
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
const TableStyleElement * getWriterSpecificTableStyleMap()
constexpr sal_uInt16 XML_NAMESPACE_TEXT
virtual ~XMLTableImport() override
const XMLPropertyMapEntry * getColumnPropertiesMap()
void finishStyles()
Inserts all table templates.
Reference< XTableColumns > mxColumns
std::vector< std::shared_ptr< MergeInfo > > MergeInfoVector
std::vector< std::shared_ptr< ColumnInfo > > maColumnInfos
SvXMLImport & mrImport
static SvXMLImportPropertyMapper * CreateTableCellExtPropMapper(SvXMLImport &)
Definition: txtimp.cxx:1077
SvXMLImportContextRef ImportColumn(sal_uInt16 nPrefix, const OUString &rLocalName, const Reference< XAttributeList > &xAttrList)
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
virtual void CreateAndInsert(bool bOverwrite)
Definition: xmlstyle.cxx:149
sal_Int32 mnRowSpan
constexpr sal_uInt16 XML_NAMESPACE_TABLE
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
Definition: xmlictxt.cxx:114
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
Definition: xmlimp.hxx:101
Handling of tokens in XML:
Reference< XTableRows > mxRows
SvXMLImportContext * CreateTableContext(sal_uInt16 nPrfx, const OUString &rLName, css::uno::Reference< css::table::XColumnRowRange > const &xColumnRowRange)
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:128
const XMLPropertyMapEntry * getRowPropertiesMap()
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:94
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:404
rtl::Reference< SvXMLImportPropertyMapper > mxRowImportPropertySetMapper
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlimp.hxx:408
SvXMLStyleContext * CreateTableTemplateContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
TABLE
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
Create a children element context.
Definition: xmlictxt.cxx:51
OUString encodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
Definition: xmluconv.cxx:739
virtual void SetAttribute(sal_uInt16 nPrefixKey, const OUString &rLocalName, const OUString &rValue)
Definition: xmlstyle.cxx:65
css::uno::Reference< css::table::XTable > mxTable
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:809
void addTableTemplate(const OUString &rsStyleName, XMLTableTemplate &xTableTemplate)
#define SAL_WARN(area, stream)
Reference< XSingleServiceFactory > xFactory
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:91
static SvXMLImportPropertyMapper * CreateParaExtPropMapper(SvXMLImport &)
Definition: txtimp.cxx:1038
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
SvXMLImportContext * ImportRow(sal_uInt16 nPrefix, const OUString &rLocalName, const Reference< XAttributeList > &xAttrList)
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:608
OUString toString(OptionInfo const *info)
SvXMLImportContextRef ImportCell(sal_uInt16 nPrefix, const OUString &rLocalName, const Reference< XAttributeList > &xAttrList)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo