Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/uiconfiguration/CommandImageResolver.cxx
Line
Count
Source
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 "CommandImageResolver.hxx"
11
#include <vcl/settings.hxx>
12
#include <vcl/svapp.hxx>
13
#include <rtl/ustrbuf.hxx>
14
#include <tools/urlobj.hxx>
15
16
using css::uno::Sequence;
17
18
namespace vcl
19
{
20
21
namespace
22
{
23
24
std::map<std::tuple<ImageType, ImageWritingDirection>, OUString> const ImageType_Prefixes{
25
    { { ImageType::Size16, ImageWritingDirection::DontCare }, u"cmd/sc_"_ustr },
26
    { { ImageType::Size26, ImageWritingDirection::DontCare }, u"cmd/lc_"_ustr },
27
    { { ImageType::Size32, ImageWritingDirection::DontCare }, u"cmd/32/"_ustr },
28
    { { ImageType::Size16, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/sc_"_ustr },
29
    { { ImageType::Size26, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/lc_"_ustr },
30
    { { ImageType::Size32, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/32/"_ustr },
31
};
32
33
OUString lclConvertToCanonicalName(const OUString& rFileName)
34
0
{
35
0
    bool bRemoveSlash(true);
36
0
    sal_Int32 nLength = rFileName.getLength();
37
0
    const sal_Unicode* pString = rFileName.getStr();
38
39
0
    OUStringBuffer aBuffer(nLength*2);
40
41
0
    for (sal_Int32 i = 0; i < nLength; i++)
42
0
    {
43
0
        const sal_Unicode cCurrentChar = pString[i];
44
0
        switch (cCurrentChar)
45
0
        {
46
            // map forbidden characters to escape
47
0
            case '/':
48
0
                if (!bRemoveSlash)
49
0
                    aBuffer.append("%2f");
50
0
                break;
51
0
            case '\\': aBuffer.append("%5c"); bRemoveSlash = false; break;
52
0
            case ':':  aBuffer.append("%3a"); bRemoveSlash = false; break;
53
0
            case '*':  aBuffer.append("%2a"); bRemoveSlash = false; break;
54
0
            case '?':  aBuffer.append("%3f"); bRemoveSlash = false; break;
55
0
            case '<':  aBuffer.append("%3c"); bRemoveSlash = false; break;
56
0
            case '>':  aBuffer.append("%3e"); bRemoveSlash = false; break;
57
0
            case '|':  aBuffer.append("%7c"); bRemoveSlash = false; break;
58
0
            default:
59
0
                aBuffer.append(cCurrentChar); bRemoveSlash = false; break;
60
0
        }
61
0
    }
62
0
    return aBuffer.makeStringAndClear();
63
0
}
64
65
} // end anonymous namespace
66
67
CommandImageResolver::CommandImageResolver()
68
0
{
69
0
}
70
71
CommandImageResolver::~CommandImageResolver()
72
0
{
73
0
}
74
75
void CommandImageResolver::registerCommands(const Sequence<OUString>& aCommandSequence)
76
0
{
77
0
    sal_Int32 nSequenceSize = aCommandSequence.getLength();
78
79
0
    m_aImageCommandNameVector.resize(nSequenceSize);
80
0
    m_aImageNameVector.resize(nSequenceSize);
81
82
0
    for (sal_Int32 i = 0; i < nSequenceSize; ++i)
83
0
    {
84
0
        const OUString& aCommandName(aCommandSequence[i]);
85
0
        OUString aImageName;
86
87
0
        m_aImageCommandNameVector[i] = aCommandName;
88
89
0
        if (aCommandName.indexOf(".uno:") != 0)
90
0
        {
91
0
            INetURLObject aUrlObject(aCommandName, INetURLObject::EncodeMechanism::All);
92
0
            aImageName = aUrlObject.GetURLPath();
93
0
            aImageName = lclConvertToCanonicalName(aImageName);
94
0
        }
95
0
        else
96
0
        {
97
            // just remove the schema
98
0
            if (aCommandName.getLength() > 5)
99
0
                aImageName = aCommandName.copy(5);
100
101
            // Search for query part.
102
0
            if (aImageName.indexOf('?') != -1)
103
0
                aImageName = lclConvertToCanonicalName(aImageName);
104
0
        }
105
106
        // Image names are not case-dependent. Always use lower case characters to
107
        // reflect this.
108
0
        aImageName = aImageName.toAsciiLowerCase() + ".png";
109
110
0
        m_aImageNameVector[i] = aImageName;
111
0
        m_aCommandToImageNameMap[aCommandName] = aImageName;
112
0
    }
113
0
}
114
115
bool CommandImageResolver::hasImage(const OUString& rCommandURL)
116
0
{
117
0
    CommandToImageNameMap::const_iterator pIterator = m_aCommandToImageNameMap.find(rCommandURL);
118
0
    return pIterator != m_aCommandToImageNameMap.end();
119
0
}
120
121
ImageList* CommandImageResolver::getImageList(ImageType nImageType, ImageWritingDirection nImageDir)
122
0
{
123
0
    const OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
124
125
0
    if (sIconTheme != m_sIconTheme)
126
0
    {
127
0
        m_sIconTheme = sIconTheme;
128
0
        m_pImageList.clear();
129
0
    }
130
131
0
    auto stKey = std::make_tuple(nImageType, nImageDir);
132
0
    if (auto it = m_pImageList.find(stKey); it != m_pImageList.end())
133
0
    {
134
0
        return it->second.get();
135
0
    }
136
137
0
    const OUString& sIconPath = ImageType_Prefixes.at(stKey);
138
0
    auto pImageList = std::make_unique<ImageList>(m_aImageNameVector, sIconPath);
139
140
0
    return m_pImageList.emplace(stKey, std::move(pImageList)).first->second.get();
141
0
}
142
143
Image CommandImageResolver::getImageFromCommandURL(ImageType nImageType,
144
                                                   ImageWritingDirection nImageDir,
145
                                                   const OUString& rCommandURL)
146
0
{
147
0
    CommandToImageNameMap::const_iterator pIterator = m_aCommandToImageNameMap.find(rCommandURL);
148
0
    if (pIterator != m_aCommandToImageNameMap.end())
149
0
    {
150
0
        ImageList* pImageList = getImageList(nImageType, nImageDir);
151
0
        return pImageList->GetImage(pIterator->second);
152
0
    }
153
0
    return Image();
154
0
}
155
156
} // end namespace vcl
157
158
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */