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 <svl/style.hxx>
21 #include <svl/itemset.hxx>
22 #include <svl/whiter.hxx>
23 
24 #include <svx/svdoutl.hxx>
25 #include <editeng/xmlcnitm.hxx>
26 #include <svx/svdotext.hxx>
27 #include <svx/svdogrp.hxx>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/lrspitem.hxx>
30 #include <editeng/outlobj.hxx>
31 
32 #include <drawdoc.hxx>
33 #include "sdtransform.hxx"
34 
35 using namespace ::com::sun::star::style;
36 
37 class SdTransformOOo2xDocument
38 {
39 public:
40     explicit SdTransformOOo2xDocument( SdDrawDocument& rDocument );
41 
42     void transform();
43 
44     void transformMasterPages();
45     void transformDrawPages();
46 
47     void transformStyles();
48     void transformStyles( SfxStyleFamily eFam );
49     void transformStyle( SfxStyleSheetBase& rSheet );
50 
51     void transformShapes( SdrObjList const & rShapes );
52     void transformShape( SdrObject& rObj );
53 
54     void transformTextShape( SdrTextObj& rTextShape );
55 
56     bool getBulletState( const SfxItemSet& rSet, SfxStyleSheetBase* pSheet, bool& rState );
57     static bool getBulletState( const SfxItemSet& rSet, sal_uInt16 nWhich, bool& rState );
58 
59     static bool transformItemSet( SfxItemSet& rSet, bool bNumbering );
60 
61     static bool removeAlienAttributes( SfxItemSet& rSet );
62     static bool removeAlienAttributes( SfxItemSet& rSet, sal_uInt16 nWhich );
63 
64     SdDrawDocument& mrDocument;
65     SdrOutliner& mrOutliner;
66 };
67 
68 /** transforms the given model from OOo 2.x to OOo 3.x. This maps
69     the deprecated EE_PARA_BULLETSTATE and clears the EE_PARA_LRSPACE
70     if used together with a EE_PARA_NUMBULLET */
TransformOOo2xDocument(SdDrawDocument * pDocument)71 void TransformOOo2xDocument( SdDrawDocument* pDocument )
72 {
73     if( pDocument )
74     {
75         SdTransformOOo2xDocument aTransformer( *pDocument );
76         aTransformer.transform();
77     }
78 }
79 
80 static const OUStringLiteral gsEnableNumbering( "enable-numbering" );
81 static const OUStringLiteral gsTextNamespace( "urn:oasis:names:tc:opendocument:xmlns:text:1.0" );
82 static const OUStringLiteral gsTrue( "true" );
83 
SdTransformOOo2xDocument(SdDrawDocument & rDocument)84 SdTransformOOo2xDocument::SdTransformOOo2xDocument( SdDrawDocument& rDocument )
85 : mrDocument( rDocument )
86 , mrOutliner( rDocument.GetDrawOutliner() )
87 {
88 }
89 
transform()90 void SdTransformOOo2xDocument::transform()
91 {
92     transformMasterPages();
93     transformDrawPages();
94     transformStyles();
95 }
96 
transformMasterPages()97 void SdTransformOOo2xDocument::transformMasterPages()
98 {
99     sal_uInt16 nMasterPageCount = mrDocument.GetMasterPageCount();
100     for( sal_uInt16 nMasterPage = 0; nMasterPage < nMasterPageCount; nMasterPage++ )
101     {
102         SdrObjList* pPage = mrDocument.GetMasterPage( nMasterPage );
103         if( pPage )
104             transformShapes( *pPage );
105     }
106 }
107 
transformDrawPages()108 void SdTransformOOo2xDocument::transformDrawPages()
109 {
110     sal_uInt16 nPageCount = mrDocument.GetPageCount();
111     for( sal_uInt16 nPage = 0; nPage < nPageCount; nPage++ )
112     {
113         SdrObjList* pPage = mrDocument.GetPage( nPage );
114         if( pPage )
115             transformShapes( *pPage );
116     }
117 }
118 
transformStyles()119 void SdTransformOOo2xDocument::transformStyles()
120 {
121     transformStyles( SfxStyleFamily::Para );
122     transformStyles( SfxStyleFamily::Page );
123 }
124 
transformStyles(SfxStyleFamily eFam)125 void SdTransformOOo2xDocument::transformStyles( SfxStyleFamily eFam )
126 {
127 
128     rtl::Reference< SfxStyleSheetBasePool > xStyleSheetPool( mrDocument.GetStyleSheetPool() );
129 
130     SfxStyleSheetIterator aIter( xStyleSheetPool.get(), eFam );
131 
132     SfxStyleSheetBase* pSheet = aIter.First();
133     while( pSheet )
134     {
135         transformStyle( *pSheet );
136         pSheet = aIter.Next();
137     }
138 }
139 
transformStyle(SfxStyleSheetBase & rSheet)140 void SdTransformOOo2xDocument::transformStyle( SfxStyleSheetBase& rSheet )
141 {
142     SfxItemSet& rSet = rSheet.GetItemSet();
143 
144     bool bState = false;
145     getBulletState( rSheet.GetItemSet(), rSheet.GetPool()->Find( rSheet.GetParent(), rSheet.GetFamily() ), bState );
146 
147     transformItemSet( rSet, bState );
148     removeAlienAttributes( rSet );
149 }
150 
transformShapes(SdrObjList const & rShapes)151 void SdTransformOOo2xDocument::transformShapes( SdrObjList const & rShapes )
152 {
153     const size_t nShapeCount = rShapes.GetObjCount();
154     for( size_t nShape = 0; nShape < nShapeCount; ++nShape )
155     {
156         SdrObject* pObj = rShapes.GetObj( nShape );
157         if( pObj )
158             transformShape( *pObj );
159     }
160 }
161 
transformShape(SdrObject & rObj)162 void SdTransformOOo2xDocument::transformShape( SdrObject& rObj )
163 {
164     SdrTextObj* pTextShape = dynamic_cast< SdrTextObj* >( &rObj );
165     if( pTextShape )
166     {
167         transformTextShape( *pTextShape );
168         return;
169     }
170 
171     SdrObjGroup* pGroupShape = dynamic_cast< SdrObjGroup* >( &rObj );
172     if( pGroupShape )
173     {
174         SdrObjList* pObjList = pGroupShape->GetSubList();
175         if( pObjList )
176             transformShapes( *pObjList );
177         return;
178     }
179 }
180 
transformTextShape(SdrTextObj & rTextShape)181 void SdTransformOOo2xDocument::transformTextShape( SdrTextObj& rTextShape )
182 {
183 
184     if(rTextShape.IsEmptyPresObj())
185         return;
186 
187     OutlinerParaObject* pOPO = rTextShape.GetOutlinerParaObject();
188     if (!pOPO)
189         return;
190 
191     mrOutliner.SetText( *pOPO );
192 
193     sal_Int32 nCount = mrOutliner.GetParagraphCount();
194 
195     bool bChange = false;
196 
197     for(sal_Int32 nPara = 0; nPara < nCount; nPara++)
198     {
199         SfxItemSet aParaSet( mrOutliner.GetParaAttribs( nPara ) );
200 
201         bool bItemChange = false;
202 
203         bool bState = false;
204         const sal_Int16 nDepth = mrOutliner.GetDepth( nPara );
205         if( (nDepth != -1) && (!getBulletState( aParaSet, mrOutliner.GetStyleSheet( nPara ), bState ) || !bState) )
206         {
207             // disable bullet if text::enable-bullet="false" is found
208             if( (nDepth > 0 ) && (rTextShape.GetObjInventor()  == SdrInventor::Default) && (rTextShape.GetObjIdentifier() == OBJ_OUTLINETEXT) )
209             {
210                 // for outline object and level > 0 burn in the style sheet because it will be changed to "outline 1"
211                 SfxStyleSheet* pStyleSheet = mrOutliner.GetStyleSheet( nPara );
212 
213                 if( pStyleSheet )
214                 {
215                     // optimize me: only put items hard into paragraph that are not equal to "outline 1" style!
216                     SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
217 
218                     SfxWhichIter aIter(aParaSet);
219                     sal_uInt16 nWhich(aIter.FirstWhich());
220 
221                     // now set all none hard attributes from the style
222                     while(nWhich)
223                     {
224                         if(SfxItemState::SET != aParaSet.GetItemState(nWhich))
225                         {
226                             aParaSet.Put(rStyleSet.Get(nWhich));
227                             bItemChange = true;
228                         }
229 
230                         nWhich = aIter.NextWhich();
231                     }
232                 }
233             }
234 
235             mrOutliner.SetDepth( mrOutliner.GetParagraph( nPara ), -1 );
236 
237             bChange = true;
238         }
239 
240         bItemChange |= transformItemSet( aParaSet, bState );
241 
242         bItemChange |= removeAlienAttributes( aParaSet );
243 
244         if( bItemChange )
245         {
246             mrOutliner.SetParaAttribs( nPara, aParaSet );
247             bChange = true;
248         }
249     }
250 
251     if( bChange )
252         rTextShape.SetOutlinerParaObject(mrOutliner.CreateParaObject());
253 
254     mrOutliner.Clear();
255 }
256 
getBulletState(const SfxItemSet & rSet,SfxStyleSheetBase * pSheet,bool & rState)257 bool SdTransformOOo2xDocument::getBulletState( const SfxItemSet& rSet, SfxStyleSheetBase* pSheet, bool& rState )
258 {
259     if( getBulletState( rSet, EE_PARA_XMLATTRIBS, rState ) )
260         return true;
261 
262     if( getBulletState( rSet, SDRATTR_XMLATTRIBUTES, rState ) )
263         return true;
264 
265     if( pSheet && getBulletState( pSheet->GetItemSet(), pSheet->GetPool()->Find( pSheet->GetParent(), pSheet->GetFamily() ), rState ) )
266         return true;
267 
268     return false;
269 }
270 
getBulletState(const SfxItemSet & rSet,sal_uInt16 nWhich,bool & rState)271 bool SdTransformOOo2xDocument::getBulletState( const SfxItemSet& rSet, sal_uInt16 nWhich, bool& rState )
272 {
273     if( rSet.GetItemState( nWhich ) == SfxItemState::SET )
274     {
275         const SvXMLAttrContainerItem& rAttr = *rSet.GetItem<SvXMLAttrContainerItem>( nWhich );
276 
277         const sal_uInt16 nCount = rAttr.GetAttrCount();
278         for( sal_uInt16 nItem = 0; nItem < nCount; nItem++ )
279         {
280             if( ( rAttr.GetAttrLName( nItem ) == gsEnableNumbering ) && ( rAttr.GetAttrNamespace( nItem ) == gsTextNamespace ) )
281             {
282                 const OUString& sValue( rAttr.GetAttrValue( nItem ) );
283                 rState = sValue == gsTrue;
284                 return true;
285             }
286         }
287     }
288 
289     return false;
290 }
291 
transformItemSet(SfxItemSet & rSet,bool bNumbering)292 bool SdTransformOOo2xDocument::transformItemSet( SfxItemSet& rSet, bool bNumbering )
293 {
294     bool bRet = false;
295     if( bNumbering )
296     {
297         SvxLRSpaceItem aItem( *rSet.GetItem<SvxLRSpaceItem>( EE_PARA_LRSPACE ) );
298         if( (aItem.GetLeft() != 0) || (aItem.GetTextFirstLineOfst() != 0) )
299         {
300             aItem.SetLeftValue( 0 );
301             aItem.SetTextFirstLineOfst( 0 );
302             rSet.Put( aItem );
303             bRet = true;
304         }
305     }
306 
307     return bRet;
308 }
309 
removeAlienAttributes(SfxItemSet & rSet)310 bool SdTransformOOo2xDocument::removeAlienAttributes( SfxItemSet& rSet )
311 {
312     bool b = removeAlienAttributes( rSet, EE_PARA_XMLATTRIBS );
313     b |= removeAlienAttributes( rSet, SDRATTR_XMLATTRIBUTES );
314     return b;
315 }
316 
removeAlienAttributes(SfxItemSet & rSet,sal_uInt16 nWhich)317 bool SdTransformOOo2xDocument::removeAlienAttributes( SfxItemSet& rSet, sal_uInt16 nWhich )
318 {
319     if( rSet.GetItemState( nWhich ) == SfxItemState::SET )
320     {
321         const SvXMLAttrContainerItem& rAttr = *rSet.GetItem<SvXMLAttrContainerItem>( nWhich );
322 
323         const sal_uInt16 nCount = rAttr.GetAttrCount();
324         for( sal_uInt16 nItem = 0; nItem < nCount; nItem++ )
325         {
326             if( ( rAttr.GetAttrLName( nItem ) == gsEnableNumbering ) && ( rAttr.GetAttrNamespace( nItem ) == gsTextNamespace ) )
327             {
328                 if( nCount == 1 )
329                 {
330                     rSet.ClearItem( nWhich );
331                 }
332                 else
333                 {
334                     SvXMLAttrContainerItem aNewItem( nWhich );
335 
336                     const sal_uInt16 nFound = nItem;
337                     for( nItem = 0; nItem < nCount; nItem++ )
338                     {
339                         if( nItem != nFound )
340                         {
341                             OUString const& rNamespace(rAttr.GetAttrNamespace(nItem));
342                             OUString const& rPrefix(rAttr.GetAttrPrefix(nItem));
343                             if (rPrefix.isEmpty())
344                             {
345                                 aNewItem.AddAttr(rAttr.GetAttrLName(nItem), rAttr.GetAttrValue(nItem));
346                             }
347                             else
348                             {
349                                 aNewItem.AddAttr(rPrefix, rNamespace, rAttr.GetAttrLName(nItem), rAttr.GetAttrValue(nItem));
350                             }
351                         }
352                     }
353 
354                     rSet.Put( aNewItem );
355                 }
356                 return true;
357             }
358         }
359     }
360     return false;
361 }
362 
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
364