source: trunk/src/gui/itemviews/qfileiconprovider.cpp@ 608

Last change on this file since 608 was 608, checked in by Dmitry A. Kuminov, 15 years ago

guil: Fixed broken build after r607: INCL_DOSDEVIOCTL causes ALT and other one unsafe "one common word" macros to be defined, that explains why it is not part of INCL_DOS/INCL_BASE.

File size: 15.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qfileiconprovider.h"
43
44#ifndef QT_NO_FILEICONPROVIDER
45#include <qstyle.h>
46#include <qapplication.h>
47#include <qdir.h>
48#include <qpixmapcache.h>
49#if defined(Q_WS_WIN)
50# define _WIN32_IE 0x0500
51# include <qt_windows.h>
52# include <commctrl.h>
53# include <objbase.h>
54#elif defined(Q_WS_PM)
55# define INCL_DOSDEVIOCTL
56# include <qt_os2.h>
57#elif defined(Q_WS_MAC)
58# include <private/qt_cocoa_helpers_mac_p.h>
59#endif
60
61#include <private/qfunctions_p.h>
62#include <private/qguiplatformplugin_p.h>
63
64#if defined(Q_WS_X11) && !defined(Q_NO_STYLE_GTK)
65# include <private/qgtkstyle_p.h>
66# include <private/qt_x11_p.h>
67#endif
68
69#ifndef SHGFI_ADDOVERLAYS
70# define SHGFI_ADDOVERLAYS 0x000000020
71#endif
72
73QT_BEGIN_NAMESPACE
74
75/*!
76 \class QFileIconProvider
77
78 \brief The QFileIconProvider class provides file icons for the QDirModel class.
79*/
80
81/*!
82 \enum QFileIconProvider::IconType
83 \value Computer
84 \value Desktop
85 \value Trashcan
86 \value Network
87 \value Drive
88 \value Folder
89 \value File
90*/
91
92class QFileIconProviderPrivate
93{
94 Q_DECLARE_PUBLIC(QFileIconProvider)
95
96public:
97 QFileIconProviderPrivate();
98 QIcon getIcon(QStyle::StandardPixmap name) const;
99#ifdef Q_WS_WIN
100 QIcon getWinIcon(const QFileInfo &fi) const;
101#elif defined(Q_WS_MAC)
102 QIcon getMacIcon(const QFileInfo &fi) const;
103#endif
104 QFileIconProvider *q_ptr;
105 QString homePath;
106
107private:
108 QIcon file;
109 QIcon fileLink;
110 QIcon directory;
111 QIcon directoryLink;
112 QIcon harddisk;
113 QIcon floppy;
114 QIcon cdrom;
115 QIcon ram;
116 QIcon network;
117 QIcon computer;
118 QIcon desktop;
119 QIcon trashcan;
120 QIcon generic;
121 QIcon home;
122};
123
124QFileIconProviderPrivate::QFileIconProviderPrivate()
125{
126 QStyle *style = QApplication::style();
127 file = style->standardIcon(QStyle::SP_FileIcon);
128 directory = style->standardIcon(QStyle::SP_DirIcon);
129 fileLink = style->standardIcon(QStyle::SP_FileLinkIcon);
130 directoryLink = style->standardIcon(QStyle::SP_DirLinkIcon);
131 harddisk = style->standardIcon(QStyle::SP_DriveHDIcon);
132 floppy = style->standardIcon(QStyle::SP_DriveFDIcon);
133 cdrom = style->standardIcon(QStyle::SP_DriveCDIcon);
134 network = style->standardIcon(QStyle::SP_DriveNetIcon);
135 computer = style->standardIcon(QStyle::SP_ComputerIcon);
136 desktop = style->standardIcon(QStyle::SP_DesktopIcon);
137 trashcan = style->standardIcon(QStyle::SP_TrashIcon);
138 home = style->standardIcon(QStyle::SP_DirHomeIcon);
139 homePath = QDir::home().absolutePath();
140}
141
142QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const
143{
144 switch (name) {
145 case QStyle::SP_FileIcon:
146 return file;
147 case QStyle::SP_FileLinkIcon:
148 return fileLink;
149 case QStyle::SP_DirIcon:
150 return directory;
151 case QStyle::SP_DirLinkIcon:
152 return directoryLink;
153 case QStyle::SP_DriveHDIcon:
154 return harddisk;
155 case QStyle::SP_DriveFDIcon:
156 return floppy;
157 case QStyle::SP_DriveCDIcon:
158 return cdrom;
159 case QStyle::SP_DriveNetIcon:
160 return network;
161 case QStyle::SP_ComputerIcon:
162 return computer;
163 case QStyle::SP_DesktopIcon:
164 return desktop;
165 case QStyle::SP_TrashIcon:
166 return trashcan;
167 case QStyle::SP_DirHomeIcon:
168 return home;
169 default:
170 return QIcon();
171 }
172 return QIcon();
173}
174
175/*!
176 Constructs a file icon provider.
177*/
178
179QFileIconProvider::QFileIconProvider()
180 : d_ptr(new QFileIconProviderPrivate)
181{
182}
183
184/*!
185 Destroys the file icon provider.
186
187*/
188
189QFileIconProvider::~QFileIconProvider()
190{
191}
192
193/*!
194 Returns an icon set for the given \a type.
195*/
196
197QIcon QFileIconProvider::icon(IconType type) const
198{
199 Q_D(const QFileIconProvider);
200 switch (type) {
201 case Computer:
202 return d->getIcon(QStyle::SP_ComputerIcon);
203 case Desktop:
204 return d->getIcon(QStyle::SP_DesktopIcon);
205 case Trashcan:
206 return d->getIcon(QStyle::SP_TrashIcon);
207 case Network:
208 return d->getIcon(QStyle::SP_DriveNetIcon);
209 case Drive:
210 return d->getIcon(QStyle::SP_DriveHDIcon);
211 case Folder:
212 return d->getIcon(QStyle::SP_DirIcon);
213 case File:
214 return d->getIcon(QStyle::SP_FileIcon);
215 default:
216 break;
217 };
218 return QIcon();
219}
220
221#ifdef Q_WS_WIN
222QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
223{
224 QIcon retIcon;
225 const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper();
226
227 QString key;
228 if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink())
229 key = QLatin1String("qt_") + fileExtension;
230
231 QPixmap pixmap;
232 if (!key.isEmpty()) {
233 QPixmapCache::find(key, pixmap);
234 }
235
236 if (!pixmap.isNull()) {
237 retIcon.addPixmap(pixmap);
238 if (QPixmapCache::find(key + QLatin1Char('l'), pixmap))
239 retIcon.addPixmap(pixmap);
240 return retIcon;
241 }
242
243 /* We don't use the variable, but by storing it statically, we
244 * ensure CoInitialize is only called once. */
245 static HRESULT comInit = CoInitialize(NULL);
246 Q_UNUSED(comInit);
247
248 SHFILEINFO info;
249 unsigned long val = 0;
250
251 //Get the small icon
252#ifndef Q_OS_WINCE
253 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
254 sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
255#else
256 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
257 sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX);
258#endif
259 if (val) {
260 if (fileInfo.isDir() && !fileInfo.isRoot()) {
261 //using the unique icon index provided by windows save us from duplicate keys
262 key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
263 QPixmapCache::find(key, pixmap);
264 if (!pixmap.isNull()) {
265 retIcon.addPixmap(pixmap);
266 if (QPixmapCache::find(key + QLatin1Char('l'), pixmap))
267 retIcon.addPixmap(pixmap);
268 DestroyIcon(info.hIcon);
269 return retIcon;
270 }
271 }
272 if (pixmap.isNull()) {
273#ifndef Q_OS_WINCE
274 pixmap = QPixmap::fromWinHICON(info.hIcon);
275#else
276 pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL));
277#endif
278 if (!pixmap.isNull()) {
279 retIcon.addPixmap(pixmap);
280 if (!key.isEmpty())
281 QPixmapCache::insert(key, pixmap);
282 }
283 else {
284 qWarning("QFileIconProviderPrivate::getWinIcon() no small icon found");
285 }
286 }
287 DestroyIcon(info.hIcon);
288 }
289
290 //Get the big icon
291#ifndef Q_OS_WINCE
292 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
293 sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
294#else
295 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
296 sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX);
297#endif
298 if (val) {
299 if (fileInfo.isDir() && !fileInfo.isRoot()) {
300 //using the unique icon index provided by windows save us from duplicate keys
301 key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
302 }
303#ifndef Q_OS_WINCE
304 pixmap = QPixmap::fromWinHICON(info.hIcon);
305#else
306 pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL));
307#endif
308 if (!pixmap.isNull()) {
309 retIcon.addPixmap(pixmap);
310 if (!key.isEmpty())
311 QPixmapCache::insert(key + QLatin1Char('l'), pixmap);
312 }
313 else {
314 qWarning("QFileIconProviderPrivate::getWinIcon() no large icon found");
315 }
316 DestroyIcon(info.hIcon);
317 }
318 return retIcon;
319}
320
321#elif defined(Q_WS_MAC)
322QIcon QFileIconProviderPrivate::getMacIcon(const QFileInfo &fi) const
323{
324 QIcon retIcon;
325 QString fileExtension = fi.suffix().toUpper();
326 fileExtension.prepend(QLatin1String("."));
327
328 const QString keyBase = QLatin1String("qt_") + fileExtension;
329
330 QPixmap pixmap;
331 if (fi.isFile() && !fi.isExecutable() && !fi.isSymLink()) {
332 QPixmapCache::find(keyBase + QLatin1String("16"), pixmap);
333 }
334
335 if (!pixmap.isNull()) {
336 retIcon.addPixmap(pixmap);
337 if (QPixmapCache::find(keyBase + QLatin1String("32"), pixmap)) {
338 retIcon.addPixmap(pixmap);
339 if (QPixmapCache::find(keyBase + QLatin1String("64"), pixmap)) {
340 retIcon.addPixmap(pixmap);
341 if (QPixmapCache::find(keyBase + QLatin1String("128"), pixmap)) {
342 retIcon.addPixmap(pixmap);
343 return retIcon;
344 }
345 }
346 }
347 }
348
349
350 FSRef macRef;
351 OSStatus status = FSPathMakeRef(reinterpret_cast<const UInt8*>(fi.canonicalFilePath().toUtf8().constData()),
352 &macRef, 0);
353 if (status != noErr)
354 return retIcon;
355 FSCatalogInfo info;
356 HFSUniStr255 macName;
357 status = FSGetCatalogInfo(&macRef, kIconServicesCatalogInfoMask, &info, &macName, 0, 0);
358 if (status != noErr)
359 return retIcon;
360 IconRef iconRef;
361 SInt16 iconLabel;
362 status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode,
363 kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag,
364 &iconRef, &iconLabel);
365 if (status != noErr)
366 return retIcon;
367 qt_mac_constructQIconFromIconRef(iconRef, 0, &retIcon);
368 ReleaseIconRef(iconRef);
369
370 pixmap = retIcon.pixmap(16);
371 QPixmapCache::insert(keyBase + QLatin1String("16"), pixmap);
372 pixmap = retIcon.pixmap(32);
373 QPixmapCache::insert(keyBase + QLatin1String("32"), pixmap);
374 pixmap = retIcon.pixmap(64);
375 QPixmapCache::insert(keyBase + QLatin1String("64"), pixmap);
376 pixmap = retIcon.pixmap(128);
377 QPixmapCache::insert(keyBase + QLatin1String("128"), pixmap);
378
379 return retIcon;
380}
381#endif
382
383
384/*!
385 Returns an icon for the file described by \a info.
386*/
387
388QIcon QFileIconProvider::icon(const QFileInfo &info) const
389{
390 Q_D(const QFileIconProvider);
391
392 QIcon platformIcon = qt_guiPlatformPlugin()->fileSystemIcon(info);
393 if (!platformIcon.isNull())
394 return platformIcon;
395
396#if defined(Q_WS_X11) && !defined(QT_NO_STYLE_GTK)
397 if (X11->desktopEnvironment == DE_GNOME) {
398 QIcon gtkIcon = QGtkStylePrivate::getFilesystemIcon(info);
399 if (!gtkIcon.isNull())
400 return gtkIcon;
401 }
402#endif
403
404#ifdef Q_WS_MAC
405 QIcon retIcon = d->getMacIcon(info);
406 if (!retIcon.isNull())
407 return retIcon;
408#elif defined Q_WS_WIN
409 QIcon icon = d->getWinIcon(info);
410 if (!icon.isNull())
411 return icon;
412#endif
413 if (info.isRoot())
414#if defined (Q_WS_WIN) && !defined(Q_WS_WINCE)
415 {
416 UINT type = GetDriveType((wchar_t *)info.absoluteFilePath().utf16());
417
418 switch (type) {
419 case DRIVE_REMOVABLE:
420 return d->getIcon(QStyle::SP_DriveFDIcon);
421 case DRIVE_FIXED:
422 return d->getIcon(QStyle::SP_DriveHDIcon);
423 case DRIVE_REMOTE:
424 return d->getIcon(QStyle::SP_DriveNetIcon);
425 case DRIVE_CDROM:
426 return d->getIcon(QStyle::SP_DriveCDIcon);
427 case DRIVE_RAMDISK:
428 case DRIVE_UNKNOWN:
429 case DRIVE_NO_ROOT_DIR:
430 default:
431 return d->getIcon(QStyle::SP_DriveHDIcon);
432 }
433 }
434#elif defined(Q_WS_PM)
435 {
436 UCHAR ioc_parm[2];
437 BIOSPARAMETERBLOCK bpb;
438 ioc_parm[0] = 0;
439 ioc_parm[1] = info.absoluteFilePath().at(0).cell() - 'A';
440 APIRET arc = DosDevIOCtl((HFILE) - 1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
441 ioc_parm, sizeof(ioc_parm), NULL,
442 &bpb, sizeof(bpb), NULL);
443
444 if (arc == ERROR_NOT_SUPPORTED)
445 return d->getIcon(QStyle::SP_DriveNetIcon);
446
447 if (arc == NO_ERROR && bpb.bDeviceType != DEVTYPE_FIXED) {
448 if (bpb.fsDeviceAttr & 0x10) // floppy format
449 return d->getIcon(QStyle::SP_DriveFDIcon);
450 if (!(bpb.fsDeviceAttr & 0x08)) // partitionable removable
451 return d->getIcon(QStyle::SP_DriveCDIcon);
452 }
453
454 return d->getIcon(QStyle::SP_DriveHDIcon);
455 }
456#else
457 return d->getIcon(QStyle::SP_DriveHDIcon);
458#endif
459 if (info.isFile()) {
460 if (info.isSymLink())
461 return d->getIcon(QStyle::SP_FileLinkIcon);
462 else
463 return d->getIcon(QStyle::SP_FileIcon);
464 }
465 if (info.isDir()) {
466 if (info.isSymLink()) {
467 return d->getIcon(QStyle::SP_DirLinkIcon);
468 } else {
469 if (info.absoluteFilePath() == d->homePath) {
470 return d->getIcon(QStyle::SP_DirHomeIcon);
471 } else {
472 return d->getIcon(QStyle::SP_DirIcon);
473 }
474 }
475 }
476 return QIcon();
477}
478
479/*!
480 Returns the type of the file described by \a info.
481*/
482
483QString QFileIconProvider::type(const QFileInfo &info) const
484{
485 if (info.isRoot())
486 return QApplication::translate("QFileDialog", "Drive");
487 if (info.isFile()) {
488 if (!info.suffix().isEmpty())
489 return info.suffix() + QLatin1Char(' ') + QApplication::translate("QFileDialog", "File");
490 return QApplication::translate("QFileDialog", "File");
491 }
492
493 if (info.isDir())
494#ifdef Q_WS_WIN
495 return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer");
496#else
497 return QApplication::translate("QFileDialog", "Folder", "All other platforms");
498#endif
499 // Windows - "File Folder"
500 // OS X - "Folder"
501 // Konqueror - "Folder"
502 // Nautilus - "folder"
503
504 if (info.isSymLink())
505#ifdef Q_OS_MAC
506 return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder");
507#else
508 return QApplication::translate("QFileDialog", "Shortcut", "All other platforms");
509#endif
510 // OS X - "Alias"
511 // Windows - "Shortcut"
512 // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
513 // Nautilus - "link to folder" or "link to object file", same as Konqueror
514
515 return QApplication::translate("QFileDialog", "Unknown");
516}
517
518QT_END_NAMESPACE
519
520#endif
Note: See TracBrowser for help on using the repository browser.