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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/gui/image/qabstractfileiconprovider.cpp