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 "xmlrowi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlcelli.hxx"
23 #include "xmlstyli.hxx"
24 #include <document.hxx>
25 #include <docuno.hxx>
26 #include <olinetab.hxx>
27 #include <sheetdata.hxx>
28 #include <documentimport.hxx>
29 #include <unonames.hxx>
30 
31 #include <xmloff/xmlnmspe.hxx>
32 #include <xmloff/families.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <sax/fastattribs.hxx>
35 #include <com/sun/star/sheet/XSpreadsheet.hpp>
36 #include <com/sun/star/table/XColumnRowRange.hpp>
37 #include <com/sun/star/sheet/XPrintAreas.hpp>
38 #include <comphelper/servicehelper.hxx>
39 #include <osl/diagnose.h>
40 
41 #define SC_ISFILTERED "IsFiltered"
42 
43 using namespace com::sun::star;
44 using namespace xmloff::token;
45 
ScXMLTableRowContext(ScXMLImport & rImport,const rtl::Reference<sax_fastparser::FastAttributeList> & rAttrList)46 ScXMLTableRowContext::ScXMLTableRowContext( ScXMLImport& rImport,
47                                       const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList ) :
48     ScXMLImportContext( rImport ),
49     sVisibility(GetXMLToken(XML_VISIBLE)),
50     nRepeatedRows(1),
51     bHasCell(false)
52 {
53     OUString sCellStyleName;
54     if ( rAttrList.is() )
55     {
56         for (auto &it : *rAttrList)
57         {
58             switch (it.getToken())
59             {
60                 case XML_ELEMENT( TABLE, XML_STYLE_NAME ):
61                 {
62                     sStyleName = it.toString();
63                 }
64                 break;
65                 case XML_ELEMENT( TABLE, XML_VISIBILITY ):
66                 {
67                     sVisibility = it.toString();
68                 }
69                 break;
70                 case XML_ELEMENT( TABLE, XML_NUMBER_ROWS_REPEATED ):
71                 {
72                     nRepeatedRows = std::max( it.toInt32(), sal_Int32(1) );
73                     nRepeatedRows = std::min( nRepeatedRows, MAXROWCOUNT );
74                 }
75                 break;
76                 case XML_ELEMENT( TABLE, XML_DEFAULT_CELL_STYLE_NAME ):
77                 {
78                     sCellStyleName = it.toString();
79                 }
80                 break;
81                 /*case XML_ELEMENT( TABLE, XML_USE_OPTIMAL_HEIGHT ):
82                 {
83                     sOptimalHeight = it.toString();
84                 }
85                 break;*/
86             }
87         }
88     }
89 
90     GetScImport().GetTables().AddRow();
91     GetScImport().GetTables().SetRowStyle(sCellStyleName);
92 }
93 
~ScXMLTableRowContext()94 ScXMLTableRowContext::~ScXMLTableRowContext()
95 {
96 }
97 
98 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)99         ScXMLTableRowContext::createFastChildContext( sal_Int32 nElement,
100         const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
101 {
102     SvXMLImportContext *pContext(nullptr);
103     sax_fastparser::FastAttributeList *pAttribList =
104         sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList );
105 
106     switch( nElement )
107     {
108     case XML_ELEMENT( TABLE, XML_TABLE_CELL ):
109 //      if( IsInsertCellPossible() )
110         {
111             bHasCell = true;
112             pContext = new ScXMLTableRowCellContext( GetScImport(),
113                                                        pAttribList, false, static_cast<SCROW>(nRepeatedRows)
114                                                       //this
115                                                       );
116         }
117         break;
118     case XML_ELEMENT( TABLE, XML_COVERED_TABLE_CELL ):
119 //      if( IsInsertCellPossible() )
120         {
121             bHasCell = true;
122             pContext = new ScXMLTableRowCellContext( GetScImport(),
123                                                       pAttribList, true, static_cast<SCROW>(nRepeatedRows)
124                                                       //this
125                                                       );
126         }
127         break;
128     }
129 
130     if( !pContext )
131         pContext = new SvXMLImportContext( GetImport() );
132 
133     return pContext;
134 }
135 
endFastElement(sal_Int32)136 void SAL_CALL ScXMLTableRowContext::endFastElement(sal_Int32 /*nElement*/)
137 {
138     ScXMLImport& rXMLImport(GetScImport());
139     ScDocument* pDoc(rXMLImport.GetDocument());
140     if (!bHasCell && nRepeatedRows > 1)
141     {
142         for (sal_Int32 i = 0; i < nRepeatedRows - 1; ++i) //one row is always added
143             GetScImport().GetTables().AddRow();
144         OSL_FAIL("it seems here is a nonvalid file; possible missing of table:table-cell element");
145     }
146     SCTAB nSheet = rXMLImport.GetTables().GetCurrentSheet();
147     sal_Int32 nCurrentRow(rXMLImport.GetTables().GetCurrentRow());
148     uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet());
149     if(xSheet.is())
150     {
151         sal_Int32 nFirstRow(nCurrentRow - nRepeatedRows + 1);
152         if (nFirstRow > pDoc->MaxRow())
153             nFirstRow = pDoc->MaxRow();
154         if (nCurrentRow > pDoc->MaxRow())
155             nCurrentRow = pDoc->MaxRow();
156         uno::Reference <table::XCellRange> xCellRange(xSheet->getCellRangeByPosition(0, nFirstRow, 0, nCurrentRow));
157         if (xCellRange.is())
158         {
159             uno::Reference<table::XColumnRowRange> xColumnRowRange (xCellRange, uno::UNO_QUERY);
160             if (xColumnRowRange.is())
161             {
162                 uno::Reference <beans::XPropertySet> xRowProperties(xColumnRowRange->getRows(), uno::UNO_QUERY);
163                 if (xRowProperties.is())
164                 {
165                     if (!sStyleName.isEmpty())
166                     {
167                         XMLTableStylesContext *pStyles(static_cast<XMLTableStylesContext *>(rXMLImport.GetAutoStyles()));
168                         if ( pStyles )
169                         {
170                             XMLTableStyleContext* pStyle(const_cast<XMLTableStyleContext*>(static_cast<const XMLTableStyleContext *>(pStyles->FindStyleChildContext(
171                                 XML_STYLE_FAMILY_TABLE_ROW, sStyleName, true))));
172                             if (pStyle)
173                             {
174                                 pStyle->FillPropertySet(xRowProperties);
175 
176                                 if ( nSheet != pStyle->GetLastSheet() )
177                                 {
178                                     ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(rXMLImport.GetModel())->GetSheetSaveData();
179                                     pSheetData->AddRowStyle( sStyleName, ScAddress( 0, static_cast<SCROW>(nFirstRow), nSheet ) );
180                                     pStyle->SetLastSheet(nSheet);
181                                 }
182                             }
183                         }
184                     }
185                     bool bVisible (true);
186                     bool bFiltered (false);
187                     if (IsXMLToken(sVisibility, XML_COLLAPSE))
188                     {
189                         bVisible = false;
190                     }
191                     else if (IsXMLToken(sVisibility, XML_FILTER))
192                     {
193                         bVisible = false;
194                         bFiltered = true;
195                     }
196                     if (!bVisible)
197                     {
198                         rXMLImport.GetDoc().setRowsVisible(nSheet, nFirstRow, nCurrentRow, false);
199                     }
200                     if (bFiltered)
201                         xRowProperties->setPropertyValue(SC_ISFILTERED, uno::makeAny(bFiltered));
202 
203                     uno::Any any = xRowProperties->getPropertyValue(SC_UNONAME_OHEIGHT);
204                     bool bOptionalHeight = false;
205                     any >>= bOptionalHeight;
206                     if (bOptionalHeight)
207                     {
208                         // Save this row for later height update
209                         std::vector<ScDocRowHeightUpdater::TabRanges>& rRecalcRanges = rXMLImport.GetRecalcRowRanges();
210                         while (static_cast<SCTAB>(rRecalcRanges.size()) <= nSheet)
211                         {
212                             rRecalcRanges.emplace_back(0);
213                         }
214                         rRecalcRanges.at(nSheet).mnTab = nSheet;
215                         rRecalcRanges.at(nSheet).maRanges.setTrue(nFirstRow, nCurrentRow);
216                     }
217                 }
218             }
219         }
220     }
221 }
222 
ScXMLTableRowsContext(ScXMLImport & rImport,const rtl::Reference<sax_fastparser::FastAttributeList> & rAttrList,const bool bTempHeader,const bool bTempGroup)223 ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport& rImport,
224                                       const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
225                                       const bool bTempHeader,
226                                       const bool bTempGroup ) :
227     ScXMLImportContext( rImport ),
228     nHeaderStartRow(0),
229     nGroupStartRow(0),
230     bHeader(bTempHeader),
231     bGroup(bTempGroup),
232     bGroupDisplay(true)
233 {
234     // don't have any attributes
235     if (bHeader)
236     {
237         ScAddress aAddr = rImport.GetTables().GetCurrentCellPos();
238         nHeaderStartRow = aAddr.Row();
239         ++nHeaderStartRow;
240     }
241     else if (bGroup)
242     {
243         nGroupStartRow = rImport.GetTables().GetCurrentRow();
244         ++nGroupStartRow;
245         if ( rAttrList.is() )
246         {
247             auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_DISPLAY ) ) );
248             if (aIter != rAttrList->end())
249                 bGroupDisplay = IsXMLToken( aIter, XML_TRUE );
250         }
251     }
252 }
253 
~ScXMLTableRowsContext()254 ScXMLTableRowsContext::~ScXMLTableRowsContext()
255 {
256 }
257 
258 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)259         ScXMLTableRowsContext::createFastChildContext( sal_Int32 nElement,
260         const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
261 {
262     SvXMLImportContext *pContext(nullptr);
263     sax_fastparser::FastAttributeList *pAttribList =
264         sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList );
265 
266     switch( nElement )
267     {
268     case XML_ELEMENT( TABLE, XML_TABLE_ROW_GROUP ):
269         pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
270                                                    false, true );
271         break;
272     case XML_ELEMENT( TABLE, XML_TABLE_HEADER_ROWS ):
273         pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
274                                                    true, false );
275         break;
276     case XML_ELEMENT( TABLE, XML_TABLE_ROWS ):
277         pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
278                                                    false, false );
279         break;
280     case XML_ELEMENT( TABLE, XML_TABLE_ROW ):
281         pContext = new ScXMLTableRowContext( GetScImport(), pAttribList );
282         break;
283     }
284 
285     if( !pContext )
286         pContext = new SvXMLImportContext( GetImport() );
287 
288     return pContext;
289 }
290 
endFastElement(sal_Int32)291 void SAL_CALL ScXMLTableRowsContext::endFastElement(sal_Int32 /*nElement*/)
292 {
293     ScXMLImport& rXMLImport(GetScImport());
294     if (bHeader)
295     {
296         SCROW nHeaderEndRow = rXMLImport.GetTables().GetCurrentRow();
297         if (nHeaderStartRow <= nHeaderEndRow)
298         {
299             uno::Reference <sheet::XPrintAreas> xPrintAreas (rXMLImport.GetTables().GetCurrentXSheet(), uno::UNO_QUERY);
300             if (xPrintAreas.is())
301             {
302                 if (!xPrintAreas->getPrintTitleRows())
303                 {
304                     xPrintAreas->setPrintTitleRows(true);
305                     table::CellRangeAddress aRowHeaderRange;
306                     aRowHeaderRange.StartRow = nHeaderStartRow;
307                     aRowHeaderRange.EndRow = nHeaderEndRow;
308                     xPrintAreas->setTitleRows(aRowHeaderRange);
309                 }
310                 else
311                 {
312                     table::CellRangeAddress aRowHeaderRange(xPrintAreas->getTitleRows());
313                     aRowHeaderRange.EndRow = nHeaderEndRow;
314                     xPrintAreas->setTitleRows(aRowHeaderRange);
315                 }
316             }
317         }
318     }
319     else if (bGroup)
320     {
321         SCROW nGroupEndRow = rXMLImport.GetTables().GetCurrentRow();
322         SCTAB nSheet(rXMLImport.GetTables().GetCurrentSheet());
323         if (nGroupStartRow <= nGroupEndRow)
324         {
325             ScDocument* pDoc(GetScImport().GetDocument());
326             if (pDoc)
327             {
328                 ScXMLImport::MutexGuard aGuard(GetScImport());
329                 ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(nSheet, true));
330                 ScOutlineArray& rRowArray(pOutlineTable->GetRowArray());
331                 bool bResized;
332                 rRowArray.Insert(nGroupStartRow, nGroupEndRow, bResized, !bGroupDisplay);
333             }
334         }
335     }
336 }
337 
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
339