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/nmspmap.hxx>
41 #include <xmloff/xmlstyle.hxx>
42 #include <xmloff/prstylei.hxx>
43 
44 #include <xmloff/xmlnmspe.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, sal_uInt16 nPrfx, const OUString& rLName, const Reference< XAttributeList >& xAttrList );
161 
162  virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList ) override;
163 
164  virtual void EndElement() override;
165 
166  virtual void CreateAndInsert( bool bOverwrite ) override;
167 protected:
168  virtual void SetAttribute( sal_uInt16 nPrefixKey,
169  const OUString& rLocalName,
170  const OUString& rValue ) override;
171 private:
172  XMLTableTemplate maTableTemplate;
173  OUString msTemplateStyleName;
174 };
175 
176 }
177 
178 
179 XMLProxyContext::XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent, sal_uInt16 nPrfx, const OUString& rLName )
180 : SvXMLImportContext( rImport, nPrfx, rLName )
181 , mxParent( xParent )
182 {
183 }
184 
185 SvXMLImportContextRef XMLProxyContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
186 {
187  if( mxParent.is() )
188  return mxParent->CreateChildContext( nPrefix, rLocalName, xAttrList );
189  return nullptr;
190 }
191 
192 
194 : mrImport( rImport )
195 {
196  bool bWriter = false;
197  // check if called by Writer
198  Reference<XMultiServiceFactory> xFac(rImport.GetModel(), UNO_QUERY);
199  if (xFac.is()) try
200  {
201  Sequence<OUString> sSNS = xFac->getAvailableServiceNames();
202  bWriter = comphelper::findValue(sSNS, "com.sun.star.style.TableStyle") != -1;
203  }
204  catch(const Exception&)
205  {
206  SAL_WARN("xmloff.table", "Error while checking available service names");
207  }
208 
209  if (bWriter)
210  {
212  }
213  else
214  {
215  mxCellImportPropertySetMapper = new SvXMLImportPropertyMapper( xCellPropertySetMapper.get(), rImport );
217  mxCellImportPropertySetMapper->ChainImportMapper(new SvXMLImportPropertyMapper(new XMLPropertySetMapper(getCellPropertiesMap(), xFactoryRef.get(), true), rImport));
218  }
219 
220  rtl::Reference < XMLPropertySetMapper > xRowMapper( new XMLPropertySetMapper( getRowPropertiesMap(), xFactoryRef.get(), false ) );
221  mxRowImportPropertySetMapper = new SvXMLImportPropertyMapper( xRowMapper, rImport );
222 
223  rtl::Reference < XMLPropertySetMapper > xColMapper( new XMLPropertySetMapper( getColumnPropertiesMap(), xFactoryRef.get(), false ) );
224  mxColumnImportPropertySetMapper = new SvXMLImportPropertyMapper( xColMapper, rImport );
225 }
226 
228 {
229 }
230 
231 SvXMLImportContext* XMLTableImport::CreateTableContext( sal_uInt16 nPrfx, const OUString& rLName, Reference< XColumnRowRange > const & xColumnRowRange )
232 {
233  rtl::Reference< XMLTableImport > xThis( this );
234  return new XMLTableImportContext( xThis, nPrfx, rLName, xColumnRowRange );
235 }
236 
237 SvXMLStyleContext* XMLTableImport::CreateTableTemplateContext( sal_uInt16 nPrfx, const OUString& rLName, const Reference< XAttributeList >& xAttrList )
238 {
239  return new XMLTableTemplateContext( mrImport, nPrfx, rLName, xAttrList );
240 }
241 
242 void XMLTableImport::addTableTemplate( const OUString& rsStyleName, XMLTableTemplate& xTableTemplate )
243 {
244  auto xPtr = std::make_shared<XMLTableTemplate>();
245  xPtr->swap( xTableTemplate );
246  maTableTemplates[rsStyleName] = xPtr;
247 }
248 
249 void XMLTableImport::insertTabletemplate(const OUString& rsStyleName, bool bOverwrite)
250 {
251  XMLTableTemplateMap::iterator it = maTableTemplates.find(rsStyleName);
252  if (it == maTableTemplates.end())
253  return;
254 
255  try
256  {
257  Reference<XStyleFamiliesSupplier> xFamiliesSupp(mrImport.GetModel(), UNO_QUERY_THROW);
258  Reference<XNameAccess> xFamilies(xFamiliesSupp->getStyleFamilies());
259  const OUString sFamilyName("TableStyles");
260  const OUString sCellFamilyName("CellStyles");
261 
262  Reference<XNameContainer> xTableFamily(xFamilies->getByName(sFamilyName), UNO_QUERY_THROW);
263  Reference<XIndexAccess> xCellFamily(xFamilies->getByName(sCellFamilyName), 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() ) try
313  {
314  Reference< XStyleFamiliesSupplier > xFamiliesSupp( mrImport.GetModel(), UNO_QUERY_THROW );
315  Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
316  const OUString sFamilyName( "table" );
317  const OUString sCellFamilyName( "cell" );
318 
319  Reference< XNameContainer > xTableFamily( xFamilies->getByName( sFamilyName ), UNO_QUERY_THROW );
320  Reference< XNameAccess > xCellFamily( xFamilies->getByName( sCellFamilyName ), UNO_QUERY_THROW );
321 
322  Reference< XSingleServiceFactory > xFactory( xTableFamily, UNO_QUERY_THROW );
323 
324  for( const auto& rTemplate : maTableTemplates ) try
325  {
326  const OUString sTemplateName( rTemplate.first );
327  Reference< XNameReplace > xTemplate( xFactory->createInstance(), UNO_QUERY_THROW );
328 
329  std::shared_ptr< XMLTableTemplate > xT( rTemplate.second );
330 
331  for( const auto& rStyle : *xT ) try
332  {
333  const OUString sPropName( rStyle.first );
334  const OUString sStyleName( rStyle.second );
335  xTemplate->replaceByName( sPropName, xCellFamily->getByName( sStyleName ) );
336  }
337  catch( Exception& )
338  {
339  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
340  }
341 
342  if( xTemplate.is() )
343  {
344  if( xTableFamily->hasByName( sTemplateName ) )
345  xTableFamily->replaceByName( sTemplateName, Any( xTemplate ) );
346  else
347  xTableFamily->insertByName( sTemplateName, Any( xTemplate ) );
348  }
349 
350  }
351  catch( Exception& )
352  {
353  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
354  }
355  }
356  catch( Exception& )
357  {
358  OSL_FAIL("xmloff::XMLTableImport::finishStyles(), exception caught!");
359  }
360 }
361 
362 
363 XMLTableImportContext::XMLTableImportContext( const rtl::Reference< XMLTableImport >& xImporter, sal_uInt16 nPrfx, const OUString& rLName, Reference< XColumnRowRange > const & xColumnRowRange )
364 : SvXMLImportContext( xImporter->mrImport, nPrfx, rLName )
365 , mxTable( xColumnRowRange, UNO_QUERY )
366 , mxColumns( xColumnRowRange->getColumns() )
367 , mxRows( xColumnRowRange->getRows() )
368 , mnCurrentRow( -1 )
369 , mnCurrentColumn( -1 )
370 {
371 }
372 
373 SvXMLImportContextRef XMLTableImportContext::ImportColumn( sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const Reference< XAttributeList >& xAttrList )
374 {
375  if( mxColumns.is() && (mnCurrentRow == -1) ) try
376  {
377  auto xInfo = std::make_shared<ColumnInfo>();
378 
379  sal_Int32 nRepeated = 1;
380 
381  // read attributes for the table-column
382  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
383  for(sal_Int16 i=0; i < nAttrCount; i++)
384  {
385  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
386  const OUString sValue( xAttrList->getValueByIndex( i ) );
387  OUString aLocalName;
388 
389  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
390  if( XML_NAMESPACE_TABLE == nPrefix2 )
391  {
392  if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
393  {
394  nRepeated = sValue.toInt32();
395  }
396  else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
397  {
398  xInfo->msStyleName = sValue;
399  }
400  else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
401  {
402  xInfo->msDefaultCellStyleName = sValue;
403  }
404  }
405  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
406  IsXMLToken(aLocalName, XML_ID) )
407  {
408 //FIXME: TODO
409  }
410  }
411 
412  if( nRepeated <= 1 )
413  {
414  maColumnInfos.push_back( xInfo );
415  }
416  else
417  {
418  maColumnInfos.insert( maColumnInfos.end(), nRepeated, xInfo );
419  }
420  }
421  catch( Exception& )
422  {
423  OSL_FAIL("xmloff::XMLTableImportContext::ImportTableColumn(), exception caught!");
424  }
425 
426  return nullptr;
427 }
428 
430 {
431  if( mxColumns.is() ) try
432  {
433  const sal_Int32 nCount1 = mxColumns->getCount();
434  const sal_Int32 nCount2 = sal::static_int_cast< sal_Int32 >( maColumnInfos.size() );
435  if( nCount1 < nCount2 )
436  mxColumns->insertByIndex( nCount1, nCount2 - nCount1 );
437 
438  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
439 
440  for( sal_Int32 nCol = 0; nCol < nCount2; nCol++ )
441  {
442  std::shared_ptr< ColumnInfo > xInfo( maColumnInfos[nCol] );
443 
444  if( pAutoStyles && !xInfo->msStyleName.isEmpty() )
445  {
446  const XMLPropStyleContext* pStyle =
447  dynamic_cast< const XMLPropStyleContext* >(
448  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_COLUMN, xInfo->msStyleName) );
449 
450  if( pStyle )
451  {
452  Reference< XPropertySet > xColProps( mxColumns->getByIndex(nCol), UNO_QUERY_THROW );
453  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xColProps );
454  }
455  }
456 
457  }
458  }
459  catch( Exception& )
460  {
461  OSL_FAIL("xmloff::XMLTableImportContext::ImportTableColumn(), exception caught!");
462  }
463 }
464 
465 SvXMLImportContext * XMLTableImportContext::ImportRow( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
466 {
467  if( mxRows.is() )
468  {
469  mnCurrentRow++;
470  if( mnCurrentRow == 0 )
471  InitColumns(); // first init columns
472 
473  mnCurrentColumn = -1;
474 
475  const sal_Int32 nRowCount = mxRows->getCount();
476  if( ( nRowCount - 1) < mnCurrentRow )
477  {
478  const sal_Int32 nCount = mnCurrentRow - nRowCount + 1;
479  mxRows->insertByIndex( nRowCount, nCount );
480  }
481 
482  Reference< XPropertySet > xRowSet( mxRows->getByIndex(mnCurrentRow), UNO_QUERY );
483 
484  OUString sStyleName;
485 
486  // read attributes for the table-row
487  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
488  for(sal_Int16 i=0; i < nAttrCount; i++)
489  {
490  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
491  const OUString sValue( xAttrList->getValueByIndex( i ) );
492  OUString aLocalName;
493 
494  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
495  if( nPrefix2 == XML_NAMESPACE_TABLE )
496  {
497  if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
498  {
499  sStyleName = sValue;
500  }
501  else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
502  {
503  msDefaultCellStyleName = sValue;
504  }
505  }
506  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
507  IsXMLToken(aLocalName, XML_ID) )
508  {
509  (void) sValue;
510 //FIXME: TODO
511  }
512  }
513 
514  if( !sStyleName.isEmpty() )
515  {
516  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
517  if( pAutoStyles )
518  {
519  const XMLPropStyleContext* pStyle =
520  dynamic_cast< const XMLPropStyleContext* >(
521  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_ROW, sStyleName) );
522 
523  if( pStyle )
524  {
525  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xRowSet );
526  }
527  }
528  }
529  }
530 
531  SvXMLImportContextRef xThis( this );
532  return new XMLProxyContext( GetImport(), xThis, nPrefix, rLocalName );
533 }
534 
535 SvXMLImportContextRef XMLTableImportContext::ImportCell( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
536 {
537  mnCurrentColumn++;
538  if( mxColumns.is() ) try
539  {
540  if( mxColumns->getCount() <= mnCurrentColumn )
541  mxColumns->insertByIndex( mxColumns->getCount(), mnCurrentColumn - mxColumns->getCount() + 1 );
542 
543  Reference< XMergeableCell > xCell( mxTable->getCellByPosition( mnCurrentColumn, mnCurrentRow ), UNO_QUERY_THROW );
544  XMLCellImportContext* pCellContext = new XMLCellImportContext( GetImport(), xCell, GetDefaultCellStyleName(), nPrefix, rLocalName, xAttrList );
545 
546  const sal_Int32 nColumnSpan = pCellContext->getColumnSpan();
547  const sal_Int32 nRowSpan = pCellContext->getRowSpan();
548  if( (nColumnSpan > 1) || (nRowSpan > 1) )
549  maMergeInfos.push_back( std::make_shared< MergeInfo >( mnCurrentColumn, mnCurrentRow, nColumnSpan, nRowSpan ) );
550 
551  const sal_Int32 nRepeated = pCellContext->getRepeated();
552  if( nRepeated > 1 )
553  {
554  OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), import of repeated Cells not implemented (TODO)");
555  mnCurrentColumn += nRepeated - 1;
556  }
557 
558  return pCellContext;
559  }
560  catch( Exception& )
561  {
562  OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), exception caught!");
563  }
564 
565  return nullptr;
566 }
567 
568 SvXMLImportContextRef XMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
569 {
570  if( nPrefix == XML_NAMESPACE_TABLE )
571  {
572  if( IsXMLToken( rLocalName, XML_TABLE_COLUMN ) )
573  return ImportColumn( nPrefix, rLocalName, xAttrList );
574  else if( IsXMLToken( rLocalName, XML_TABLE_ROW ) )
575  return ImportRow( nPrefix, rLocalName, xAttrList );
576  else if( IsXMLToken( rLocalName, XML_TABLE_CELL ) || IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) )
577  return ImportCell( nPrefix, rLocalName, xAttrList );
578  else if( IsXMLToken( rLocalName, XML_TABLE_COLUMNS ) || IsXMLToken( rLocalName, XML_TABLE_ROWS ) )
579  {
580  SvXMLImportContextRef xThis( this );
581  return new XMLProxyContext( GetImport(), xThis, nPrefix, rLocalName );
582  }
583  }
584 
585  return nullptr;
586 }
587 
588 void XMLTableImportContext::StartElement( const Reference< XAttributeList >& /*xAttrList*/ )
589 {
590 }
591 
593 {
594  for( const std::shared_ptr< MergeInfo >& xInfo : maMergeInfos )
595  {
596  if( xInfo.get() ) try
597  {
598  Reference< XCellRange > xRange( mxTable->getCellRangeByPosition( xInfo->mnStartColumn, xInfo->mnStartRow, xInfo->mnEndColumn, xInfo->mnEndRow ) );
599  Reference< XMergeableCellRange > xCursor( mxTable->createCursorByRange( xRange ), UNO_QUERY_THROW );
600  xCursor->merge();
601  }
602  catch( Exception& )
603  {
604  OSL_FAIL("XMLTableImportContext::EndElement(), exception caught while merging cells!");
605  }
606  }
607 }
608 
610 {
611  OUString sStyleName( msDefaultCellStyleName );
612 
613  // if there is still no style name, try default style name from column
614  if( (sStyleName.isEmpty()) && (mnCurrentColumn < sal::static_int_cast<sal_Int32>(maColumnInfos.size())) )
616 
617  return sStyleName;
618 }
619 
620 // XMLCellImportContext
621 
622 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 )
623 : SvXMLImportContext( rImport, nPrfx, rLName )
624 , mxCell( xCell )
625 , mbListContextPushed( false )
626 , mnColSpan( 1 )
627 , mnRowSpan( 1 )
628 , mnRepeated( 1 )
629 {
630  OUString sStyleName;
631 
632  // read attributes for the table-cell
633  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
634  for(sal_Int16 i=0; i < nAttrCount; i++)
635  {
636  const OUString sAttrName( xAttrList->getNameByIndex( i ) );
637  const OUString sValue( xAttrList->getValueByIndex( i ) );
638  OUString aLocalName;
639 
640  sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
641  if( XML_NAMESPACE_TABLE == nPrefix2 )
642  {
643  if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
644  {
645  mnRepeated = sValue.toInt32();
646  }
647  else if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_SPANNED ) )
648  {
649  mnColSpan = sValue.toInt32();
650  }
651  else if( IsXMLToken( aLocalName, XML_NUMBER_ROWS_SPANNED ) )
652  {
653  mnRowSpan = sValue.toInt32();
654  }
655  else if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
656  {
657  sStyleName = sValue;
658  }
659  }
660  else if ( (XML_NAMESPACE_XML == nPrefix2) &&
661  IsXMLToken(aLocalName, XML_ID) )
662  {
663 //FIXME: TODO
664  }
665 //FIXME: RDFa (table:table-cell)
666  }
667 
668  // if there is no style name at the cell, try default style name from row
669  if( sStyleName.isEmpty() )
670  sStyleName = sDefaultCellStyleName;
671 
672  if( !sStyleName.isEmpty() )
673  {
674  SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext();
675  if( pAutoStyles )
676  {
677  const XMLPropStyleContext* pStyle =
678  dynamic_cast< const XMLPropStyleContext* >(
679  pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL, sStyleName) );
680 
681  if( pStyle )
682  {
683  Reference< XPropertySet > xCellSet( mxCell, UNO_QUERY );
684  if( xCellSet.is() )
685  const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xCellSet );
686  }
687  }
688  }
689 }
690 
691 SvXMLImportContextRef XMLCellImportContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
692 {
693  // create text cursor on demand
694  if( !mxCursor.is() )
695  {
696  Reference< XText > xText( mxCell, UNO_QUERY );
697  if( xText.is() )
698  {
699  rtl::Reference < XMLTextImportHelper > xTxtImport( GetImport().GetTextImport() );
700  mxOldCursor = xTxtImport->GetCursor();
701  mxCursor = xText->createTextCursor();
702  if( mxCursor.is() )
703  xTxtImport->SetCursor( mxCursor );
704 
705  // remember old list item and block (#91964#) and reset them
706  // for the text frame
707  xTxtImport->PushListContext();
708  mbListContextPushed = true;
709  }
710  }
711 
712  SvXMLImportContext * pContext = nullptr;
713 
714  // if we have a text cursor, lets try to import some text
715  if( mxCursor.is() )
716  {
717  pContext = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nPrefix, rLocalName, xAttrList );
718  }
719 
720  return pContext;
721 }
722 
723 void XMLCellImportContext::EndElement()
724 {
725  if(mxCursor.is())
726  {
727  // delete addition newline
728  mxCursor->gotoEnd( false );
729  mxCursor->goLeft( 1, true );
730  mxCursor->setString( "" );
731 
732  // reset cursor
733  GetImport().GetTextImport()->ResetCursor();
734  }
735 
736  if(mxOldCursor.is())
737  GetImport().GetTextImport()->SetCursor( mxOldCursor );
738 
739  // reinstall old list item (if necessary) #91964#
740  if (mbListContextPushed) {
741  GetImport().GetTextImport()->PopListContext();
742  }
743 }
744 
745 
746 XMLTableTemplateContext::XMLTableTemplateContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< XAttributeList >& xAttrList )
747 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XmlStyleFamily::TABLE_TEMPLATE_ID, false )
748 {
749 }
750 
751 void XMLTableTemplateContext::SetAttribute( sal_uInt16 nPrefixKey,
752  const OUString& rLocalName,
753  const OUString& rValue )
754 {
755  if( (nPrefixKey == XML_NAMESPACE_TEXT && IsXMLToken( rLocalName, XML_STYLE_NAME ))
756  // Writer specific: according to oasis odf 1.2 prefix should be "table" and element name should be "name"
757  || (nPrefixKey == XML_NAMESPACE_TABLE && IsXMLToken( rLocalName, XML_NAME )))
758  {
759  msTemplateStyleName = rValue;
760  }
761 }
762 
763 void XMLTableTemplateContext::EndElement()
764 {
765  rtl::Reference< XMLTableImport > xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() );
766  if( xTableImport.is() )
767  xTableImport->addTableTemplate( msTemplateStyleName, maTableTemplate );
768 }
769 
770 void XMLTableTemplateContext::CreateAndInsert(bool bOverwrite)
771 {
772  rtl::Reference<XMLTableImport> xTableImport(GetImport().GetShapeImport()->GetShapeTableImport());
773  if(xTableImport.is())
774  xTableImport->insertTabletemplate(msTemplateStyleName, bOverwrite);
775 }
776 
777 SvXMLImportContextRef XMLTableTemplateContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
778 {
779  if( nPrefix == XML_NAMESPACE_TABLE )
780  {
781  const TableStyleElement* pElements = getTableStyleMap();
782  while( (pElements->meElement != XML_TOKEN_END) && !IsXMLToken( rLocalName, pElements->meElement ) )
783  pElements++;
784 
785  if( pElements->meElement != XML_TOKEN_END )
786  {
787  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
788  for(sal_Int16 i=0; i < nAttrCount; i++)
789  {
790  OUString sAttrName;
791  sal_uInt16 nAttrPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( i ), &sAttrName );
792  if( (nAttrPrefix == XML_NAMESPACE_TEXT || nAttrPrefix == XML_NAMESPACE_TABLE) &&
793  IsXMLToken( sAttrName, XML_STYLE_NAME ) )
794  {
795  maTableTemplate[pElements->msStyleName] = xAttrList->getValueByIndex( i );
796  break;
797  }
798  }
799  }
800  } else if (nPrefix == XML_NAMESPACE_LO_EXT) // Writer specific cell styles
801  {
803  while ((pElements->meElement != XML_TOKEN_END) && !IsXMLToken(rLocalName, pElements->meElement ))
804  pElements++;
805 
806  if (pElements->meElement != XML_TOKEN_END)
807  {
808  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
809  for (sal_Int16 i=0; i < nAttrCount; i++)
810  {
811  OUString sAttrName;
812  sal_uInt16 nAttrPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName(xAttrList->getNameByIndex( i ), &sAttrName);
813  if( (nAttrPrefix == XML_NAMESPACE_TEXT || nAttrPrefix == XML_NAMESPACE_TABLE) &&
814  IsXMLToken( sAttrName, XML_STYLE_NAME ) )
815  {
816  maTableTemplate[pElements->msStyleName] = xAttrList->getValueByIndex(i);
817  break;
818  }
819  }
820  }
821  }
822 
823  return nullptr;
824 }
825 
826 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
rtl::Reference< SvXMLImportPropertyMapper > mxColumnImportPropertySetMapper
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
Definition: xmlnmspe.hxx:80
SvXMLStyleContext * CreateTableTemplateContext(sal_uInt16 nPrfx, const OUString &rLName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
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:397
std::map< OUString, OUString > XMLTableTemplate
constexpr sal_uInt16 XML_NAMESPACE_TEXT
Definition: xmlnmspe.hxx:31
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
Definition: nmspmap.cxx:437
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
XMLTableTemplateMap maTableTemplates
OUString msStyleName
constexpr sal_uInt16 XML_NAMESPACE_XML
Definition: xmlnmspe.hxx:51
rtl::Reference< SvXMLImportPropertyMapper > mxCellImportPropertySetMapper
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
const TableStyleElement * getWriterSpecificTableStyleMap()
virtual ~XMLTableImport() override
const XMLPropertyMapEntry * getColumnPropertiesMap()
void finishStyles()
Inserts all table templates.
Reference< XTableColumns > mxColumns
OUString msStyleName
Definition: table.hxx:30
std::vector< std::shared_ptr< MergeInfo > > MergeInfoVector
std::vector< std::shared_ptr< ColumnInfo > > maColumnInfos
SvXMLImport & mrImport
static SvXMLImportPropertyMapper * CreateTableCellExtPropMapper(SvXMLImport &)
Definition: txtimp.cxx:1093
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:182
sal_Int32 mnRowSpan
Handling of tokens in XML:
Reference< XTableRows > mxRows
constexpr sal_uInt16 XML_NAMESPACE_TABLE
Definition: xmlnmspe.hxx:32
SvXMLImportContext * CreateTableContext(sal_uInt16 nPrfx, const OUString &rLName, css::uno::Reference< css::table::XColumnRowRange > const &xColumnRowRange)
const XMLPropertyMapEntry * getRowPropertiesMap()
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:399
rtl::Reference< SvXMLImportPropertyMapper > mxRowImportPropertySetMapper
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlimp.hxx:403
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:94
css::uno::Reference< css::table::XTable > mxTable
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
Definition: xmlstyle.cxx:870
void addTableTemplate(const OUString &rsStyleName, XMLTableTemplate &xTableTemplate)
#define SAL_WARN(area, stream)
Reference< XSingleServiceFactory > xFactory
static SvXMLImportPropertyMapper * CreateParaExtPropMapper(SvXMLImport &)
Definition: txtimp.cxx:1054
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:602
SvXMLImportContextRef ImportCell(sal_uInt16 nPrefix, const OUString &rLocalName, const Reference< XAttributeList > &xAttrList)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo