LCOV - code coverage report
Current view: top level - vcl/source/app - IconThemeScanner.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 74 86 86.0 %
Date: 2015-06-13 12:38:46 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      10             : #include <vcl/IconThemeScanner.hxx>
      11             : 
      12             : #include <config_folders.h>
      13             : #include <osl/file.hxx>
      14             : #include <rtl/bootstrap.hxx>
      15             : #include <salhelper/linkhelper.hxx>
      16             : 
      17             : #include <vcl/svapp.hxx>
      18             : #include <vcl/IconThemeInfo.hxx>
      19             : 
      20             : namespace vcl {
      21             : 
      22             : namespace {
      23             : 
      24             : // set the status of a file. Returns false if the status could not be determined.
      25        3376 : bool set_file_status(osl::FileStatus& status, const OUString& file)
      26             : {
      27        3376 :     osl::DirectoryItem dirItem;
      28        3376 :     osl::FileBase::RC retvalGet = osl::DirectoryItem::get(file, dirItem);
      29        3376 :     if (retvalGet != osl::FileBase::E_None) {
      30             :         SAL_WARN("vcl.app", "Could not determine status for file '" << file << "'.");
      31           0 :         return false;
      32             :     }
      33        3376 :     osl::FileBase::RC retvalStatus = dirItem.getFileStatus(status);
      34        3376 :     if (retvalStatus != osl::FileBase::E_None) {
      35             :         SAL_WARN("vcl.app", "Could not determine status for file '" << file << "'.");
      36           0 :         return false;
      37             :     }
      38        3376 :     return true;
      39             : }
      40             : 
      41        4221 : OUString convert_to_absolute_path(const OUString& path)
      42             : {
      43        4221 :     salhelper::LinkResolver resolver(0);
      44        4221 :     osl::FileBase::RC rc = resolver.fetchFileStatus(path);
      45        4221 :     if (rc != osl::FileBase::E_None) {
      46             :         SAL_WARN("vcl.app", "Could not resolve path '" << path << "' to search for icon themes.");
      47           0 :         if (rc == osl::FileBase::E_MULTIHOP)
      48             :         {
      49           0 :             throw std::runtime_error("Provided a recursive symlink to a icon theme directory that could not be resolved.");
      50             :         }
      51             :     }
      52        4221 :     return resolver.m_aStatus.getFileURL();
      53             : }
      54             : 
      55             : }
      56             : 
      57         425 : IconThemeScanner::IconThemeScanner()
      58         425 : {;}
      59             : 
      60             : bool
      61         422 : IconThemeScanner::ScanDirectoryForIconThemes(const OUString& path)
      62             : {
      63         422 :     osl::FileStatus fileStatus(osl_FileStatus_Mask_Type);
      64         422 :     bool couldSetFileStatus = set_file_status(fileStatus, path);
      65         422 :     if (!couldSetFileStatus) {
      66           0 :         return false;
      67             :     }
      68             : 
      69         422 :     if (!fileStatus.isDirectory()) {
      70             :         SAL_INFO("vcl.app", "Cannot search for icon themes in '"<< path << "'. It is not a directory.");
      71           0 :         return false;
      72             :     }
      73             : 
      74         844 :     std::vector<OUString> iconThemePaths = ReadIconThemesFromPath(path);
      75         422 :     if (iconThemePaths.empty()) {
      76             :         SAL_WARN("vcl.app", "Could not find any icon themes in the provided directory ('" <<path<<"'.");
      77           0 :         return false;
      78             :     }
      79         422 :     mFoundIconThemes.clear();
      80        3376 :     for (std::vector<OUString>::iterator aI = iconThemePaths.begin(); aI != iconThemePaths.end(); ++aI)
      81             :     {
      82        2954 :         AddIconThemeByPath(*aI);
      83             :     }
      84         844 :     return true;
      85             : }
      86             : 
      87             : bool
      88        2957 : IconThemeScanner::AddIconThemeByPath(const OUString &url)
      89             : {
      90        2957 :     if (!IconThemeInfo::UrlCanBeParsed(url)) {
      91           0 :         return false;
      92             :     }
      93             :     SAL_INFO("vcl.app", "Found a file that seems to be an icon theme: '" << url << "'" );
      94        2957 :     IconThemeInfo newTheme(url);
      95        2957 :     mFoundIconThemes.push_back(newTheme);
      96             :     SAL_INFO("vcl.app", "Adding the file as '" << newTheme.GetDisplayName() <<
      97             :             "' with id '" << newTheme.GetThemeId() << "'.");
      98        2957 :     return true;
      99             : }
     100             : 
     101             : /*static*/ std::vector<OUString>
     102         422 : IconThemeScanner::ReadIconThemesFromPath(const OUString& dir)
     103             : {
     104         422 :     std::vector<OUString> found;
     105             :     SAL_INFO("vcl.app", "Scanning directory '" << dir << " for icon themes.");
     106             : 
     107         844 :     osl::Directory dirToScan(dir);
     108         422 :     osl::FileBase::RC retvalOpen = dirToScan.open();
     109         422 :     if (retvalOpen != osl::FileBase::E_None) {
     110           0 :         return found;
     111             :     }
     112             : 
     113         844 :     osl::DirectoryItem directoryItem;
     114        5065 :     while (dirToScan.getNextItem(directoryItem) == osl::FileBase::E_None) {
     115        4221 :         osl::FileStatus status(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName);
     116        4221 :         osl::FileBase::RC retvalStatus = directoryItem.getFileStatus(status);
     117        4221 :         if (retvalStatus != osl::FileBase::E_None) {
     118           0 :             continue;
     119             :         }
     120             : 
     121        7175 :         OUString filename = convert_to_absolute_path(status.getFileURL());
     122        4221 :         if (!FileIsValidIconTheme(filename)) {
     123        1267 :             continue;
     124             :         }
     125        2954 :         found.push_back(filename);
     126        2954 :     }
     127         422 :     return found;
     128             : }
     129             : 
     130             : /*static*/ bool
     131        4221 : IconThemeScanner::FileIsValidIconTheme(const OUString& filename)
     132             : {
     133             :     // check whether we can construct a IconThemeInfo from it
     134        4221 :     if (!IconThemeInfo::UrlCanBeParsed(filename)) {
     135             :         SAL_INFO("vcl.app", "File '" << filename << "' does not seem to be an icon theme.");
     136        1267 :         return false;
     137             :     }
     138             : 
     139        2954 :     osl::FileStatus fileStatus(osl_FileStatus_Mask_Type);
     140        2954 :     bool couldSetFileStatus = set_file_status(fileStatus, filename);
     141        2954 :     if (!couldSetFileStatus) {
     142           0 :         return false;
     143             :     }
     144             : 
     145        2954 :     if (!fileStatus.isRegular()) {
     146           0 :         return false;
     147             :     }
     148        2954 :     return true;
     149             : }
     150             : 
     151             : bool
     152           1 : IconThemeScanner::IconThemeIsInstalled(const OUString& themeId) const
     153             : {
     154           1 :     return IconThemeInfo::IconThemeIsInVector(mFoundIconThemes, themeId);
     155             : }
     156             : 
     157             : /*static*/ std::shared_ptr<IconThemeScanner>
     158         422 : IconThemeScanner::Create(const OUString &path)
     159             : {
     160         422 :     std::shared_ptr<IconThemeScanner> retval(new IconThemeScanner);
     161         422 :     retval->ScanDirectoryForIconThemes(path);
     162         422 :     return retval;
     163             : }
     164             : 
     165             : /*static*/ OUString
     166         422 : IconThemeScanner::GetStandardIconThemePath()
     167             : {
     168         422 :     OUString url( "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/config/" );
     169         422 :     rtl::Bootstrap::expandMacros(url);
     170         422 :     return url;
     171             : }
     172             : 
     173       47299 : IconThemeScanner::~IconThemeScanner()
     174       47299 : {;}
     175             : 
     176             : namespace
     177             : {
     178             :     class SameTheme :
     179             :         public std::unary_function<const vcl::IconThemeInfo &, bool>
     180             :     {
     181             :     private:
     182             :         const OUString& m_rThemeId;
     183             :     public:
     184           2 :         explicit SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {}
     185           2 :         bool operator()(const vcl::IconThemeInfo &rInfo)
     186             :         {
     187           2 :             return m_rThemeId == rInfo.GetThemeId();
     188             :         }
     189             :     };
     190             : }
     191             : 
     192             : const vcl::IconThemeInfo&
     193           2 : IconThemeScanner::GetIconThemeInfo(const OUString& themeId)
     194             : {
     195             :     std::vector<IconThemeInfo>::iterator info = std::find_if(mFoundIconThemes.begin(), mFoundIconThemes.end(),
     196           2 :         SameTheme(themeId));
     197           2 :     if (info == mFoundIconThemes.end()) {
     198             :         SAL_WARN("vcl.app", "Requested information for icon theme with id '" << themeId
     199             :                 << "' which does not exist.");
     200           1 :         throw std::runtime_error("Requested information on not-installed icon theme");
     201             :     }
     202           1 :     return *info;
     203             : }
     204             : 
     205             : } // end namespace vcl
     206             : 
     207             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11