Coverage Report

Created: 2026-10-27 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/image/qabstractfileiconprovider.cpp
Line
Count
Source
1
// Copyright (C) 2020 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#include "qabstractfileiconprovider.h"
6
7
#include <qguiapplication.h>
8
#include <private/qguiapplication_p.h>
9
#include <qpa/qplatformtheme.h>
10
#include <qfileinfo.h>
11
#include <qicon.h>
12
#if QT_CONFIG(mimetype)
13
#include <qmimedatabase.h>
14
#endif
15
16
17
#include <private/qabstractfileiconprovider_p.h>
18
#include <private/qfilesystementry_p.h>
19
20
QT_BEGIN_NAMESPACE
21
22
using namespace Qt::StringLiterals;
23
24
QAbstractFileIconProviderPrivate::QAbstractFileIconProviderPrivate(QAbstractFileIconProvider *q)
25
0
    : q_ptr(q)
26
0
{}
27
28
0
QAbstractFileIconProviderPrivate::~QAbstractFileIconProviderPrivate() = default;
29
30
using IconTypeCache = QHash<QAbstractFileIconProvider::IconType, QIcon>;
31
Q_GLOBAL_STATIC(IconTypeCache, iconTypeCache)
32
33
void QAbstractFileIconProviderPrivate::clearIconTypeCache()
34
0
{
35
0
    iconTypeCache()->clear();
36
0
}
37
38
QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(QAbstractFileIconProvider::IconType type) const
39
0
{
40
0
    auto theme = QGuiApplicationPrivate::platformTheme();
41
0
    if (theme == nullptr)
42
0
        return {};
43
44
0
    if (theme->themeHint(QPlatformTheme::PreferFileIconFromTheme).toBool()) {
45
0
        const QIcon result = getIconThemeIcon(type);
46
0
        if (!result.isNull())
47
0
            return result;
48
0
    }
49
50
0
    auto &cache = *iconTypeCache();
51
0
    auto it = cache.find(type);
52
0
    if (it == cache.end()) {
53
0
        const auto sp = [&]() -> QPlatformTheme::StandardPixmap {
54
0
            switch (type) {
55
0
            case QAbstractFileIconProvider::Computer:
56
0
                return QPlatformTheme::ComputerIcon;
57
0
            case QAbstractFileIconProvider::Desktop:
58
0
                return QPlatformTheme::DesktopIcon;
59
0
            case QAbstractFileIconProvider::Trashcan:
60
0
                return QPlatformTheme::TrashIcon;
61
0
            case QAbstractFileIconProvider::Network:
62
0
                return QPlatformTheme::DriveNetIcon;
63
0
            case QAbstractFileIconProvider::Drive:
64
0
                return QPlatformTheme::DriveHDIcon;
65
0
            case QAbstractFileIconProvider::Folder:
66
0
                return QPlatformTheme::DirIcon;
67
0
            case QAbstractFileIconProvider::File:
68
0
                break;
69
            // no default on purpose; we want warnings when the type enum is extended
70
0
            }
71
0
            return QPlatformTheme::FileIcon;
72
0
        }();
73
74
0
        const auto sizesHint = theme->themeHint(QPlatformTheme::IconPixmapSizes);
75
0
        auto sizes = sizesHint.value<QList<QSize>>();
76
0
        if (sizes.isEmpty())
77
0
            sizes.append({64, 64});
78
79
0
        QIcon icon;
80
0
        for (const auto &size : std::as_const(sizes))
81
0
            icon.addPixmap(theme->standardPixmap(sp, size));
82
0
        it = cache.insert(type, icon);
83
0
    }
84
0
    return it.value();
85
0
}
86
87
QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(QAbstractFileIconProvider::IconType type) const
88
0
{
89
0
    switch (type) {
90
0
    case QAbstractFileIconProvider::Computer:
91
0
        return QIcon::fromTheme("computer"_L1);
92
0
    case QAbstractFileIconProvider::Desktop:
93
0
        return QIcon::fromTheme("user-desktop"_L1);
94
0
    case QAbstractFileIconProvider::Trashcan:
95
0
        return QIcon::fromTheme("user-trash"_L1);
96
0
    case QAbstractFileIconProvider::Network:
97
0
        return QIcon::fromTheme("network-workgroup"_L1);
98
0
    case QAbstractFileIconProvider::Drive:
99
0
        return QIcon::fromTheme("drive-harddisk"_L1);
100
0
    case QAbstractFileIconProvider::Folder:
101
0
        return QIcon::fromTheme("folder"_L1);
102
0
    case QAbstractFileIconProvider::File:
103
0
        return QIcon::fromTheme("text-x-generic"_L1);
104
        // no default on purpose; we want warnings when the type enum is extended
105
0
    }
106
0
    return QIcon::fromTheme("text-x-generic"_L1);
107
0
}
108
109
static inline QPlatformTheme::IconOptions toThemeIconOptions(QAbstractFileIconProvider::Options options)
110
0
{
111
0
    QPlatformTheme::IconOptions result;
112
0
    if (options.testFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons))
113
0
        result |= QPlatformTheme::DontUseCustomDirectoryIcons;
114
0
    return result;
115
0
}
116
117
QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(const QFileInfo &info) const
118
0
{
119
0
    if (auto theme = QGuiApplicationPrivate::platformTheme()) {
120
0
        if (theme->themeHint(QPlatformTheme::PreferFileIconFromTheme).toBool()) {
121
0
            const QIcon result = getIconThemeIcon(info);
122
0
            if (!result.isNull())
123
0
                return result;
124
0
        }
125
0
        return theme->fileIcon(info, toThemeIconOptions(options));
126
0
    }
127
0
    return {};
128
0
}
129
130
QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(const QFileInfo &info) const
131
0
{
132
0
    if (info.isRoot())
133
0
        return getIconThemeIcon(QAbstractFileIconProvider::Drive);
134
0
    if (info.isDir())
135
0
        return getIconThemeIcon(QAbstractFileIconProvider::Folder);
136
0
#if QT_CONFIG(mimetype)
137
0
    return QIcon::fromTheme(mimeDatabase.mimeTypeForFile(info).iconName());
138
#else
139
    return QIcon::fromTheme("text-x-generic"_L1);
140
#endif
141
0
}
142
143
/*!
144
  \class QAbstractFileIconProvider
145
146
  \inmodule QtGui
147
  \since 6.0
148
149
  \brief The QAbstractFileIconProvider class provides file icons for the QFileSystemModel class.
150
*/
151
152
/*!
153
  \enum QAbstractFileIconProvider::IconType
154
155
  \value Computer   The icon used for the computing device as a whole
156
  \value Desktop    The icon for the special "Desktop" directory of the user
157
  \value Trashcan   The icon for the user's "Trash" place in the desktop's file manager
158
  \value Network    The icon for the “Network Servers” place in the desktop's file manager,
159
                    and workgroups within the network
160
  \value Drive      The icon used for disk drives
161
  \value Folder     The standard folder icon used to represent directories on local filesystems
162
  \value File       The icon used for generic text file types
163
*/
164
165
/*!
166
    \enum QAbstractFileIconProvider::Option
167
168
    \value DontUseCustomDirectoryIcons Always use the default directory icon.
169
    Some platforms allow the user to set a different icon. Custom icon lookup
170
    cause a big performance impact over network or removable drives.
171
*/
172
173
/*!
174
  Constructs a file icon provider.
175
*/
176
QAbstractFileIconProvider::QAbstractFileIconProvider()
177
0
    : d_ptr(new QAbstractFileIconProviderPrivate(this))
178
0
{
179
0
}
180
181
/*!
182
  \internal
183
*/
184
QAbstractFileIconProvider::QAbstractFileIconProvider(QAbstractFileIconProviderPrivate &dd)
185
0
    : d_ptr(&dd)
186
0
{}
187
188
/*!
189
  Destroys the file icon provider.
190
*/
191
192
0
QAbstractFileIconProvider::~QAbstractFileIconProvider() = default;
193
194
195
/*!
196
    Sets \a options that affect the icon provider.
197
    \sa options()
198
*/
199
200
void QAbstractFileIconProvider::setOptions(QAbstractFileIconProvider::Options options)
201
0
{
202
0
    Q_D(QAbstractFileIconProvider);
203
0
    d->options = options;
204
0
}
205
206
/*!
207
    Returns all the options that affect the icon provider.
208
    By default, all options are disabled.
209
    \sa setOptions()
210
*/
211
212
QAbstractFileIconProvider::Options QAbstractFileIconProvider::options() const
213
0
{
214
0
    Q_D(const QAbstractFileIconProvider);
215
0
    return d->options;
216
0
}
217
218
/*!
219
  Returns an icon set for the given \a type, using the current
220
  icon theme.
221
222
  \sa QIcon::fromTheme
223
*/
224
225
QIcon QAbstractFileIconProvider::icon(IconType type) const
226
0
{
227
0
    Q_D(const QAbstractFileIconProvider);
228
0
    return d->getPlatformThemeIcon(type);
229
0
}
230
231
/*!
232
  Returns an icon for the file described by \a info, using the
233
  current icon theme.
234
235
  \sa QIcon::fromTheme
236
*/
237
238
QIcon QAbstractFileIconProvider::icon(const QFileInfo &info) const
239
0
{
240
0
    Q_D(const QAbstractFileIconProvider);
241
0
    return d->getPlatformThemeIcon(info);
242
0
}
243
244
245
QString QAbstractFileIconProviderPrivate::getFileType(const QFileInfo &info)
246
0
{
247
0
    if (QFileSystemEntry::isRootPath(info.absoluteFilePath()))
248
0
        return QGuiApplication::translate("QAbstractFileIconProvider", "Drive");
249
0
    if (info.isFile()) {
250
0
#if QT_CONFIG(mimetype)
251
0
        const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(info);
252
0
        return mimeType.comment().isEmpty() ? mimeType.name() : mimeType.comment();
253
#else
254
        return QGuiApplication::translate("QAbstractFileIconProvider", "File");
255
#endif
256
0
    }
257
258
0
    if (info.isDir())
259
#ifdef Q_OS_WIN
260
        return QGuiApplication::translate("QAbstractFileIconProvider", "File Folder", "Match Windows Explorer");
261
#else
262
0
        return QGuiApplication::translate("QAbstractFileIconProvider", "Folder", "All other platforms");
263
0
#endif
264
    // Windows   - "File Folder"
265
    // macOS     - "Folder"
266
    // Konqueror - "Folder"
267
    // Nautilus  - "folder"
268
269
0
    if (info.isSymLink())
270
#ifdef Q_OS_MACOS
271
        return QGuiApplication::translate("QAbstractFileIconProvider", "Alias", "macOS Finder");
272
#else
273
0
        return QGuiApplication::translate("QAbstractFileIconProvider", "Shortcut", "All other platforms");
274
0
#endif
275
    // macOS     - "Alias"
276
    // Windows   - "Shortcut"
277
    // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
278
    // Nautilus  - "link to folder" or "link to object file", same as Konqueror
279
280
0
    return QGuiApplication::translate("QAbstractFileIconProvider", "Unknown");
281
0
}
282
283
/*!
284
  Returns the type of the file described by \a info.
285
*/
286
287
QString QAbstractFileIconProvider::type(const QFileInfo &info) const
288
0
{
289
0
    return QAbstractFileIconProviderPrivate::getFileType(info);
290
0
}
291
292
QT_END_NAMESPACE
293
294
#include "moc_qabstractfileiconprovider.cpp"