xref: /core/svx/source/xoutdev/xtable.cxx (revision 4f3c7aa921a097ceb4a5c680bb70e083c28cb04c)
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 <memory>
21 #include <utility>
22 #include <xmlxtexp.hxx>
23 #include <xmlxtimp.hxx>
24 #include <o3tl/safeint.hxx>
25 #include <osl/diagnose.h>
26 #include <tools/urlobj.hxx>
27 #include <svx/xtable.hxx>
28 #include <tools/debug.hxx>
29 #include <stack>
30 
31 using namespace com::sun::star;
32 
XColorEntry(const Color & rColor,const OUString & rName)33 XColorEntry::XColorEntry(const Color& rColor, const OUString& rName)
34 :   XPropertyEntry(rName),
35     m_aColor(rColor)
36 {
37 }
38 
Clone() const39 std::unique_ptr<XPropertyEntry> XColorEntry::Clone() const
40 {
41     return std::make_unique<XColorEntry>(m_aColor, GetName());
42 }
43 
XLineEndEntry(basegfx::B2DPolyPolygon _aB2DPolyPolygon,const OUString & rName)44 XLineEndEntry::XLineEndEntry(basegfx::B2DPolyPolygon _aB2DPolyPolygon, const OUString& rName)
45 :   XPropertyEntry(rName),
46     m_aB2DPolyPolygon(std::move(_aB2DPolyPolygon))
47 {
48 }
49 
XLineEndEntry(const XLineEndEntry & rOther)50 XLineEndEntry::XLineEndEntry(const XLineEndEntry& rOther)
51 :   XPropertyEntry(rOther),
52     m_aB2DPolyPolygon(rOther.m_aB2DPolyPolygon)
53 {
54 }
55 
Clone() const56 std::unique_ptr<XPropertyEntry> XLineEndEntry::Clone() const
57 {
58     return std::make_unique<XLineEndEntry>(*this);
59 }
60 
XDashEntry(const XDash & rDash,const OUString & rName)61 XDashEntry::XDashEntry(const XDash& rDash, const OUString& rName)
62 :   XPropertyEntry(rName),
63     m_aDash(rDash)
64 {
65 }
66 
XDashEntry(const XDashEntry & rOther)67 XDashEntry::XDashEntry(const XDashEntry& rOther)
68 :   XPropertyEntry(rOther),
69 m_aDash(rOther.m_aDash)
70 {
71 }
72 
Clone() const73 std::unique_ptr<XPropertyEntry> XDashEntry::Clone() const
74 {
75     return std::make_unique<XDashEntry>(*this);
76 }
77 
XHatchEntry(const XHatch & rHatch,const OUString & rName)78 XHatchEntry::XHatchEntry(const XHatch& rHatch, const OUString& rName)
79 :   XPropertyEntry(rName),
80     m_aHatch(rHatch)
81 {
82 }
83 
XHatchEntry(const XHatchEntry & rOther)84 XHatchEntry::XHatchEntry(const XHatchEntry& rOther)
85 :   XPropertyEntry(rOther),
86     m_aHatch(rOther.m_aHatch)
87 {
88 }
89 
Clone() const90 std::unique_ptr<XPropertyEntry> XHatchEntry::Clone() const
91 {
92     return std::make_unique<XHatchEntry>(*this);
93 }
94 
XGradientEntry(const basegfx::BGradient & rGradient,const OUString & rName)95 XGradientEntry::XGradientEntry(const basegfx::BGradient& rGradient, const OUString& rName)
96 :   XPropertyEntry(rName),
97     m_aGradient(rGradient)
98 {
99 }
100 
XGradientEntry(const XGradientEntry & rOther)101 XGradientEntry::XGradientEntry(const XGradientEntry& rOther)
102 :   XPropertyEntry(rOther),
103     m_aGradient(rOther.m_aGradient)
104 {
105 }
106 
Clone() const107 std::unique_ptr<XPropertyEntry> XGradientEntry::Clone() const
108 {
109     return std::make_unique<XGradientEntry>(*this);
110 }
111 
XBitmapEntry(const GraphicObject & rGraphicObject,const OUString & rName)112 XBitmapEntry::XBitmapEntry(const GraphicObject& rGraphicObject, const OUString& rName)
113 :   XPropertyEntry(rName),
114     maGraphicObject(rGraphicObject)
115 {
116 }
117 
XBitmapEntry(const XBitmapEntry & rOther)118 XBitmapEntry::XBitmapEntry(const XBitmapEntry& rOther)
119 :   XPropertyEntry(rOther),
120     maGraphicObject(rOther.maGraphicObject)
121 {
122 }
123 
Clone() const124 std::unique_ptr<XPropertyEntry> XBitmapEntry::Clone() const
125 {
126     return std::make_unique<XBitmapEntry>(*this);
127 }
128 
XPropertyList(XPropertyListType type,OUString aPath,OUString aReferer)129 XPropertyList::XPropertyList(
130     XPropertyListType type,
131     OUString aPath, OUString aReferer
132 ) : meType           ( type ),
133     maName           ( u"standard"_ustr ),
134     maPath           (std::move( aPath )),
135     maReferer        (std::move( aReferer )),
136     mbListDirty      ( true ),
137     mbEmbedInDocument( false )
138     , mbNeedsExportableList(false)
139 {
140 //    fprintf (stderr, "Create type %d count %d\n", (int)meType, count++);
141 }
142 
isValidIdx(tools::Long nIndex) const143 bool XPropertyList::isValidIdx(tools::Long nIndex) const
144 {
145     return (nIndex >= 0 && o3tl::make_unsigned(nIndex) < maList.size());
146 }
147 
148 
~XPropertyList()149 XPropertyList::~XPropertyList()
150 {
151 }
152 
Count() const153 tools::Long XPropertyList::Count() const
154 {
155     if( mbListDirty )
156     {
157         if( !const_cast<XPropertyList*>(this)->Load() )
158             const_cast<XPropertyList*>(this)->Create();
159     }
160     return maList.size();
161 }
162 
Get(tools::Long nIndex) const163 XPropertyEntry* XPropertyList::Get( tools::Long nIndex ) const
164 {
165     if( mbListDirty )
166     {
167         if( !const_cast<XPropertyList*>(this)->Load() )
168             const_cast<XPropertyList*>(this)->Create();
169     }
170     if (!isValidIdx(nIndex))
171         return nullptr;
172 
173     return maList[nIndex].get();
174 }
175 
GetIndex(std::u16string_view rName) const176 tools::Long XPropertyList::GetIndex(std::u16string_view rName) const
177 {
178     if( mbListDirty )
179     {
180         if( !const_cast<XPropertyList*>(this)->Load() )
181             const_cast<XPropertyList*>(this)->Create();
182     }
183 
184     for( tools::Long i = 0, n = maList.size(); i < n; ++i ) {
185         if (rName == maList[ i ]->GetName()) {
186             return i;
187         }
188     }
189     return -1;
190 }
191 
GetUiBitmap(tools::Long nIndex) const192 Bitmap XPropertyList::GetUiBitmap( tools::Long nIndex ) const
193 {
194     Bitmap aRetval;
195     if (!isValidIdx(nIndex))
196         return aRetval;
197 
198     XPropertyEntry* pEntry = maList[nIndex].get();
199     aRetval = pEntry->GetUiBitmap();
200 
201     if(aRetval.IsEmpty())
202     {
203         aRetval = const_cast< XPropertyList* >(this)->CreateBitmapForUI(nIndex);
204         pEntry->SetUiBitmap(aRetval);
205     }
206     return aRetval;
207 }
208 
Insert(std::unique_ptr<XPropertyEntry> pEntry,tools::Long nIndex)209 void XPropertyList::Insert(std::unique_ptr<XPropertyEntry> pEntry, tools::Long nIndex)
210 {
211     if (!pEntry)
212     {
213         assert(!"empty XPropertyEntry not allowed in XPropertyList");
214         return;
215     }
216 
217     if (!pEntry->GetSavingAllowed())
218         mbNeedsExportableList = true;
219 
220     if (isValidIdx(nIndex)) {
221         maList.insert( maList.begin()+nIndex, std::move(pEntry) );
222     } else {
223         maList.push_back( std::move(pEntry) );
224     }
225 }
226 
Replace(std::unique_ptr<XPropertyEntry> pEntry,tools::Long nIndex)227 void XPropertyList::Replace(std::unique_ptr<XPropertyEntry> pEntry, tools::Long nIndex)
228 {
229     if (!pEntry)
230     {
231         assert(!"empty XPropertyEntry not allowed in XPropertyList");
232         return;
233     }
234     if (!isValidIdx(nIndex))
235     {
236         assert(!"trying to replace invalid entry in XPropertyList");
237         return;
238     }
239 
240     maList[nIndex] = std::move(pEntry);
241 }
242 
Remove(tools::Long nIndex)243 void XPropertyList::Remove(tools::Long nIndex)
244 {
245     if (!isValidIdx(nIndex))
246     {
247         assert(!"trying to remove invalid entry in XPropertyList");
248         return;
249     }
250 
251     maList.erase(maList.begin() + nIndex);
252 }
253 
SetName(const OUString & rString)254 void XPropertyList::SetName( const OUString& rString )
255 {
256     if(!rString.isEmpty())
257     {
258         maName = rString;
259     }
260 }
261 
Load()262 bool XPropertyList::Load()
263 {
264     if( mbListDirty )
265     {
266         mbListDirty = false;
267         std::stack<OUString> aDirs;
268 
269         sal_Int32 nIndex = 0;
270         do
271         {
272             aDirs.push(maPath.getToken(0, ';', nIndex));
273         }
274         while (nIndex >= 0);
275 
276         //try all entries palette path list working back to front until one
277         //succeeds
278         while (!aDirs.empty())
279         {
280             OUString aPath(aDirs.top());
281             aDirs.pop();
282 
283             INetURLObject aURL(aPath);
284 
285             if( INetProtocol::NotValid == aURL.GetProtocol() )
286             {
287                 DBG_ASSERT( aPath.isEmpty(), "invalid URL" );
288                 return false;
289             }
290 
291             aURL.Append( maName );
292 
293             if( aURL.getExtension().isEmpty() )
294                 aURL.setExtension( GetDefaultExt() );
295 
296             bool bRet = SvxXMLXTableImport::load(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
297                                              maReferer, uno::Reference < embed::XStorage >(),
298                                              createInstance(), nullptr );
299             if (bRet)
300                 return bRet;
301         }
302     }
303     return false;
304 }
305 
LoadFrom(const uno::Reference<embed::XStorage> & xStorage,const OUString & rURL,const OUString & rReferer)306 bool XPropertyList::LoadFrom( const uno::Reference < embed::XStorage > &xStorage,
307                               const OUString &rURL, const OUString &rReferer )
308 {
309     if( !mbListDirty )
310         return false;
311     mbListDirty = false;
312     return SvxXMLXTableImport::load( rURL, rReferer, xStorage, createInstance(), &mbEmbedInDocument );
313 }
314 
Save()315 bool XPropertyList::Save()
316 {
317     //save to the last path in the palette path list
318     OUString aLastDir;
319     sal_Int32 nIndex = 0;
320     do
321     {
322         aLastDir = maPath.getToken(0, ';', nIndex);
323     }
324     while (nIndex >= 0);
325 
326     INetURLObject aURL(aLastDir);
327 
328     if( INetProtocol::NotValid == aURL.GetProtocol() )
329     {
330         DBG_ASSERT( aLastDir.isEmpty(), "invalid URL" );
331         return false;
332     }
333 
334     aURL.Append( maName );
335 
336     if( aURL.getExtension().isEmpty() )
337         aURL.setExtension( GetDefaultExt() );
338 
339     XPropertyListRef rExportableList = CreatePropertyList(meType, maPath, "");
340     if (mbNeedsExportableList)
341     {
342         rExportableList->SetName(maName);
343         rExportableList->SetDirty(mbListDirty);
344         bool bHasUnsaveableEntry = false;
345         for (const std::unique_ptr<XPropertyEntry>& rEntry : maList)
346         {
347             if (rEntry->GetSavingAllowed())
348                 rExportableList->Insert(rEntry->Clone());
349             else
350                 bHasUnsaveableEntry = true;
351         }
352         if (!bHasUnsaveableEntry)
353             mbNeedsExportableList = false;
354     }
355     css::uno::Reference<css::container::XNameContainer> xExportableNameContainer
356         = mbNeedsExportableList ? rExportableList->createInstance() : createInstance();
357 
358     return SvxXMLXTableExportComponent::save( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
359                                               xExportableNameContainer,
360                                               uno::Reference< embed::XStorage >(), nullptr );
361 }
362 
SaveTo(const uno::Reference<embed::XStorage> & xStorage,const OUString & rURL,OUString * pOptName)363 bool XPropertyList::SaveTo( const uno::Reference< embed::XStorage > &xStorage,
364                             const OUString &rURL, OUString *pOptName )
365 {
366     return SvxXMLXTableExportComponent::save( rURL, createInstance(), xStorage, pOptName );
367 }
368 
CreatePropertyList(XPropertyListType aType,const OUString & rPath,const OUString & rReferer)369 XPropertyListRef XPropertyList::CreatePropertyList( XPropertyListType aType,
370                                                     const OUString& rPath,
371                                                     const OUString& rReferer )
372 {
373     XPropertyListRef pRet;
374 
375     switch (aType) {
376         case XPropertyListType::Color:
377             pRet = XPropertyListRef(new XColorList(rPath, rReferer));
378             break;
379         case XPropertyListType::LineEnd:
380             pRet = XPropertyListRef(new XLineEndList(rPath, rReferer));
381             break;
382         case XPropertyListType::Dash:
383             pRet = XPropertyListRef(new XDashList(rPath, rReferer));
384             break;
385         case XPropertyListType::Hatch:
386             pRet = XPropertyListRef(new XHatchList(rPath, rReferer));
387             break;
388         case XPropertyListType::Gradient:
389             pRet = XPropertyListRef(new XGradientList(rPath, rReferer));
390             break;
391         case XPropertyListType::Bitmap:
392             pRet = XPropertyListRef(new XBitmapList(rPath, rReferer));
393             break;
394         case XPropertyListType::Pattern:
395             pRet = XPropertyListRef(new XPatternList(rPath, rReferer));
396             break;
397     default:
398         OSL_FAIL("unknown xproperty type");
399         break;
400     }
401     OSL_ASSERT( !pRet.is() || pRet->meType == aType );
402 
403     return pRet;
404 }
405 
406 XPropertyListRef
CreatePropertyListFromURL(XPropertyListType t,std::u16string_view rURLStr)407 XPropertyList::CreatePropertyListFromURL( XPropertyListType t,
408                                           std::u16string_view rURLStr )
409 {
410     INetURLObject aURL( rURLStr );
411     INetURLObject aPathURL( aURL );
412 
413     aPathURL.removeSegment();
414     aPathURL.removeFinalSlash();
415 
416     XPropertyListRef pList = XPropertyList::CreatePropertyList(
417         t, aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), u""_ustr );
418     pList->SetName( aURL.getName() );
419 
420     return pList;
421 }
422 
423 struct {
424     XPropertyListType t;
425     OUString aExt;
426 } constexpr pExtnMap[] = {
427     { XPropertyListType::Color,    u"soc"_ustr },
428     { XPropertyListType::LineEnd, u"soe"_ustr },
429     { XPropertyListType::Dash,     u"sod"_ustr },
430     { XPropertyListType::Hatch,    u"soh"_ustr },
431     { XPropertyListType::Gradient, u"sog"_ustr },
432     { XPropertyListType::Bitmap,   u"sob"_ustr },
433     { XPropertyListType::Pattern,  u"sop"_ustr}
434 };
435 
GetDefaultExt(XPropertyListType t)436 OUString XPropertyList::GetDefaultExt( XPropertyListType t )
437 {
438     for (const auto & i : pExtnMap)
439     {
440         if( i.t == t )
441             return i.aExt;
442     }
443     return OUString();
444 }
445 
446 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
447