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

Last change on this file since 104 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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