Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/app/IconThemeSelector.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 <comphelper/lok.hxx>
11
12
#include <IconThemeSelector.hxx>
13
14
#include <tools/color.hxx>
15
#include <vcl/IconThemeInfo.hxx>
16
#include <vcl/settings.hxx>
17
#include <vcl/svapp.hxx>
18
#include <config_mpl.h>
19
20
#include <algorithm>
21
22
namespace vcl {
23
24
namespace {
25
26
    class SameTheme
27
    {
28
    private:
29
        const OUString& m_rThemeId;
30
    public:
31
266
        explicit SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {}
32
        bool operator()(const vcl::IconThemeInfo &rInfo)
33
0
        {
34
0
            return m_rThemeId == rInfo.GetThemeId();
35
0
        }
36
    };
37
38
bool icon_theme_is_in_installed_themes(const OUString& theme,
39
        const std::vector<IconThemeInfo>& installedThemes)
40
266
{
41
266
    return std::any_of(installedThemes.begin(), installedThemes.end(),
42
266
                       SameTheme(theme));
43
266
}
44
45
} // end anonymous namespace
46
47
IconThemeSelector::IconThemeSelector()
48
1.20k
    : mUseHighContrastTheme(false)
49
1.20k
    , mPreferDarkIconTheme(false)
50
1.20k
{
51
1.20k
}
52
53
/*static*/ OUString
54
IconThemeSelector::GetIconThemeForDesktopEnvironment(const OUString& desktopEnvironment, bool bPreferDarkIconTheme)
55
0
{
56
0
    if (comphelper::LibreOfficeKit::isActive())
57
0
    {
58
0
        if (!bPreferDarkIconTheme)
59
0
            return u"colibre"_ustr;
60
0
        else
61
0
            return u"colibre_dark"_ustr;
62
0
    }
63
64
#ifdef _WIN32
65
    (void)desktopEnvironment;
66
    if (!bPreferDarkIconTheme)
67
        return "colibre";
68
    else
69
        return "colibre_dark";
70
#else
71
0
    OUString r;
72
0
    if ( desktopEnvironment.equalsIgnoreAsciiCase("plasma5") ||
73
0
         desktopEnvironment.equalsIgnoreAsciiCase("plasma6") ||
74
0
         desktopEnvironment.equalsIgnoreAsciiCase("lxqt") ) {
75
0
        if (!bPreferDarkIconTheme)
76
0
            r = "breeze";
77
0
        else
78
0
            r = "breeze_dark";
79
0
    }
80
0
    else if ( desktopEnvironment.equalsIgnoreAsciiCase("macosx") ) {
81
0
        if (!bPreferDarkIconTheme)
82
0
            r = "sukapura_svg";
83
0
        else
84
0
            r = "sukapura_dark_svg";
85
0
    }
86
0
    else if ( desktopEnvironment.equalsIgnoreAsciiCase("gnome") ||
87
0
         desktopEnvironment.equalsIgnoreAsciiCase("mate") ||
88
0
         desktopEnvironment.equalsIgnoreAsciiCase("unity") ) {
89
0
        if (!bPreferDarkIconTheme)
90
0
            r = "elementary";
91
0
        else
92
0
            r = "sifr_dark";
93
0
    } else
94
0
    {
95
0
        if (!bPreferDarkIconTheme)
96
0
            r = FALLBACK_LIGHT_ICON_THEME_ID;
97
0
        else
98
0
            r = FALLBACK_DARK_ICON_THEME_ID;
99
0
    }
100
0
    return r;
101
0
#endif // _WIN32
102
0
}
103
104
OUString
105
IconThemeSelector::SelectIconThemeForDesktopEnvironment(
106
        const std::vector<IconThemeInfo>& installedThemes,
107
        const OUString& desktopEnvironment) const
108
0
{
109
0
    if (!mPreferredIconTheme.isEmpty()) {
110
0
        if (icon_theme_is_in_installed_themes(mPreferredIconTheme, installedThemes)) {
111
0
            return mPreferredIconTheme;
112
0
        }
113
0
    }
114
115
0
    OUString themeForDesktop = GetIconThemeForDesktopEnvironment(desktopEnvironment, mPreferDarkIconTheme);
116
0
    if (icon_theme_is_in_installed_themes(themeForDesktop, installedThemes)) {
117
0
        return themeForDesktop;
118
0
    }
119
120
0
    return ReturnFallback(installedThemes);
121
0
}
122
123
OUString
124
IconThemeSelector::SelectIconTheme(
125
        const std::vector<IconThemeInfo>& installedThemes,
126
        const OUString& theme) const
127
266
{
128
266
    if (mUseHighContrastTheme) {
129
0
        const Color aCol(Application::GetSettings().GetStyleSettings().GetWindowColor());
130
0
        const OUString name(aCol.IsDark() ? IconThemeInfo::HIGH_CONTRAST_ID_DARK
131
0
                                          : IconThemeInfo::HIGH_CONTRAST_ID_BRIGHT);
132
0
        if (icon_theme_is_in_installed_themes(name, installedThemes)) {
133
0
            return name;
134
0
        }
135
0
    }
136
137
266
    if (icon_theme_is_in_installed_themes(theme, installedThemes)) {
138
0
        return theme;
139
0
    }
140
141
266
    return ReturnFallback(installedThemes);
142
266
}
143
144
void
145
IconThemeSelector::SetUseHighContrastTheme(bool v)
146
0
{
147
0
    mUseHighContrastTheme = v;
148
0
}
149
150
bool
151
IconThemeSelector::SetPreferredIconTheme(const OUString& theme, bool bDarkIconTheme)
152
0
{
153
    // lower case theme name, and (tdf#120175) replace - with _
154
    // see icon-themes/README
155
0
    OUString sIconTheme = theme.toAsciiLowerCase().replace('-','_');
156
157
0
    const bool bChanged = mPreferredIconTheme != sIconTheme || mPreferDarkIconTheme != bDarkIconTheme;
158
0
    if (bChanged)
159
0
    {
160
0
        mPreferredIconTheme = sIconTheme;
161
0
        mPreferDarkIconTheme = bDarkIconTheme;
162
0
    }
163
0
    return bChanged;
164
0
}
165
166
/*static*/ OUString
167
IconThemeSelector::ReturnFallback(const std::vector<IconThemeInfo>& installedThemes)
168
266
{
169
266
    if (!installedThemes.empty()) {
170
0
        return installedThemes.front().GetThemeId();
171
0
    }
172
266
    else {
173
266
        return FALLBACK_LIGHT_ICON_THEME_ID;
174
266
    }
175
266
}
176
177
} /* namespace vcl */
178
179
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */