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