summaryrefslogtreecommitdiffstats
path: root/vcl/source/image/ImplImageTree.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vcl/source/image/ImplImageTree.cxx714
1 files changed, 714 insertions, 0 deletions
diff --git a/vcl/source/image/ImplImageTree.cxx b/vcl/source/image/ImplImageTree.cxx
new file mode 100644
index 000000000..36ac5f4de
--- /dev/null
+++ b/vcl/source/image/ImplImageTree.cxx
@@ -0,0 +1,714 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_folders.h>
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <deque>
+#include <string_view>
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <osl/file.hxx>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <rtl/bootstrap.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <tools/diagnose_ex.h>
+#include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
+#include <implimagetree.hxx>
+
+#include <vcl/bitmapex.hxx>
+#include <vcl/dibtools.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <IconThemeScanner.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/pngwrite.hxx>
+#include <o3tl/string_view.hxx>
+#include <bitmap/BitmapLightenFilter.hxx>
+
+using namespace css;
+
+bool ImageRequestParameters::convertToDarkTheme()
+{
+ static bool bIconsForDarkTheme = !!getenv("VCL_ICONS_FOR_DARK_THEME");
+
+ bool bConvertToDarkTheme = false;
+ if (!(meFlags & ImageLoadFlags::IgnoreDarkTheme))
+ bConvertToDarkTheme = bIconsForDarkTheme;
+
+ return bConvertToDarkTheme;
+}
+
+sal_Int32 ImageRequestParameters::scalePercentage()
+{
+ sal_Int32 aScalePercentage = 100;
+ if (!(meFlags & ImageLoadFlags::IgnoreScalingFactor))
+ aScalePercentage = Application::GetDefaultDevice()->GetDPIScalePercentage();
+ else if (mnScalePercentage > 0)
+ aScalePercentage = mnScalePercentage;
+ return aScalePercentage;
+}
+
+namespace
+{
+
+OUString convertLcTo32Path(std::u16string_view rPath)
+{
+ OUString aResult;
+ size_t nSlashPos = rPath.rfind('/');
+ if (nSlashPos != std::u16string_view::npos)
+ {
+ sal_Int32 nCopyFrom = nSlashPos + 1;
+ std::u16string_view sFile = rPath.substr(nCopyFrom);
+ std::u16string_view sDir = rPath.substr(0, nSlashPos);
+ if (!sFile.empty() && o3tl::starts_with(sFile, u"lc_"))
+ {
+ aResult = OUString::Concat(sDir) + "/32/" + sFile.substr(3);
+ }
+ }
+ return aResult;
+}
+
+OUString createPath(std::u16string_view name, sal_Int32 pos, std::u16string_view locale)
+{
+ return OUString::Concat(name.substr(0, pos + 1)) + locale + name.substr(pos);
+}
+
+OUString getIconCacheUrl(std::u16string_view sVariant, ImageRequestParameters const & rParameters)
+{
+ // the macro expansion can be expensive in bulk, so cache that
+ static OUString CACHE_DIR = []()
+ {
+ OUString sDir = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/";
+ rtl::Bootstrap::expandMacros(sDir);
+ return sDir;
+ }();
+ return CACHE_DIR + rParameters.msStyle + "/" + sVariant + "/" + rParameters.msName;
+}
+
+OUString createIconCacheUrl(
+ std::u16string_view sVariant, ImageRequestParameters const & rParameters)
+{
+ OUString sUrl(getIconCacheUrl(sVariant, rParameters));
+ OUString sDir = sUrl.copy(0, sUrl.lastIndexOf('/'));
+ osl::Directory::createPath(sDir);
+ return sUrl;
+}
+
+bool urlExists(OUString const & sUrl)
+{
+ osl::File aFile(sUrl);
+ osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read);
+ return osl::FileBase::E_None == eRC;
+}
+
+OUString getNameNoExtension(std::u16string_view sName)
+{
+ size_t nDotPosition = sName.rfind('.');
+ return OUString(sName.substr(0, nDotPosition));
+}
+
+std::shared_ptr<SvMemoryStream> wrapStream(uno::Reference<io::XInputStream> const & rInputStream)
+{
+ // This could use SvInputStream instead if that did not have a broken
+ // SeekPos implementation for an XInputStream that is not also XSeekable
+ // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
+ // l. 593):
+ OSL_ASSERT(rInputStream.is());
+ std::shared_ptr<SvMemoryStream> aMemoryStream(std::make_shared<SvMemoryStream>());
+ for (;;)
+ {
+ const sal_Int32 nSize(2048);
+ uno::Sequence<sal_Int8> aData(nSize);
+ sal_Int32 nRead = rInputStream->readBytes(aData, nSize);
+ aMemoryStream->WriteBytes(aData.getConstArray(), nRead);
+ if (nRead < nSize)
+ break;
+ }
+ aMemoryStream->Seek(0);
+ rInputStream->closeInput();
+ return aMemoryStream;
+}
+
+void loadImageFromStream(std::shared_ptr<SvStream> const & xStream, OUString const & rPath, ImageRequestParameters& rParameters)
+{
+ bool bConvertToDarkTheme = rParameters.convertToDarkTheme();
+ sal_Int32 aScalePercentage = rParameters.scalePercentage();
+
+ if (rPath.endsWith(".png"))
+ {
+ vcl::PngImageReader aPNGReader(*xStream);
+ aPNGReader.read(rParameters.mrBitmap);
+ }
+ else if (rPath.endsWith(".svg"))
+ {
+ rParameters.mbWriteImageToCache = true; // We always want to cache a SVG image
+ vcl::bitmap::loadFromSvg(*xStream, rPath, rParameters.mrBitmap, aScalePercentage / 100.0);
+
+ if (bConvertToDarkTheme)
+ BitmapFilter::Filter(rParameters.mrBitmap, BitmapLightenFilter());
+
+ return;
+ }
+ else
+ {
+ ReadDIBBitmapEx(rParameters.mrBitmap, *xStream);
+ }
+
+ if (bConvertToDarkTheme)
+ {
+ rParameters.mbWriteImageToCache = true; // Cache the dark variant
+ BitmapFilter::Filter(rParameters.mrBitmap, BitmapLightenFilter());
+ }
+
+ if (aScalePercentage > 100)
+ {
+ rParameters.mbWriteImageToCache = true; // Cache the scaled variant
+ double aScaleFactor(aScalePercentage / 100.0);
+ // when scaling use the full 24bit RGB values
+ rParameters.mrBitmap.Convert(BmpConversion::N24Bit);
+ rParameters.mrBitmap.Scale(aScaleFactor, aScaleFactor, BmpScaleFlag::Fast);
+ }
+}
+
+} // end anonymous namespace
+
+ImplImageTree::ImplImageTree()
+{
+}
+
+ImplImageTree::~ImplImageTree()
+{
+}
+
+std::vector<OUString> ImplImageTree::getPaths(OUString const & name, LanguageTag const & rLanguageTag)
+{
+ std::vector<OUString> sPaths;
+
+ sal_Int32 pos = name.lastIndexOf('/');
+ if (pos != -1)
+ {
+ for (const OUString& rFallback : rLanguageTag.getFallbackStrings(true))
+ {
+ OUString aFallbackName = getNameNoExtension(getRealImageName(createPath(name, pos, rFallback)));
+ sPaths.emplace_back(aFallbackName + ".png");
+ sPaths.emplace_back(aFallbackName + ".svg");
+ }
+ }
+
+ OUString aRealName = getNameNoExtension(getRealImageName(name));
+ sPaths.emplace_back(aRealName + ".png");
+ sPaths.emplace_back(aRealName + ".svg");
+
+ return sPaths;
+}
+
+OUString ImplImageTree::getImageUrl(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+{
+ OUString aStyle(rStyle);
+
+ while (!aStyle.isEmpty())
+ {
+ try
+ {
+ setStyle(aStyle);
+
+ if (checkPathAccess())
+ {
+ IconSet& rIconSet = getCurrentIconSet();
+ const uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.maNameAccess;
+
+ LanguageTag aLanguageTag(rLang);
+
+ for (const OUString& rPath: getPaths(rName, aLanguageTag))
+ {
+ if (rNameAccess->hasByName(rPath))
+ {
+ return "vnd.sun.star.zip://"
+ + rtl::Uri::encode(rIconSet.maURL, rtl_UriCharClassRegName,
+ rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8)
+ + "/" + rPath;
+ }
+ }
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION("vcl", "");
+ }
+
+ aStyle = fallbackStyle(aStyle);
+ }
+ return OUString();
+}
+
+uno::Reference<io::XInputStream> ImplImageTree::getImageXInputStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+{
+ OUString aStyle(rStyle);
+
+ while (!aStyle.isEmpty())
+ {
+ try
+ {
+ setStyle(aStyle);
+
+ if (checkPathAccess())
+ {
+ IconSet& rIconSet = getCurrentIconSet();
+ const uno::Reference<container::XNameAccess>& rNameAccess = rIconSet.maNameAccess;
+
+ LanguageTag aLanguageTag(rLang);
+
+ for (const OUString& rPath: getPaths(rName, aLanguageTag))
+ {
+ if (rNameAccess->hasByName(rPath))
+ {
+ uno::Reference<io::XInputStream> aStream;
+ bool ok = rNameAccess->getByName(rPath) >>= aStream;
+ assert(ok);
+ (void)ok; // prevent unused warning in release build
+ return aStream;
+ }
+ }
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION("vcl", "");
+ }
+
+ aStyle = fallbackStyle(aStyle);
+ }
+ return nullptr;
+}
+
+std::shared_ptr<SvMemoryStream> ImplImageTree::getImageStream(OUString const & rName, OUString const & rStyle, OUString const & rLang)
+{
+ uno::Reference<io::XInputStream> xStream = getImageXInputStream(rName, rStyle, rLang);
+ if (xStream)
+ return wrapStream(xStream);
+ return std::shared_ptr<SvMemoryStream>();
+}
+
+OUString ImplImageTree::fallbackStyle(std::u16string_view rsStyle)
+{
+ OUString sResult;
+
+ if (rsStyle == u"colibre" || rsStyle == u"helpimg")
+ sResult = "";
+ else if (rsStyle == u"sifr" || rsStyle == u"breeze_dark")
+ sResult = "breeze";
+ else if (rsStyle == u"sifr_dark" )
+ sResult = "breeze_dark";
+ else
+ sResult = "colibre";
+
+ return sResult;
+}
+
+bool ImplImageTree::loadImage(OUString const & rName, OUString const & rStyle, BitmapEx & rBitmap, bool localized,
+ const ImageLoadFlags eFlags, sal_Int32 nScalePercentage)
+{
+ OUString aCurrentStyle(rStyle);
+ while (!aCurrentStyle.isEmpty())
+ {
+ try
+ {
+ ImageRequestParameters aParameters(rName, aCurrentStyle, rBitmap, localized, eFlags, nScalePercentage);
+ if (doLoadImage(aParameters))
+ return true;
+ }
+ catch (uno::RuntimeException &)
+ {}
+
+ aCurrentStyle = fallbackStyle(aCurrentStyle);
+ }
+ return false;
+}
+
+namespace
+{
+
+OUString createVariant(ImageRequestParameters& rParameters)
+{
+ bool bConvertToDarkTheme = rParameters.convertToDarkTheme();
+ sal_Int32 aScalePercentage = rParameters.scalePercentage();
+
+ OUString aVariant = OUString::number(aScalePercentage);
+
+ if (bConvertToDarkTheme)
+ aVariant += "-dark";
+
+ return aVariant;
+}
+
+bool loadDiskCachedVersion(std::u16string_view sVariant, ImageRequestParameters& rParameters)
+{
+ OUString sUrl(getIconCacheUrl(sVariant, rParameters));
+ if (!urlExists(sUrl))
+ return false;
+ SvFileStream aFileStream(sUrl, StreamMode::READ);
+ vcl::PngImageReader aPNGReader(aFileStream);
+ aPNGReader.read(rParameters.mrBitmap);
+ return true;
+}
+
+void cacheBitmapToDisk(std::u16string_view sVariant, ImageRequestParameters const & rParameters)
+{
+ OUString sUrl(createIconCacheUrl(sVariant, rParameters));
+ vcl::PNGWriter aWriter(rParameters.mrBitmap);
+ try
+ {
+ SvFileStream aStream(sUrl, StreamMode::WRITE);
+ aWriter.Write(aStream);
+ aStream.Close();
+ }
+ catch (...)
+ {}
+}
+
+} // end anonymous namespace
+
+bool ImplImageTree::doLoadImage(ImageRequestParameters& rParameters)
+{
+ setStyle(rParameters.msStyle);
+
+ if (iconCacheLookup(rParameters))
+ return true;
+
+ OUString aVariant = createVariant(rParameters);
+ if (loadDiskCachedVersion(aVariant, rParameters))
+ return true;
+
+ if (!rParameters.mrBitmap.IsEmpty())
+ rParameters.mrBitmap.SetEmpty();
+
+ LanguageTag aLanguageTag = Application::GetSettings().GetUILanguageTag();
+
+ std::vector<OUString> aPaths = getPaths(rParameters.msName, aLanguageTag);
+
+ bool bFound = false;
+
+ try
+ {
+ bFound = findImage(aPaths, rParameters);
+ }
+ catch (uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_INFO_EXCEPTION("vcl", "ImplImageTree::doLoadImage");
+ }
+
+ if (bFound)
+ {
+ if (rParameters.mbWriteImageToCache)
+ {
+ cacheBitmapToDisk(aVariant, rParameters);
+ }
+ getIconCache(rParameters)[rParameters.msName] = std::make_pair(rParameters.mbLocalized, rParameters.mrBitmap);
+ }
+
+ return bFound;
+}
+
+void ImplImageTree::shutdown()
+{
+ maCurrentStyle.clear();
+ maIconSets.clear();
+}
+
+void ImplImageTree::setStyle(OUString const & style)
+{
+ assert(!style.isEmpty());
+ if (style != maCurrentStyle)
+ {
+ maCurrentStyle = style;
+ createStyle();
+ }
+}
+
+/**
+ * The vcldemo app doesn't set up all the config stuff that the main app does, so we need another
+ * way of finding the cursor images.
+ */
+static bool isVclDemo()
+{
+ static const bool bVclDemoOverride = std::getenv("LIBO_VCL_DEMO") != nullptr;
+ return bVclDemoOverride;
+}
+
+void ImplImageTree::createStyle()
+{
+ if (maIconSets.find(maCurrentStyle) != maIconSets.end())
+ return;
+
+ OUString sThemeUrl;
+
+ if (isVclDemo())
+ {
+ if (maCurrentStyle == "default")
+ sThemeUrl = "file://" SRC_ROOT "/icon-themes/colibre-svg";
+ else
+ sThemeUrl = "file://" SRC_ROOT "/icon-themes/" + maCurrentStyle;
+ }
+ else if (maCurrentStyle != "default")
+ {
+ OUString paths = vcl::IconThemeScanner::GetStandardIconThemePath();
+ std::deque<OUString> aPaths;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ aPaths.push_front(paths.getToken(0, ';', nIndex));
+ }
+ while (nIndex >= 0);
+
+ for (const auto& path : aPaths)
+ {
+ INetURLObject aUrl(path);
+ OSL_ASSERT(!aUrl.HasError());
+
+ bool ok = aUrl.Append(OUStringConcatenation("images_" + maCurrentStyle), INetURLObject::EncodeMechanism::All);
+ OSL_ASSERT(ok);
+ sThemeUrl = aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE) + ".zip";
+ if (urlExists(sThemeUrl))
+ break;
+ sThemeUrl.clear();
+ }
+
+ if (sThemeUrl.isEmpty())
+ return;
+ }
+ else
+ {
+ sThemeUrl += "images";
+ if (!urlExists(sThemeUrl))
+ return;
+ }
+
+ maIconSets[maCurrentStyle] = IconSet(sThemeUrl);
+
+ loadImageLinks();
+}
+
+/// Find an icon cache for the right scale factor
+ImplImageTree::IconCache &ImplImageTree::getIconCache(const ImageRequestParameters& rParameters)
+{
+ IconSet &rSet = getCurrentIconSet();
+ auto it = rSet.maScaledIconCaches.find(rParameters.mnScalePercentage);
+ if ( it != rSet.maScaledIconCaches.end() )
+ return it->second;
+ rSet.maScaledIconCaches.emplace(rParameters.mnScalePercentage, IconCache());
+ return rSet.maScaledIconCaches[rParameters.mnScalePercentage];
+}
+
+bool ImplImageTree::iconCacheLookup(ImageRequestParameters& rParameters)
+{
+ IconCache& rIconCache = getIconCache(rParameters);
+
+ IconCache::iterator i(rIconCache.find(getRealImageName(rParameters.msName)));
+ if (i != rIconCache.end() && i->second.first == rParameters.mbLocalized)
+ {
+ rParameters.mrBitmap = i->second.second;
+ return true;
+ }
+
+ return false;
+}
+
+bool ImplImageTree::findImage(std::vector<OUString> const & rPaths, ImageRequestParameters& rParameters)
+{
+ if (!checkPathAccess())
+ return false;
+
+ uno::Reference<container::XNameAccess> const & rNameAccess = getCurrentIconSet().maNameAccess;
+
+ for (OUString const & rPath : rPaths)
+ {
+ if (rNameAccess->hasByName(rPath))
+ {
+ uno::Reference<io::XInputStream> aStream;
+ bool ok = rNameAccess->getByName(rPath) >>= aStream;
+ assert(ok);
+ (void)ok; // prevent unused warning in release build
+
+ loadImageFromStream(wrapStream(aStream), rPath, rParameters);
+
+ return true;
+ }
+ }
+ return false;
+}
+
+void ImplImageTree::loadImageLinks()
+{
+ static const OUStringLiteral aLinkFilename(u"links.txt");
+
+ if (!checkPathAccess())
+ return;
+
+ const uno::Reference<container::XNameAccess> &rNameAccess = getCurrentIconSet().maNameAccess;
+
+ if (rNameAccess->hasByName(aLinkFilename))
+ {
+ uno::Reference<io::XInputStream> xStream;
+ bool ok = rNameAccess->getByName(aLinkFilename) >>= xStream;
+ assert(ok);
+ (void)ok; // prevent unused warning in release build
+
+ parseLinkFile(wrapStream(xStream));
+ return;
+ }
+}
+
+void ImplImageTree::parseLinkFile(std::shared_ptr<SvStream> const & xStream)
+{
+ OStringBuffer aLine;
+ OUString aLink, aOriginal;
+ int nLineNo = 0;
+ while (xStream->ReadLine(aLine))
+ {
+ ++nLineNo;
+ if (aLine.isEmpty())
+ continue;
+
+ sal_Int32 nIndex = 0;
+ aLink = OStringToOUString(o3tl::getToken(aLine, 0, ' ', nIndex), RTL_TEXTENCODING_UTF8);
+ aOriginal = OStringToOUString(o3tl::getToken(aLine, 0, ' ', nIndex), RTL_TEXTENCODING_UTF8);
+
+ // skip comments, or incomplete entries
+ if (aLink.isEmpty() || aLink[0] == '#' || aOriginal.isEmpty())
+ {
+ if (aLink.isEmpty() || aOriginal.isEmpty())
+ SAL_WARN("vcl", "ImplImageTree::parseLinkFile: icon links.txt parse error, incomplete link at line " << nLineNo);
+ continue;
+ }
+
+ getCurrentIconSet().maLinkHash[aLink] = aOriginal;
+
+ OUString aOriginal32 = convertLcTo32Path(aOriginal);
+ OUString aLink32 = convertLcTo32Path(aLink);
+
+ if (!aOriginal32.isEmpty() && !aLink32.isEmpty())
+ getCurrentIconSet().maLinkHash[aLink32] = aOriginal32;
+ }
+}
+
+OUString const & ImplImageTree::getRealImageName(OUString const & rIconName)
+{
+ IconLinkHash & rLinkHash = maIconSets[maCurrentStyle].maLinkHash;
+
+ OUString sNameWithNoExtension = getNameNoExtension(rIconName);
+
+ // PNG is priority
+ auto it = rLinkHash.find(sNameWithNoExtension + ".png");
+ if (it != rLinkHash.end())
+ return it->second;
+
+ // also check SVG name
+ it = rLinkHash.find(sNameWithNoExtension + ".svg");
+ if (it != rLinkHash.end())
+ return it->second;
+
+ // neither was found so just return the original name
+ return rIconName;
+}
+
+namespace {
+
+class FolderFileAccess : public ::cppu::WeakImplHelper<css::container::XNameAccess>
+{
+public:
+ uno::Reference< uno::XComponentContext > mxContext;
+ OUString maURL;
+ FolderFileAccess(uno::Reference< uno::XComponentContext > const & context, OUString const & url)
+ : mxContext(context), maURL(url) {}
+ // XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType() override { return cppu::UnoType<io::XInputStream>::get(); }
+ virtual sal_Bool SAL_CALL hasElements() override { return true; }
+ // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override
+ {
+ uno::Reference< io::XInputStream > xInputStream = ucb::SimpleFileAccess::create(mxContext)->openFileRead( maURL + "/" + aName );
+ return css::uno::Any(xInputStream);
+ }
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
+ {
+ return {};
+ }
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
+ {
+ osl::File aBaseFile(maURL + "/" + aName);
+ return osl::File::E_None == aBaseFile.open(osl_File_OpenFlag_Read);
+ }
+};
+
+}
+
+bool ImplImageTree::checkPathAccess()
+{
+ IconSet& rIconSet = getCurrentIconSet();
+ uno::Reference<container::XNameAccess> & rNameAccess = rIconSet.maNameAccess;
+ if (rNameAccess.is())
+ return true;
+
+ try
+ {
+ if (isVclDemo())
+ rNameAccess = new FolderFileAccess(comphelper::getProcessComponentContext(), rIconSet.maURL);
+ else
+ rNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), rIconSet.maURL);
+ }
+ catch (const uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION("vcl", "ImplImageTree::zip file location " << rIconSet.maURL);
+ return false;
+ }
+ return rNameAccess.is();
+}
+
+uno::Reference<container::XNameAccess> const & ImplImageTree::getNameAccess()
+{
+ (void)checkPathAccess();
+ return getCurrentIconSet().maNameAccess;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */