1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qfileiconprovider.h"
41#include "qfileiconprovider_p.h"
42
43#include <qapplication.h>
44#include <qdir.h>
45#include <qpixmapcache.h>
46#include <private/qfunctions_p.h>
47#include <private/qguiapplication_p.h>
48#include <private/qicon_p.h>
49#include <private/qfilesystementry_p.h>
50#include <qpa/qplatformintegration.h>
51#include <qpa/qplatformservices.h>
52#include <qpa/qplatformtheme.h>
53
54#if defined(Q_OS_WIN)
55# include <qt_windows.h>
56# ifndef Q_OS_WINRT
57# include <commctrl.h>
58# include <objbase.h>
59# endif
60#endif
61
62QT_BEGIN_NAMESPACE
63
64/*!
65 \class QFileIconProvider
66
67 \inmodule QtWidgets
68
69 \brief The QFileIconProvider class provides file icons for the QDirModel and the QFileSystemModel classes.
70*/
71
72/*!
73 \enum QFileIconProvider::IconType
74 \value Computer
75 \value Desktop
76 \value Trashcan
77 \value Network
78 \value Drive
79 \value Folder
80 \value File
81*/
82
83
84/*!
85 \enum QFileIconProvider::Option
86 \since 5.2
87
88 \value DontUseCustomDirectoryIcons Always use the default directory icon.
89 Some platforms allow the user to set a different icon. Custom icon lookup
90 cause a big performance impact over network or removable drives.
91*/
92
93QFileIconProviderPrivate::QFileIconProviderPrivate(QFileIconProvider *q) :
94 q_ptr(q), homePath(QDir::home().absolutePath())
95{
96}
97
98QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const
99{
100 switch (name) {
101 case QStyle::SP_FileIcon:
102 if (file.isNull())
103 file = QApplication::style()->standardIcon(standardIcon: name);
104 return file;
105 case QStyle::SP_FileLinkIcon:
106 if (fileLink.isNull())
107 fileLink = QApplication::style()->standardIcon(standardIcon: name);
108 return fileLink;
109 case QStyle::SP_DirIcon:
110 if (directory.isNull())
111 directory = QApplication::style()->standardIcon(standardIcon: name);
112 return directory;
113 case QStyle::SP_DirLinkIcon:
114 if (directoryLink.isNull())
115 directoryLink = QApplication::style()->standardIcon(standardIcon: name);
116 return directoryLink;
117 case QStyle::SP_DriveHDIcon:
118 if (harddisk.isNull())
119 harddisk = QApplication::style()->standardIcon(standardIcon: name);
120 return harddisk;
121 case QStyle::SP_DriveFDIcon:
122 if (floppy.isNull())
123 floppy = QApplication::style()->standardIcon(standardIcon: name);
124 return floppy;
125 case QStyle::SP_DriveCDIcon:
126 if (cdrom.isNull())
127 cdrom = QApplication::style()->standardIcon(standardIcon: name);
128 return cdrom;
129 case QStyle::SP_DriveNetIcon:
130 if (network.isNull())
131 network = QApplication::style()->standardIcon(standardIcon: name);
132 return network;
133 case QStyle::SP_ComputerIcon:
134 if (computer.isNull())
135 computer = QApplication::style()->standardIcon(standardIcon: name);
136 return computer;
137 case QStyle::SP_DesktopIcon:
138 if (desktop.isNull())
139 desktop = QApplication::style()->standardIcon(standardIcon: name);
140 return desktop;
141 case QStyle::SP_TrashIcon:
142 if (trashcan.isNull())
143 trashcan = QApplication::style()->standardIcon(standardIcon: name);
144 return trashcan;
145 case QStyle::SP_DirHomeIcon:
146 if (home.isNull())
147 home = QApplication::style()->standardIcon(standardIcon: name);
148 return home;
149 default:
150 return QIcon();
151 }
152 return QIcon();
153}
154
155/*!
156 Constructs a file icon provider.
157*/
158
159QFileIconProvider::QFileIconProvider()
160 : d_ptr(new QFileIconProviderPrivate(this))
161{
162}
163
164/*!
165 Destroys the file icon provider.
166
167*/
168
169QFileIconProvider::~QFileIconProvider()
170{
171}
172
173/*!
174 \since 5.2
175 Sets \a options that affect the icon provider.
176 \sa options()
177*/
178
179void QFileIconProvider::setOptions(QFileIconProvider::Options options)
180{
181 Q_D(QFileIconProvider);
182 d->options = options;
183}
184
185/*!
186 \since 5.2
187 Returns all the options that affect the icon provider.
188 By default, all options are disabled.
189 \sa setOptions()
190*/
191
192QFileIconProvider::Options QFileIconProvider::options() const
193{
194 Q_D(const QFileIconProvider);
195 return d->options;
196}
197
198/*!
199 Returns an icon set for the given \a type.
200*/
201
202QIcon QFileIconProvider::icon(IconType type) const
203{
204 Q_D(const QFileIconProvider);
205 switch (type) {
206 case Computer:
207 return d->getIcon(name: QStyle::SP_ComputerIcon);
208 case Desktop:
209 return d->getIcon(name: QStyle::SP_DesktopIcon);
210 case Trashcan:
211 return d->getIcon(name: QStyle::SP_TrashIcon);
212 case Network:
213 return d->getIcon(name: QStyle::SP_DriveNetIcon);
214 case Drive:
215 return d->getIcon(name: QStyle::SP_DriveHDIcon);
216 case Folder:
217 return d->getIcon(name: QStyle::SP_DirIcon);
218 case File:
219 return d->getIcon(name: QStyle::SP_FileIcon);
220 default:
221 break;
222 };
223 return QIcon();
224}
225
226static inline QPlatformTheme::IconOptions toThemeIconOptions(QFileIconProvider::Options options)
227{
228 QPlatformTheme::IconOptions result;
229 if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
230 result |= QPlatformTheme::DontUseCustomDirectoryIcons;
231 return result;
232}
233
234QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
235{
236 return QGuiApplicationPrivate::platformTheme()->fileIcon(fileInfo: fi, iconOptions: toThemeIconOptions(options));
237}
238
239/*!
240 Returns an icon for the file described by \a info.
241*/
242
243QIcon QFileIconProvider::icon(const QFileInfo &info) const
244{
245 Q_D(const QFileIconProvider);
246
247 QIcon retIcon = d->getIcon(fi: info);
248 if (!retIcon.isNull())
249 return retIcon;
250
251 const QString &path = info.absoluteFilePath();
252 if (path.isEmpty() || QFileSystemEntry::isRootPath(path))
253#if defined (Q_OS_WIN) && !defined(Q_OS_WINRT)
254 {
255 UINT type = GetDriveType(reinterpret_cast<const wchar_t *>(path.utf16()));
256
257 switch (type) {
258 case DRIVE_REMOVABLE:
259 return d->getIcon(QStyle::SP_DriveFDIcon);
260 case DRIVE_FIXED:
261 return d->getIcon(QStyle::SP_DriveHDIcon);
262 case DRIVE_REMOTE:
263 return d->getIcon(QStyle::SP_DriveNetIcon);
264 case DRIVE_CDROM:
265 return d->getIcon(QStyle::SP_DriveCDIcon);
266 case DRIVE_RAMDISK:
267 case DRIVE_UNKNOWN:
268 case DRIVE_NO_ROOT_DIR:
269 default:
270 return d->getIcon(QStyle::SP_DriveHDIcon);
271 }
272 }
273#else
274 return d->getIcon(name: QStyle::SP_DriveHDIcon);
275#endif
276
277 if (info.isFile()) {
278 if (info.isSymLink())
279 return d->getIcon(name: QStyle::SP_FileLinkIcon);
280 else
281 return d->getIcon(name: QStyle::SP_FileIcon);
282 }
283 if (info.isDir()) {
284 if (info.isSymLink()) {
285 return d->getIcon(name: QStyle::SP_DirLinkIcon);
286 } else {
287 if (info.absoluteFilePath() == d->homePath) {
288 return d->getIcon(name: QStyle::SP_DirHomeIcon);
289 } else {
290 return d->getIcon(name: QStyle::SP_DirIcon);
291 }
292 }
293 }
294 return QIcon();
295}
296
297/*!
298 Returns the type of the file described by \a info.
299*/
300
301QString QFileIconProvider::type(const QFileInfo &info) const
302{
303 if (QFileSystemEntry::isRootPath(path: info.absoluteFilePath()))
304 return QApplication::translate(context: "QFileDialog", key: "Drive");
305 if (info.isFile()) {
306 if (!info.suffix().isEmpty()) {
307 //: %1 is a file name suffix, for example txt
308 return QApplication::translate(context: "QFileDialog", key: "%1 File").arg(a: info.suffix());
309 }
310 return QApplication::translate(context: "QFileDialog", key: "File");
311 }
312
313 if (info.isDir())
314#ifdef Q_OS_WIN
315 return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer");
316#else
317 return QApplication::translate(context: "QFileDialog", key: "Folder", disambiguation: "All other platforms");
318#endif
319 // Windows - "File Folder"
320 // OS X - "Folder"
321 // Konqueror - "Folder"
322 // Nautilus - "folder"
323
324 if (info.isSymLink())
325#ifdef Q_OS_MAC
326 return QApplication::translate("QFileDialog", "Alias", "OS X Finder");
327#else
328 return QApplication::translate(context: "QFileDialog", key: "Shortcut", disambiguation: "All other platforms");
329#endif
330 // OS X - "Alias"
331 // Windows - "Shortcut"
332 // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
333 // Nautilus - "link to folder" or "link to object file", same as Konqueror
334
335 return QApplication::translate(context: "QFileDialog", key: "Unknown");
336}
337
338QT_END_NAMESPACE
339

source code of qtbase/src/widgets/itemviews/qfileiconprovider.cpp