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 "xmlcoli.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlstyli.hxx"
23 #include <document.hxx>
24 #include <docuno.hxx>
25 #include <olinetab.hxx>
26 #include <sheetdata.hxx>
27 #include <unonames.hxx>
28 
29 #include <xmloff/xmlnamespace.hxx>
30 #include <xmloff/families.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include <com/sun/star/sheet/XSpreadsheet.hpp>
33 #include <com/sun/star/table/XColumnRowRange.hpp>
34 #include <com/sun/star/sheet/XPrintAreas.hpp>
35 #include <comphelper/servicehelper.hxx>
36 
37 using namespace com::sun::star;
38 using namespace xmloff::token;
39 
ScXMLTableColContext(ScXMLImport & rImport,const rtl::Reference<sax_fastparser::FastAttributeList> & rAttrList)40 ScXMLTableColContext::ScXMLTableColContext( ScXMLImport& rImport,
41                                       const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList ) :
42     ScXMLImportContext( rImport ),
43     nColCount(1),
44     sVisibility(GetXMLToken(XML_VISIBLE))
45 {
46     if ( !rAttrList.is() )
47         return;
48 
49     for (auto &aIter : *rAttrList)
50     {
51         switch (aIter.getToken())
52         {
53         case XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ):
54             {
55                 nColCount = std::max<sal_Int32>(aIter.toInt32(), 1);
56                 nColCount = std::min<sal_Int32>(nColCount, MAXCOLCOUNT);
57             }
58             break;
59         case XML_ELEMENT( TABLE, XML_STYLE_NAME ):
60             {
61                 sStyleName = aIter.toString();
62             }
63             break;
64         case XML_ELEMENT( TABLE, XML_VISIBILITY ):
65             {
66                 sVisibility = aIter.toString();
67             }
68             break;
69         case XML_ELEMENT( TABLE, XML_DEFAULT_CELL_STYLE_NAME ):
70             {
71                 sCellStyleName = aIter.toString();
72             }
73             break;
74         }
75     }
76 }
77 
~ScXMLTableColContext()78 ScXMLTableColContext::~ScXMLTableColContext()
79 {
80 }
81 
endFastElement(sal_Int32)82 void SAL_CALL ScXMLTableColContext::endFastElement( sal_Int32 /*nElement*/ )
83 {
84     ScXMLImport& rXMLImport = GetScImport();
85     ScDocument* pDoc = rXMLImport.GetDocument();
86     SCTAB nSheet = rXMLImport.GetTables().GetCurrentSheet();
87     sal_Int32 nCurrentColumn = rXMLImport.GetTables().GetCurrentColCount();
88     uno::Reference<sheet::XSpreadsheet> xSheet(rXMLImport.GetTables().GetCurrentXSheet());
89     if(xSheet.is())
90     {
91         sal_Int32 nLastColumn(nCurrentColumn + nColCount - 1);
92         if (nLastColumn > pDoc->MaxCol())
93             nLastColumn = pDoc->MaxCol();
94         if (nCurrentColumn > pDoc->MaxCol())
95             nCurrentColumn = pDoc->MaxCol();
96         pDoc->CreateColumnIfNotExists(nSheet, nLastColumn);
97         uno::Reference<table::XColumnRowRange> xColumnRowRange (xSheet->getCellRangeByPosition(nCurrentColumn, 0, nLastColumn, 0), uno::UNO_QUERY);
98         if (xColumnRowRange.is())
99         {
100             uno::Reference <beans::XPropertySet> xColumnProperties(xColumnRowRange->getColumns(), uno::UNO_QUERY);
101             if (xColumnProperties.is())
102             {
103                 if (!sStyleName.isEmpty())
104                 {
105                     XMLTableStylesContext *pStyles = static_cast<XMLTableStylesContext *>(rXMLImport.GetAutoStyles());
106                     if ( pStyles )
107                     {
108                         XMLTableStyleContext* pStyle = const_cast<XMLTableStyleContext*>(static_cast<const XMLTableStyleContext *>(pStyles->FindStyleChildContext(
109                             XmlStyleFamily::TABLE_COLUMN, sStyleName, true)));
110                         if (pStyle)
111                         {
112                             pStyle->FillPropertySet(xColumnProperties);
113 
114                             if ( nSheet != pStyle->GetLastSheet() )
115                             {
116                                 ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(rXMLImport.GetModel())->GetSheetSaveData();
117                                 pSheetData->AddColumnStyle( sStyleName, ScAddress( static_cast<SCCOL>(nCurrentColumn), 0, nSheet ) );
118                                 pStyle->SetLastSheet(nSheet);
119                             }
120                         }
121                     }
122                 }
123                 bool bValue(true);
124                 if (!IsXMLToken(sVisibility, XML_VISIBLE))
125                     bValue = false;
126                 xColumnProperties->setPropertyValue(SC_UNONAME_CELLVIS, uno::makeAny(bValue));
127             }
128         }
129     }
130 
131     // #i57915# ScXMLImport::SetStyleToRange can't handle empty style names.
132     // The default for a column if there is no attribute is the style "Default" (programmatic API name).
133     if ( sCellStyleName.isEmpty() )
134         sCellStyleName = "Default";
135 
136     GetScImport().GetTables().AddColStyle(nColCount, sCellStyleName);
137 }
138 
ScXMLTableColsContext(ScXMLImport & rImport,const rtl::Reference<sax_fastparser::FastAttributeList> & rAttrList,const bool bTempHeader,const bool bTempGroup)139 ScXMLTableColsContext::ScXMLTableColsContext( ScXMLImport& rImport,
140                                       const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
141                                       const bool bTempHeader, const bool bTempGroup) :
142     ScXMLImportContext( rImport ),
143     nHeaderStartCol(0),
144     nHeaderEndCol(0),
145     nGroupStartCol(0),
146     nGroupEndCol(0),
147     bHeader(bTempHeader),
148     bGroup(bTempGroup),
149     bGroupDisplay(true)
150 {
151     // don't have any attributes
152     if (bHeader)
153         nHeaderStartCol = rImport.GetTables().GetCurrentColCount();
154     else if (bGroup)
155     {
156         nGroupStartCol = rImport.GetTables().GetCurrentColCount();
157         if ( rAttrList.is() )
158         {
159             auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_DISPLAY ) ) );
160             if ( aIter != rAttrList->end() && IsXMLToken(aIter, XML_FALSE) )
161                 bGroupDisplay = false;
162         }
163     }
164 }
165 
~ScXMLTableColsContext()166 ScXMLTableColsContext::~ScXMLTableColsContext()
167 {
168 }
169 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)170 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLTableColsContext::createFastChildContext(
171     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
172 {
173     SvXMLImportContext *pContext = nullptr;
174     sax_fastparser::FastAttributeList *pAttribList =
175         &sax_fastparser::castToFastAttributeList( xAttrList );
176 
177     switch (nElement)
178     {
179     case XML_ELEMENT( TABLE, XML_TABLE_COLUMN_GROUP ):
180         pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
181                                                    false, true );
182         break;
183     case XML_ELEMENT( TABLE, XML_TABLE_HEADER_COLUMNS ):
184         pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
185                                                    true, false );
186         break;
187     case XML_ELEMENT( TABLE, XML_TABLE_COLUMNS ):
188         pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
189                                                    false, false );
190         break;
191     case XML_ELEMENT( TABLE, XML_TABLE_COLUMN ):
192         pContext = new ScXMLTableColContext( GetScImport(), pAttribList );
193         break;
194     }
195 
196     return pContext;
197 }
198 
endFastElement(sal_Int32)199 void SAL_CALL ScXMLTableColsContext::endFastElement( sal_Int32 /*nElement*/ )
200 {
201     ScXMLImport& rXMLImport = GetScImport();
202     if (bHeader)
203     {
204         nHeaderEndCol = rXMLImport.GetTables().GetCurrentColCount();
205         nHeaderEndCol--;
206         if (nHeaderStartCol <= nHeaderEndCol)
207         {
208             uno::Reference <sheet::XPrintAreas> xPrintAreas (rXMLImport.GetTables().GetCurrentXSheet(), uno::UNO_QUERY);
209             if (xPrintAreas.is())
210             {
211                 if (!xPrintAreas->getPrintTitleColumns())
212                 {
213                     xPrintAreas->setPrintTitleColumns(true);
214                     table::CellRangeAddress aColumnHeaderRange;
215                     aColumnHeaderRange.StartColumn = nHeaderStartCol;
216                     aColumnHeaderRange.EndColumn = nHeaderEndCol;
217                     xPrintAreas->setTitleColumns(aColumnHeaderRange);
218                 }
219                 else
220                 {
221                     table::CellRangeAddress aColumnHeaderRange(xPrintAreas->getTitleColumns());
222                     aColumnHeaderRange.EndColumn = nHeaderEndCol;
223                     xPrintAreas->setTitleColumns(aColumnHeaderRange);
224                 }
225             }
226         }
227     }
228     else if (bGroup)
229     {
230         SCTAB nSheet = rXMLImport.GetTables().GetCurrentSheet();
231         nGroupEndCol = rXMLImport.GetTables().GetCurrentColCount();
232         nGroupEndCol--;
233         if (nGroupStartCol <= nGroupEndCol)
234         {
235             ScDocument* pDoc = GetScImport().GetDocument();
236             if (pDoc)
237             {
238                 ScXMLImport::MutexGuard aGuard(GetScImport());
239                 ScOutlineTable* pOutlineTable = pDoc->GetOutlineTable(nSheet, true);
240                 if (pOutlineTable)
241                 {
242                     ScOutlineArray& rColArray = pOutlineTable->GetColArray();
243                     bool bResized;
244                     rColArray.Insert(static_cast<SCCOL>(nGroupStartCol), static_cast<SCCOL>(nGroupEndCol), bResized, !bGroupDisplay);
245                 }
246             }
247         }
248     }
249 }
250 
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
252