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 <config_folders.h>
21
22 #include <sal/config.h>
23 #include <sal/log.hxx>
24
25 #include <deque>
26 #include <string_view>
27
28 #include <com/sun/star/container/XNameAccess.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
31 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
32 #include <com/sun/star/uno/Exception.hpp>
33 #include <com/sun/star/uno/RuntimeException.hpp>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <comphelper/processfactory.hxx>
36 #include <cppuhelper/implbase.hxx>
37 #include <osl/file.hxx>
38 #include <osl/diagnose.h>
39 #include <osl/process.h>
40 #include <rtl/bootstrap.hxx>
41 #include <rtl/uri.hxx>
42
43 #include <tools/diagnose_ex.h>
44 #include <tools/stream.hxx>
45 #include <tools/urlobj.hxx>
46 #include <implimagetree.hxx>
47
48 #include <vcl/bitmapex.hxx>
49 #include <vcl/dibtools.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/BitmapTools.hxx>
53 #include <IconThemeScanner.hxx>
54 #include <vcl/filter/PngImageReader.hxx>
55 #include <vcl/outdev.hxx>
56 #include <vcl/pngwrite.hxx>
57
58 #include <bitmap/BitmapLightenFilter.hxx>
59
60 using namespace css;
61
convertToDarkTheme()62 bool ImageRequestParameters::convertToDarkTheme()
63 {
64 static bool bIconsForDarkTheme = !!getenv("VCL_ICONS_FOR_DARK_THEME");
65
66 bool bConvertToDarkTheme = false;
67 if (!(meFlags & ImageLoadFlags::IgnoreDarkTheme))
68 bConvertToDarkTheme = bIconsForDarkTheme;
69
70 return bConvertToDarkTheme;
71 }
72
scalePercentage()73 sal_Int32 ImageRequestParameters::scalePercentage()
74 {
75 sal_Int32 aScalePercentage = 100;
76 if (!(meFlags & ImageLoadFlags::IgnoreScalingFactor))
77 aScalePercentage = Application::GetDefaultDevice()->GetDPIScalePercentage();
78 else if (mnScalePercentage > 0)
79 aScalePercentage = mnScalePercentage;
80 return aScalePercentage;
81 }
82
83 namespace
84 {
85
convertLcTo32Path(OUString const & rPath)86 OUString convertLcTo32Path(OUString const & rPath)
87 {
88 OUString aResult;
89 if (rPath.lastIndexOf('/') != -1)
90 {
91 sal_Int32 nCopyFrom = rPath.lastIndexOf('/') + 1;
92 OUString sFile = rPath.copy(nCopyFrom);
93 OUString sDir = rPath.copy(0, rPath.lastIndexOf('/'));
94 if (!sFile.isEmpty() && sFile.startsWith("lc_"))
95 {
96 aResult = sDir + "/32/" + sFile.subView(3);
97 }
98 }
99 return aResult;
100 }
101
createPath(std::u16string_view name,sal_Int32 pos,std::u16string_view locale)102 OUString createPath(std::u16string_view name, sal_Int32 pos, std::u16string_view locale)
103 {
104 return OUString::Concat(name.substr(0, pos + 1)) + locale + name.substr(pos);
105 }
106
getIconCacheUrl(std::u16string_view sVariant,ImageRequestParameters const & rParameters)107 OUString getIconCacheUrl(std::u16string_view sVariant, ImageRequestParameters const & rParameters)
108 {
109 OUString sUrl = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/"
110 + rParameters.msStyle + "/" + sVariant + "/" + rParameters.msName;
111 rtl::Bootstrap::expandMacros(sUrl);
112 return sUrl;
113 }
114
createIconCacheUrl(std::u16string_view sVariant,ImageRequestParameters const & rParameters)115 OUString createIconCacheUrl(
116 std::u16string_view sVariant, ImageRequestParameters const & rParameters)
117 {
118 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
119 OUString sDir = sUrl.copy(0, sUrl.lastIndexOf('/'));
120 osl::Directory::createPath(sDir);
121 return sUrl;
122 }
123
urlExists(OUString const & sUrl)124 bool urlExists(OUString const & sUrl)
125 {
126 osl::File aFile(sUrl);
127 osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read);
128 return osl::FileBase::E_None == eRC;
129 }
130
getNameNoExtension(OUString const & sName)131 OUString getNameNoExtension(OUString const & sName)
132 {
133 sal_Int32 nDotPosition = sName.lastIndexOf('.');
134 return sName.copy(0, nDotPosition);
135 }
136
wrapStream(uno::Reference<io::XInputStream> const & rInputStream)137 std::shared_ptr<SvMemoryStream> wrapStream(uno::Reference<io::XInputStream> const & rInputStream)
138 {
139 // This could use SvInputStream instead if that did not have a broken
140 // SeekPos implementation for an XInputStream that is not also XSeekable
141 // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
142 // l. 593):
143 OSL_ASSERT(rInputStream.is());
144 std::shared_ptr<SvMemoryStream> aMemoryStream(std::make_shared<SvMemoryStream>());
145 for (;;)
146 {
147 const sal_Int32 nSize(2048);
148 uno::Sequence<sal_Int8> aData(nSize);
149 sal_Int32 nRead = rInputStream->readBytes(aData, nSize);
150 aMemoryStream->WriteBytes(aData.getConstArray(), nRead);
151 if (nRead < nSize)
152 break;
153 }
154 aMemoryStream->Seek(0);
155 rInputStream->closeInput();
156 return aMemoryStream;
157 }
158
loadImageFromStream(std::shared_ptr<SvStream> const & xStream,OUString const & rPath,ImageRequestParameters & rParameters)159 void loadImageFromStream(std::shared_ptr<SvStream> const & xStream, OUString const & rPath, ImageRequestParameters& rParameters)
160 {
161 bool bConvertToDarkTheme = rParameters.convertToDarkTheme();
162 sal_Int32 aScalePercentage = rParameters.scalePercentage();
163
164 if (rPath.endsWith(".png"))
165 {
166 vcl::PngImageReader aPNGReader(*xStream);
167 aPNGReader.read(rParameters.mrBitmap);
168 }
169 else if (rPath.endsWith(".svg"))
170 {
171 rParameters.mbWriteImageToCache = true; // We always want to cache a SVG image
172 vcl::bitmap::loadFromSvg(*xStream, rPath, rParameters.mrBitmap, aScalePercentage / 100.0);
173
174 if (bConvertToDarkTheme)
175 BitmapFilter::Filter(rParameters.mrBitmap, BitmapLightenFilter());
176
177 return;
178 }
179 else
180 {
181 ReadDIBBitmapEx(rParameters.mrBitmap, *xStream);
182 }
183
184 if (bConvertToDarkTheme)
185 {
186 rParameters.mbWriteImageToCache = true; // Cache the dark variant
187 BitmapFilter::Filter(rParameters.mrBitmap, BitmapLightenFilter());
188 }
189
190 if (aScalePercentage > 100)
191 {
192 rParameters.mbWriteImageToCache = true; // Cache the scaled variant
193 double aScaleFactor(aScalePercentage / 100.0);
194 // when scaling use the full 24bit RGB values
195 rParameters.mrBitmap.Convert(BmpConversion::N24Bit);
196 rParameters.mrBitmap.Scale(aScaleFactor, aScaleFactor, BmpScaleFlag::Fast);
197 }
198 }
199
200 } // end anonymous namespace
201
ImplImageTree()202 ImplImageTree::ImplImageTree()
203 {
204 }
205
~ImplImageTree()206 ImplImageTree::~ImplImageTree()
207 {
208 }
209
getPaths(OUString const & name,LanguageTag const & rLanguageTag)210 std::vector<OUString> ImplImageTree::getPaths(OUString const & name, LanguageTag const & rLanguageTag)
211 {
212 std::vector<OUString> sPaths;
213
214 sal_Int32 pos = name.lastIndexOf('/');
215 if (pos != -1)
216 {
217 for (const OUString& rFallback : rLanguageTag.getFallbackStrings(true))
218 {
219 OUString aFallbackName = getNameNoExtension(getRealImageName(createPath(name, pos, rFallback)));
220 sPaths.emplace_back(aFallbackName + ".png");
221 sPaths.emplace_back(aFallbackName + ".svg");
222 }
223 }
224
225 OUString aRealName = getNameNoExtension(getRealImageName(name));
226 sPaths.emplace_back(aRealName + ".png");
227 sPaths.emplace_back(aRealName + ".svg");
228
229 return sPaths;
230 }
231
getImageUrl(OUString const & rName,OUString const & rStyle,OUString const & rLang)232 OUString ImplImageTree::getImageUrl(OUString const & rName, OUString const & rStyle, OUString const & rLang)
233 {
234 OUString aStyle(rStyle);
235
236 while (!aStyle.isEmpty())
237 {
238 try
239 {
240 setStyle(aStyle);
241
242 if (checkPathAccess())
243 {
244 IconSet& rIconSet = getCurrentIconSet();
245 const uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.maNameAccess;
246
247 LanguageTag aLanguageTag(rLang);
248
249 for (const OUString& rPath: getPaths(rName, aLanguageTag))
250 {
251 if (rNameAccess->hasByName(rPath))
252 {
253 return "vnd.sun.star.zip://"
254 + rtl::Uri::encode(rIconSet.maURL, rtl_UriCharClassRegName,
255 rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8)
256 + "/" + rPath;
257 }
258 }
259 }
260 }
261 catch (const uno::Exception &)
262 {
263 TOOLS_INFO_EXCEPTION("vcl", "");
264 }
265
266 aStyle = fallbackStyle(aStyle);
267 }
268 return OUString();
269 }
270
getImageStream(OUString const & rName,OUString const & rStyle,OUString const & rLang)271 std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
272 {
273 OUString aStyle(rStyle);
274
275 while (!aStyle.isEmpty())
276 {
277 try
278 {
279 setStyle(aStyle);
280
281 if (checkPathAccess())
282 {
283 IconSet& rIconSet = getCurrentIconSet();
284 const uno::Reference<container::XNameAccess>& rNameAccess = rIconSet.maNameAccess;
285
286 LanguageTag aLanguageTag(rLang);
287
288 for (const OUString& rPath: getPaths(rName, aLanguageTag))
289 {
290 if (rNameAccess->hasByName(rPath))
291 {
292 uno::Reference<io::XInputStream> aStream;
293 bool ok = rNameAccess->getByName(rPath) >>= aStream;
294 assert(ok);
295 (void)ok; // prevent unused warning in release build
296 return wrapStream(aStream);
297 }
298 }
299 }
300 }
301 catch (const uno::Exception &)
302 {
303 TOOLS_INFO_EXCEPTION("vcl", "");
304 }
305
306 aStyle = fallbackStyle(aStyle);
307 }
308 return std::shared_ptr<SvMemoryStream>();
309 }
310
fallbackStyle(std::u16string_view rsStyle)311 OUString ImplImageTree::fallbackStyle(std::u16string_view rsStyle)
312 {
313 OUString sResult;
314
315 if (rsStyle == u"colibre" || rsStyle == u"helpimg")
316 sResult = "";
317 else if (rsStyle == u"sifr" || rsStyle == u"breeze_dark")
318 sResult = "breeze";
319 else if (rsStyle == u"sifr_dark" )
320 sResult = "breeze_dark";
321 else
322 sResult = "colibre";
323
324 return sResult;
325 }
326
loadImage(OUString const & rName,OUString const & rStyle,BitmapEx & rBitmap,bool localized,const ImageLoadFlags eFlags,sal_Int32 nScalePercentage)327 bool ImplImageTree::loadImage(OUString const & rName, OUString const & rStyle, BitmapEx & rBitmap, bool localized,
328 const ImageLoadFlags eFlags, sal_Int32 nScalePercentage)
329 {
330 OUString aCurrentStyle(rStyle);
331 while (!aCurrentStyle.isEmpty())
332 {
333 try
334 {
335 ImageRequestParameters aParameters(rName, aCurrentStyle, rBitmap, localized, eFlags, nScalePercentage);
336 if (doLoadImage(aParameters))
337 return true;
338 }
339 catch (uno::RuntimeException &)
340 {}
341
342 aCurrentStyle = fallbackStyle(aCurrentStyle);
343 }
344 return false;
345 }
346
347 namespace
348 {
349
createVariant(ImageRequestParameters & rParameters)350 OUString createVariant(ImageRequestParameters& rParameters)
351 {
352 bool bConvertToDarkTheme = rParameters.convertToDarkTheme();
353 sal_Int32 aScalePercentage = rParameters.scalePercentage();
354
355 OUString aVariant = OUString::number(aScalePercentage);
356
357 if (bConvertToDarkTheme)
358 aVariant += "-dark";
359
360 return aVariant;
361 }
362
loadDiskCachedVersion(std::u16string_view sVariant,ImageRequestParameters & rParameters)363 bool loadDiskCachedVersion(std::u16string_view sVariant, ImageRequestParameters& rParameters)
364 {
365 OUString sUrl(getIconCacheUrl(sVariant, rParameters));
366 if (!urlExists(sUrl))
367 return false;
368 SvFileStream aFileStream(sUrl, StreamMode::READ);
369 vcl::PngImageReader aPNGReader(aFileStream);
370 aPNGReader.read(rParameters.mrBitmap);
371 return true;
372 }
373
cacheBitmapToDisk(std::u16string_view sVariant,ImageRequestParameters const & rParameters)374 void cacheBitmapToDisk(std::u16string_view sVariant, ImageRequestParameters const & rParameters)
375 {
376 OUString sUrl(createIconCacheUrl(sVariant, rParameters));
377 vcl::PNGWriter aWriter(rParameters.mrBitmap);
378 try
379 {
380 SvFileStream aStream(sUrl, StreamMode::WRITE);
381 aWriter.Write(aStream);
382 aStream.Close();
383 }
384 catch (...)
385 {}
386 }
387
388 } // end anonymous namespace
389
doLoadImage(ImageRequestParameters & rParameters)390 bool ImplImageTree::doLoadImage(ImageRequestParameters& rParameters)
391 {
392 setStyle(rParameters.msStyle);
393
394 if (iconCacheLookup(rParameters))
395 return true;
396
397 OUString aVariant = createVariant(rParameters);
398 if (loadDiskCachedVersion(aVariant, rParameters))
399 return true;
400
401 if (!rParameters.mrBitmap.IsEmpty())
402 rParameters.mrBitmap.SetEmpty();
403
404 LanguageTag aLanguageTag = Application::GetSettings().GetUILanguageTag();
405
406 std::vector<OUString> aPaths = getPaths(rParameters.msName, aLanguageTag);
407
408 bool bFound = false;
409
410 try
411 {
412 bFound = findImage(aPaths, rParameters);
413 }
414 catch (uno::RuntimeException&)
415 {
416 throw;
417 }
418 catch (const uno::Exception&)
419 {
420 TOOLS_INFO_EXCEPTION("vcl", "ImplImageTree::doLoadImage");
421 }
422
423 if (bFound)
424 {
425 if (rParameters.mbWriteImageToCache)
426 {
427 cacheBitmapToDisk(aVariant, rParameters);
428 }
429 getIconCache(rParameters)[rParameters.msName] = std::make_pair(rParameters.mbLocalized, rParameters.mrBitmap);
430 }
431
432 return bFound;
433 }
434
shutdown()435 void ImplImageTree::shutdown()
436 {
437 maCurrentStyle.clear();
438 maIconSets.clear();
439 }
440
setStyle(OUString const & style)441 void ImplImageTree::setStyle(OUString const & style)
442 {
443 assert(!style.isEmpty());
444 if (style != maCurrentStyle)
445 {
446 maCurrentStyle = style;
447 createStyle();
448 }
449 }
450
451 /**
452 * The vcldemo app doesn't set up all the config stuff that the main app does, so we need another
453 * way of finding the cursor images.
454 */
isVclDemo()455 static bool isVclDemo()
456 {
457 static const bool bVclDemoOverride = std::getenv("LIBO_VCL_DEMO") != nullptr;
458 return bVclDemoOverride;
459 }
460
createStyle()461 void ImplImageTree::createStyle()
462 {
463 if (maIconSets.find(maCurrentStyle) != maIconSets.end())
464 return;
465
466 OUString sThemeUrl;
467
468 if (isVclDemo())
469 {
470 if (maCurrentStyle == "default")
471 sThemeUrl = "file://" SRC_ROOT "/icon-themes/colibre-svg";
472 else
473 sThemeUrl = "file://" SRC_ROOT "/icon-themes/" + maCurrentStyle;
474 }
475 else if (maCurrentStyle != "default")
476 {
477 OUString paths = vcl::IconThemeScanner::GetStandardIconThemePath();
478 std::deque<OUString> aPaths;
479 sal_Int32 nIndex = 0;
480 do
481 {
482 aPaths.push_front(paths.getToken(0, ';', nIndex));
483 }
484 while (nIndex >= 0);
485
486 for (const auto& path : aPaths)
487 {
488 INetURLObject aUrl(path);
489 OSL_ASSERT(!aUrl.HasError());
490
491 bool ok = aUrl.Append(OUString("images_" + maCurrentStyle), INetURLObject::EncodeMechanism::All);
492 OSL_ASSERT(ok);
493 sThemeUrl = aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE) + ".zip";
494 if (urlExists(sThemeUrl))
495 break;
496 sThemeUrl.clear();
497 }
498
499 if (sThemeUrl.isEmpty())
500 return;
501 }
502 else
503 {
504 sThemeUrl += "images";
505 if (!urlExists(sThemeUrl))
506 return;
507 }
508
509 maIconSets[maCurrentStyle] = IconSet(sThemeUrl);
510
511 loadImageLinks();
512 }
513
514 /// Find an icon cache for the right scale factor
getIconCache(const ImageRequestParameters & rParameters)515 ImplImageTree::IconCache &ImplImageTree::getIconCache(const ImageRequestParameters& rParameters)
516 {
517 IconSet &rSet = getCurrentIconSet();
518 auto it = rSet.maScaledIconCaches.find(rParameters.mnScalePercentage);
519 if ( it != rSet.maScaledIconCaches.end() )
520 return *it->second;
521 rSet.maScaledIconCaches[rParameters.mnScalePercentage] = std::make_unique<IconCache>();
522 return *rSet.maScaledIconCaches[rParameters.mnScalePercentage];
523 }
524
iconCacheLookup(ImageRequestParameters & rParameters)525 bool ImplImageTree::iconCacheLookup(ImageRequestParameters& rParameters)
526 {
527 IconCache& rIconCache = getIconCache(rParameters);
528
529 IconCache::iterator i(rIconCache.find(getRealImageName(rParameters.msName)));
530 if (i != rIconCache.end() && i->second.first == rParameters.mbLocalized)
531 {
532 rParameters.mrBitmap = i->second.second;
533 return true;
534 }
535
536 return false;
537 }
538
findImage(std::vector<OUString> const & rPaths,ImageRequestParameters & rParameters)539 bool ImplImageTree::findImage(std::vector<OUString> const & rPaths, ImageRequestParameters& rParameters)
540 {
541 if (!checkPathAccess())
542 return false;
543
544 uno::Reference<container::XNameAccess> const & rNameAccess = getCurrentIconSet().maNameAccess;
545
546 for (OUString const & rPath : rPaths)
547 {
548 if (rNameAccess->hasByName(rPath))
549 {
550 uno::Reference<io::XInputStream> aStream;
551 bool ok = rNameAccess->getByName(rPath) >>= aStream;
552 assert(ok);
553 (void)ok; // prevent unused warning in release build
554
555 loadImageFromStream(wrapStream(aStream), rPath, rParameters);
556
557 return true;
558 }
559 }
560 return false;
561 }
562
loadImageLinks()563 void ImplImageTree::loadImageLinks()
564 {
565 static const OUStringLiteral aLinkFilename(u"links.txt");
566
567 if (!checkPathAccess())
568 return;
569
570 const uno::Reference<container::XNameAccess> &rNameAccess = getCurrentIconSet().maNameAccess;
571
572 if (rNameAccess->hasByName(aLinkFilename))
573 {
574 uno::Reference<io::XInputStream> xStream;
575 bool ok = rNameAccess->getByName(aLinkFilename) >>= xStream;
576 assert(ok);
577 (void)ok; // prevent unused warning in release build
578
579 parseLinkFile(wrapStream(xStream));
580 return;
581 }
582 }
583
parseLinkFile(std::shared_ptr<SvStream> const & xStream)584 void ImplImageTree::parseLinkFile(std::shared_ptr<SvStream> const & xStream)
585 {
586 OString aLine;
587 OUString aLink, aOriginal;
588 int nLineNo = 0;
589 while (xStream->ReadLine(aLine))
590 {
591 ++nLineNo;
592 if (aLine.isEmpty())
593 continue;
594
595 sal_Int32 nIndex = 0;
596 aLink = OStringToOUString(aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8);
597 aOriginal = OStringToOUString(aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8);
598
599 // skip comments, or incomplete entries
600 if (aLink.isEmpty() || aLink[0] == '#' || aOriginal.isEmpty())
601 {
602 if (aLink.isEmpty() || aOriginal.isEmpty())
603 SAL_WARN("vcl", "ImplImageTree::parseLinkFile: icon links.txt parse error, incomplete link at line " << nLineNo);
604 continue;
605 }
606
607 getCurrentIconSet().maLinkHash[aLink] = aOriginal;
608
609 OUString aOriginal32 = convertLcTo32Path(aOriginal);
610 OUString aLink32 = convertLcTo32Path(aLink);
611
612 if (!aOriginal32.isEmpty() && !aLink32.isEmpty())
613 getCurrentIconSet().maLinkHash[aLink32] = aOriginal32;
614 }
615 }
616
getRealImageName(OUString const & rIconName)617 OUString const & ImplImageTree::getRealImageName(OUString const & rIconName)
618 {
619 IconLinkHash & rLinkHash = maIconSets[maCurrentStyle].maLinkHash;
620
621 OUString sNameWithNoExtension = getNameNoExtension(rIconName);
622
623 // PNG is priority
624 auto it = rLinkHash.find(sNameWithNoExtension + ".png");
625 if (it != rLinkHash.end())
626 return it->second;
627
628 // also check SVG name
629 it = rLinkHash.find(sNameWithNoExtension + ".svg");
630 if (it != rLinkHash.end())
631 return it->second;
632
633 // neither was found so just return the original name
634 return rIconName;
635 }
636
637 namespace {
638
639 class FolderFileAccess : public ::cppu::WeakImplHelper<css::container::XNameAccess>
640 {
641 public:
642 uno::Reference< uno::XComponentContext > mxContext;
643 OUString maURL;
FolderFileAccess(uno::Reference<uno::XComponentContext> const & context,OUString const & url)644 FolderFileAccess(uno::Reference< uno::XComponentContext > const & context, OUString const & url)
645 : mxContext(context), maURL(url) {}
646 // XElementAccess
getElementType()647 virtual css::uno::Type SAL_CALL getElementType() override { return cppu::UnoType<io::XInputStream>::get(); }
hasElements()648 virtual sal_Bool SAL_CALL hasElements() override { return true; }
649 // XNameAccess
getByName(const OUString & aName)650 virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override
651 {
652 uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(mxContext)->openFileRead( maURL + "/" + aName );
653 return css::uno::Any(xInputStream);
654 }
getElementNames()655 virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
656 {
657 return {};
658 }
hasByName(const OUString & aName)659 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
660 {
661 osl::File aBaseFile(maURL + "/" + aName);
662 return osl::File::E_None == aBaseFile.open(osl_File_OpenFlag_Read);
663 }
664 };
665
666 }
667
checkPathAccess()668 bool ImplImageTree::checkPathAccess()
669 {
670 IconSet& rIconSet = getCurrentIconSet();
671 uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.maNameAccess;
672 if (rNameAccess.is())
673 return true;
674
675 try
676 {
677 if (isVclDemo())
678 rNameAccess = new FolderFileAccess(comphelper::getProcessComponentContext(), rIconSet.maURL);
679 else
680 rNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), rIconSet.maURL);
681 }
682 catch (const uno::RuntimeException &)
683 {
684 throw;
685 }
686 catch (const uno::Exception &)
687 {
688 TOOLS_INFO_EXCEPTION("vcl", "ImplImageTree::zip file location " << rIconSet.maURL);
689 return false;
690 }
691 return rNameAccess.is();
692 }
693
getNameAccess()694 uno::Reference<container::XNameAccess> const & ImplImageTree::getNameAccess()
695 {
696 (void)checkPathAccess();
697 return getCurrentIconSet().maNameAccess;
698 }
699
700 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
701