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 | |
62 | QT_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 | |
93 | QFileIconProviderPrivate::QFileIconProviderPrivate(QFileIconProvider *q) : |
94 | q_ptr(q), homePath(QDir::home().absolutePath()) |
95 | { |
96 | } |
97 | |
98 | QIcon 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 | |
159 | QFileIconProvider::QFileIconProvider() |
160 | : d_ptr(new QFileIconProviderPrivate(this)) |
161 | { |
162 | } |
163 | |
164 | /*! |
165 | Destroys the file icon provider. |
166 | |
167 | */ |
168 | |
169 | QFileIconProvider::~QFileIconProvider() |
170 | { |
171 | } |
172 | |
173 | /*! |
174 | \since 5.2 |
175 | Sets \a options that affect the icon provider. |
176 | \sa options() |
177 | */ |
178 | |
179 | void 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 | |
192 | QFileIconProvider::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 | |
202 | QIcon 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 | |
226 | static 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 | |
234 | QIcon 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 | |
243 | QIcon 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 | |
301 | QString 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 | |
338 | QT_END_NAMESPACE |
339 | |