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

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

trunk: Merged in qt 4.6.1 sources.

File size: 15.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
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 qt-info@nokia.com.
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_MAC)
55# include <private/qt_cocoa_helpers_mac_p.h>
56#endif
57
58#include <private/qfunctions_p.h>
59#include <private/qguiplatformplugin_p.h>
60
61#if defined(Q_WS_X11) && !defined(Q_NO_STYLE_GTK)
62# include <private/qgtkstyle_p.h>
63# include <private/qt_x11_p.h>
64#endif
65
66#ifndef SHGFI_ADDOVERLAYS
67# define SHGFI_ADDOVERLAYS 0x000000020
68#endif
69
70QT_BEGIN_NAMESPACE
71
72/*!
73 \class QFileIconProvider
74
75 \brief The QFileIconProvider class provides file icons for the QDirModel class.
76*/
77
78/*!
79 \enum QFileIconProvider::IconType
80 \value Computer
81 \value Desktop
82 \value Trashcan
83 \value Network
84 \value Drive
85 \value Folder
86 \value File
87*/
88
89class QFileIconProviderPrivate
90{
91 Q_DECLARE_PUBLIC(QFileIconProvider)
92
93public:
94 QFileIconProviderPrivate();
95 QIcon getIcon(QStyle::StandardPixmap name) const;
96#ifdef Q_WS_WIN
97 QIcon getWinIcon(const QFileInfo &fi) const;
98#elif defined(Q_WS_MAC)
99 QIcon getMacIcon(const QFileInfo &fi) const;
100#endif
101 QFileIconProvider *q_ptr;
102 QString homePath;
103
104private:
105 QIcon file;
106 QIcon fileLink;
107 QIcon directory;
108 QIcon directoryLink;
109 QIcon harddisk;
110 QIcon floppy;
111 QIcon cdrom;
112 QIcon ram;
113 QIcon network;
114 QIcon computer;
115 QIcon desktop;
116 QIcon trashcan;
117 QIcon generic;
118 QIcon home;
119};
120
121QFileIconProviderPrivate::QFileIconProviderPrivate()
122{
123 QStyle *style = QApplication::style();
124 file = style->standardIcon(QStyle::SP_FileIcon);
125 directory = style->standardIcon(QStyle::SP_DirIcon);
126 fileLink = style->standardIcon(QStyle::SP_FileLinkIcon);
127 directoryLink = style->standardIcon(QStyle::SP_DirLinkIcon);
128 harddisk = style->standardIcon(QStyle::SP_DriveHDIcon);
129 floppy = style->standardIcon(QStyle::SP_DriveFDIcon);
130 cdrom = style->standardIcon(QStyle::SP_DriveCDIcon);
131 network = style->standardIcon(QStyle::SP_DriveNetIcon);
132 computer = style->standardIcon(QStyle::SP_ComputerIcon);
133 desktop = style->standardIcon(QStyle::SP_DesktopIcon);
134 trashcan = style->standardIcon(QStyle::SP_TrashIcon);
135 home = style->standardIcon(QStyle::SP_DirHomeIcon);
136 homePath = QDir::home().absolutePath();
137}
138
139QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const
140{
141 switch (name) {
142 case QStyle::SP_FileIcon:
143 return file;
144 case QStyle::SP_FileLinkIcon:
145 return fileLink;
146 case QStyle::SP_DirIcon:
147 return directory;
148 case QStyle::SP_DirLinkIcon:
149 return directoryLink;
150 case QStyle::SP_DriveHDIcon:
151 return harddisk;
152 case QStyle::SP_DriveFDIcon:
153 return floppy;
154 case QStyle::SP_DriveCDIcon:
155 return cdrom;
156 case QStyle::SP_DriveNetIcon:
157 return network;
158 case QStyle::SP_ComputerIcon:
159 return computer;
160 case QStyle::SP_DesktopIcon:
161 return desktop;
162 case QStyle::SP_TrashIcon:
163 return trashcan;
164 case QStyle::SP_DirHomeIcon:
165 return home;
166 default:
167 return QIcon();
168 }
169 return QIcon();
170}
171
172/*!
173 Constructs a file icon provider.
174*/
175
176QFileIconProvider::QFileIconProvider()
177 : d_ptr(new QFileIconProviderPrivate)
178{
179}
180
181/*!
182 Destroys the file icon provider.
183
184*/
185
186QFileIconProvider::~QFileIconProvider()
187{
188}
189
190/*!
191 Returns an icon set for the given \a type.
192*/
193
194QIcon QFileIconProvider::icon(IconType type) const
195{
196 Q_D(const QFileIconProvider);
197 switch (type) {
198 case Computer:
199 return d->getIcon(QStyle::SP_ComputerIcon);
200 case Desktop:
201 return d->getIcon(QStyle::SP_DesktopIcon);
202 case Trashcan:
203 return d->getIcon(QStyle::SP_TrashIcon);
204 case Network:
205 return d->getIcon(QStyle::SP_DriveNetIcon);
206 case Drive:
207 return d->getIcon(QStyle::SP_DriveHDIcon);
208 case Folder:
209 return d->getIcon(QStyle::SP_DirIcon);
210 case File:
211 return d->getIcon(QStyle::SP_FileIcon);
212 default:
213 break;
214 };
215 return QIcon();
216}
217
218#ifdef Q_WS_WIN
219QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
220{
221 QIcon retIcon;
222 const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper();
223
224 QString key;
225 if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink())
226 key = QLatin1String("qt_") + fileExtension;
227
228 QPixmap pixmap;
229 if (!key.isEmpty()) {
230 QPixmapCache::find(key, pixmap);
231 }
232
233 if (!pixmap.isNull()) {
234 retIcon.addPixmap(pixmap);
235 if (QPixmapCache::find(key + QLatin1Char('l'), pixmap))
236 retIcon.addPixmap(pixmap);
237 return retIcon;
238 }
239
240 /* We don't use the variable, but by storing it statically, we
241 * ensure CoInitialize is only called once. */
242 static HRESULT comInit = CoInitialize(NULL);
243 Q_UNUSED(comInit);
244
245 SHFILEINFO info;
246 unsigned long val = 0;
247
248 //Get the small icon
249#ifndef Q_OS_WINCE
250 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
251 sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
252#else
253 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
254 sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX);
255#endif
256 if (val) {
257 if (fileInfo.isDir() && !fileInfo.isRoot()) {
258 //using the unique icon index provided by windows save us from duplicate keys
259 key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
260 QPixmapCache::find(key, pixmap);
261 if (!pixmap.isNull()) {
262 retIcon.addPixmap(pixmap);
263 if (QPixmapCache::find(key + QLatin1Char('l'), pixmap))
264 retIcon.addPixmap(pixmap);
265 DestroyIcon(info.hIcon);
266 return retIcon;
267 }
268 }
269 if (pixmap.isNull()) {
270#ifndef Q_OS_WINCE
271 pixmap = QPixmap::fromWinHICON(info.hIcon);
272#else
273 pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL));
274#endif
275 if (!pixmap.isNull()) {
276 retIcon.addPixmap(pixmap);
277 if (!key.isEmpty())
278 QPixmapCache::insert(key, pixmap);
279 }
280 else {
281 qWarning("QFileIconProviderPrivate::getWinIcon() no small icon found");
282 }
283 }
284 DestroyIcon(info.hIcon);
285 }
286
287 //Get the big icon
288#ifndef Q_OS_WINCE
289 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
290 sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS);
291#else
292 val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
293 sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX);
294#endif
295 if (val) {
296 if (fileInfo.isDir() && !fileInfo.isRoot()) {
297 //using the unique icon index provided by windows save us from duplicate keys
298 key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
299 }
300#ifndef Q_OS_WINCE
301 pixmap = QPixmap::fromWinHICON(info.hIcon);
302#else
303 pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL));
304#endif
305 if (!pixmap.isNull()) {
306 retIcon.addPixmap(pixmap);
307 if (!key.isEmpty())
308 QPixmapCache::insert(key + QLatin1Char('l'), pixmap);
309 }
310 else {
311 qWarning("QFileIconProviderPrivate::getWinIcon() no large icon found");
312 }
313 DestroyIcon(info.hIcon);
314 }
315 return retIcon;
316}
317
318#elif defined(Q_WS_MAC)
319QIcon QFileIconProviderPrivate::getMacIcon(const QFileInfo &fi) const
320{
321 QIcon retIcon;
322 QString fileExtension = fi.suffix().toUpper();
323 fileExtension.prepend(QLatin1String("."));
324
325 const QString keyBase = QLatin1String("qt_") + fileExtension;
326
327 QPixmap pixmap;
328 if (fi.isFile() && !fi.isExecutable() && !fi.isSymLink()) {
329 QPixmapCache::find(keyBase + QLatin1String("16"), pixmap);
330 }
331
332 if (!pixmap.isNull()) {
333 retIcon.addPixmap(pixmap);
334 if (QPixmapCache::find(keyBase + QLatin1String("32"), pixmap)) {
335 retIcon.addPixmap(pixmap);
336 if (QPixmapCache::find(keyBase + QLatin1String("64"), pixmap)) {
337 retIcon.addPixmap(pixmap);
338 if (QPixmapCache::find(keyBase + QLatin1String("128"), pixmap)) {
339 retIcon.addPixmap(pixmap);
340 return retIcon;
341 }
342 }
343 }
344 }
345
346
347 FSRef macRef;
348 OSStatus status = FSPathMakeRef(reinterpret_cast<const UInt8*>(fi.canonicalFilePath().toUtf8().constData()),
349 &macRef, 0);
350 if (status != noErr)
351 return retIcon;
352 FSCatalogInfo info;
353 HFSUniStr255 macName;
354 status = FSGetCatalogInfo(&macRef, kIconServicesCatalogInfoMask, &info, &macName, 0, 0);
355 if (status != noErr)
356 return retIcon;
357 IconRef iconRef;
358 SInt16 iconLabel;
359 status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode,
360 kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag,
361 &iconRef, &iconLabel);
362 if (status != noErr)
363 return retIcon;
364 qt_mac_constructQIconFromIconRef(iconRef, 0, &retIcon);
365 ReleaseIconRef(iconRef);
366
367 pixmap = retIcon.pixmap(16);
368 QPixmapCache::insert(keyBase + QLatin1String("16"), pixmap);
369 pixmap = retIcon.pixmap(32);
370 QPixmapCache::insert(keyBase + QLatin1String("32"), pixmap);
371 pixmap = retIcon.pixmap(64);
372 QPixmapCache::insert(keyBase + QLatin1String("64"), pixmap);
373 pixmap = retIcon.pixmap(128);
374 QPixmapCache::insert(keyBase + QLatin1String("128"), pixmap);
375
376 return retIcon;
377}
378#endif
379
380
381/*!
382 Returns an icon for the file described by \a info.
383*/
384
385QIcon QFileIconProvider::icon(const QFileInfo &info) const
386{
387 Q_D(const QFileIconProvider);
388
389 QIcon platformIcon = qt_guiPlatformPlugin()->fileSystemIcon(info);
390 if (!platformIcon.isNull())
391 return platformIcon;
392
393#if defined(Q_WS_X11) && !defined(QT_NO_STYLE_GTK)
394 if (X11->desktopEnvironment == DE_GNOME) {
395 QIcon gtkIcon = QGtkStylePrivate::getFilesystemIcon(info);
396 if (!gtkIcon.isNull())
397 return gtkIcon;
398 }
399#endif
400
401#ifdef Q_WS_MAC
402 QIcon retIcon = d->getMacIcon(info);
403 if (!retIcon.isNull())
404 return retIcon;
405#elif defined Q_WS_WIN
406 QIcon icon = d->getWinIcon(info);
407 if (!icon.isNull())
408 return icon;
409#endif
410 if (info.isRoot())
411#if defined (Q_WS_WIN) && !defined(Q_WS_WINCE)
412 {
413 UINT type = GetDriveType((wchar_t *)info.absoluteFilePath().utf16());
414
415 switch (type) {
416 case DRIVE_REMOVABLE:
417 return d->getIcon(QStyle::SP_DriveFDIcon);
418 case DRIVE_FIXED:
419 return d->getIcon(QStyle::SP_DriveHDIcon);
420 case DRIVE_REMOTE:
421 return d->getIcon(QStyle::SP_DriveNetIcon);
422 case DRIVE_CDROM:
423 return d->getIcon(QStyle::SP_DriveCDIcon);
424 case DRIVE_RAMDISK:
425 case DRIVE_UNKNOWN:
426 case DRIVE_NO_ROOT_DIR:
427 default:
428 return d->getIcon(QStyle::SP_DriveHDIcon);
429 }
430 }
431#else
432 return d->getIcon(QStyle::SP_DriveHDIcon);
433#endif
434 if (info.isFile()) {
435 if (info.isSymLink())
436 return d->getIcon(QStyle::SP_FileLinkIcon);
437 else
438 return d->getIcon(QStyle::SP_FileIcon);
439 }
440 if (info.isDir()) {
441 if (info.isSymLink()) {
442 return d->getIcon(QStyle::SP_DirLinkIcon);
443 } else {
444 if (info.absoluteFilePath() == d->homePath) {
445 return d->getIcon(QStyle::SP_DirHomeIcon);
446 } else {
447 return d->getIcon(QStyle::SP_DirIcon);
448 }
449 }
450 }
451 return QIcon();
452}
453
454/*!
455 Returns the type of the file described by \a info.
456*/
457
458QString QFileIconProvider::type(const QFileInfo &info) const
459{
460 if (info.isRoot())
461 return QApplication::translate("QFileDialog", "Drive");
462 if (info.isFile()) {
463 if (!info.suffix().isEmpty())
464 return info.suffix() + QLatin1Char(' ') + QApplication::translate("QFileDialog", "File");
465 return QApplication::translate("QFileDialog", "File");
466 }
467
468 if (info.isDir())
469#ifdef Q_WS_WIN
470 return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer");
471#else
472 return QApplication::translate("QFileDialog", "Folder", "All other platforms");
473#endif
474 // Windows - "File Folder"
475 // OS X - "Folder"
476 // Konqueror - "Folder"
477 // Nautilus - "folder"
478
479 if (info.isSymLink())
480#ifdef Q_OS_MAC
481 return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder");
482#else
483 return QApplication::translate("QFileDialog", "Shortcut", "All other platforms");
484#endif
485 // OS X - "Alias"
486 // Windows - "Shortcut"
487 // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
488 // Nautilus - "link to folder" or "link to object file", same as Konqueror
489
490 return QApplication::translate("QFileDialog", "Unknown");
491}
492
493QT_END_NAMESPACE
494
495#endif
Note: See TracBrowser for help on using the repository browser.