# # Machekku Show file icons in Transfer Manager on Windows # # Version: 0.2 # Date: 2006-12-05 # # filetransdlg.cpp | 52 ++++++++++---- # filetransdlg.h | 4 - # src.pri | 1 # tools/desktoputil/desktoputil.cpp | 46 ++++++++++++ # tools/desktoputil/desktoputil.h | 11 +++ # tools/desktoputil/desktoputil.pri | 9 ++ # tools/desktoputil/third-party/qt_hicon_win.cpp | 91 +++++++++++++++++++++++++ # tools/desktoputil/third-party/qt_hicon_win.h | 7 + # 8 files changed, 207 insertions(+), 14 deletions(-) # diff -rN -u old-psi-ft-tmp-2/src/filetransdlg.cpp new-psi-ft-tmp-2/src/filetransdlg.cpp --- old-psi-ft-tmp-2/src/filetransdlg.cpp 2006-12-05 03:08:46.078125000 +0100 +++ new-psi-ft-tmp-2/src/filetransdlg.cpp 2006-12-05 03:08:50.375000000 +0100 @@ -39,6 +39,7 @@ #include "psitooltip.h" #include "psicontactlist.h" #include "accountlabel.h" +#include "desktoputil.h" typedef Q_UINT64 LARGE_TYPE; @@ -138,6 +139,7 @@ S5BConnection *c; Jid peer; QString fileName, saveName; + QString filePath; // full file path, but without ".part" qlonglong fileSize, sent, offset, length; QString desc; bool sending; @@ -192,6 +194,7 @@ d->peer = to; QFileInfo fi(fname); + d->filePath = fname; d->fileName = fi.fileName(); d->fileSize = fi.size(); // TODO: large file support d->desc = desc; @@ -233,6 +236,12 @@ return d->fileSize; } +QPixmap FileTransferHandler::fileIcon() const +{ + return DesktopUtil::getFileIcon(d->filePath, !d->sending && d->sent < d->fileSize, true); + // use generic icon when still receiving the file +} + QString FileTransferHandler::description() const { return d->desc; @@ -266,6 +275,8 @@ if(d->sending) return; d->fileName = fileName; + d->filePath = saveName; + d->filePath.chop(5); // remove ".part" d->saveName = saveName; d->offset = offset; d->length = d->fileSize; @@ -953,7 +964,7 @@ class FileTransItem : public Q3ListViewItem { public: - QPixmap icon; + QPixmap icon, fileicon; bool sending; QString name; qlonglong size; @@ -1233,9 +1244,19 @@ p->fillRect(0, 0, width, h, br); // icon - p->drawPixmap(m, m + yoff, icon); - int tm = m + icon.width() + 4; - tw = tw - (icon.width() + 4); + int fullIconWidth; + if(!fileicon.isNull()) { + fullIconWidth = fileicon.width() + icon.width()/2; + p->drawPixmap(m, m + yoff, fileicon); + p->drawPixmap(m + fullIconWidth - icon.width(), m + yoff + fileicon.height() - icon.height()/2, icon); + } + else { + fullIconWidth = icon.width(); + p->drawPixmap(m, m + yoff, icon); + } + + int tm = m + fullIconWidth + 4; + tw = tw - (fullIconWidth + 4); // filename / peer if(isSelected()) @@ -1511,20 +1532,13 @@ fi->done = true; } - parent->setProgress(i->id, i->p, i->h->totalSteps(), i->sent, bps, updateAll); - if(done) { bool recv = (i->h->mode() == FileTransferHandler::Receiving); QString fname, savename; if(recv) { fname = i->h->fileName(); savename = i->h->saveName(); - } - - PsiAccount *pa = i->h->account(); - transferList.removeRef(i); - if(recv) { //printf("fname: [%s], savename: [%s]\n", fname.latin1(), savename.latin1()); // rename .part to original filename @@ -1535,10 +1549,19 @@ if(!dir.rename(fi.fileName(), fname)) { // TODO: display some error about renaming } + + findItem(i->id)->fileicon = i->h->fileIcon(); } + PsiAccount *pa = i->h->account(); pa->playSound(option.onevent[eFTComplete]); } + + parent->setProgress(i->id, i->p, i->h->totalSteps(), i->sent, bps, updateAll); + + if(done) { + transferList.removeRef(i); + } } }; @@ -1590,7 +1613,7 @@ delete d; } -int FileTransDlg::addItem(const QString &filename, qlonglong size, const QString &peer, bool sending) +int FileTransDlg::addItem(const QString &filename, const QPixmap &fileicon, qlonglong size, const QString &peer, bool sending) { int id = d->findFreeId(); FileTransItem *i = new FileTransItem(d->lv, filename, size, peer, sending); @@ -1598,6 +1621,9 @@ i->icon = IconsetFactory::icon("psi/upload").impix().pixmap(); else i->icon = IconsetFactory::icon("psi/download").impix().pixmap(); + + i->fileicon = fileicon; + i->id = id; d->t.start(1000); return id; @@ -1658,7 +1684,7 @@ TransferMapping *i = new TransferMapping; i->h = h; - i->id = addItem(h->fileName(), h->fileSize(), peer, (h->mode() == FileTransferHandler::Sending)); + i->id = addItem(h->fileName(), h->fileIcon(), h->fileSize(), peer, (h->mode() == FileTransferHandler::Sending)); i->p = p; i->sent = sent; d->transferList.append(i); diff -rN -u old-psi-ft-tmp-2/src/filetransdlg.h new-psi-ft-tmp-2/src/filetransdlg.h --- old-psi-ft-tmp-2/src/filetransdlg.h 2006-12-05 03:08:46.046875000 +0100 +++ new-psi-ft-tmp-2/src/filetransdlg.h 2006-12-05 03:08:50.375000000 +0100 @@ -2,6 +2,7 @@ #define FILETRANSDLG_H #include +#include #include "xmpp_jid.h" #include "ui_filetrans.h" @@ -34,6 +35,7 @@ int totalSteps() const; bool resumeSupported() const; QString saveName() const; + QPixmap fileIcon() const; void send(const Jid &to, const QString &fname, const QString &desc); void accept(const QString &saveName, const QString &fileName, qlonglong offset=0); @@ -113,7 +115,7 @@ FileTransDlg(PsiCon *); ~FileTransDlg(); - int addItem(const QString &filename, qlonglong size, const QString &peer, bool sending); + int addItem(const QString &filename, const QPixmap &fileicon, qlonglong size, const QString &peer, bool sending); void setProgress(int id, int step, int total, qlonglong sent, int bytesPerSecond, bool updateAll=false); void setError(int id, const QString &reason); void removeItem(int id); diff -rN -u old-psi-ft-tmp-2/src/src.pri new-psi-ft-tmp-2/src/src.pri --- old-psi-ft-tmp-2/src/src.pri 2006-12-05 03:08:45.875000000 +0100 +++ new-psi-ft-tmp-2/src/src.pri 2006-12-05 03:08:52.046875000 +0100 @@ -13,6 +13,7 @@ include($$PWD/tools/spellchecker/spellchecker.pri) include($$PWD/tools/contactlist/contactlist.pri) include($$PWD/tools/grepshortcutkeydlg/grepshortcutkeydlg.pri) +include($$PWD/tools/desktoputil/desktoputil.pri) # Growl mac { diff -rN -u old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.cpp new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.cpp --- old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.cpp 2006-12-05 03:08:52.671875000 +0100 @@ -0,0 +1,46 @@ +#include "desktoputil.h" + +#include + +/** + * \brief Returns icon of the given file. + * \param path, path to the file + * \param genericIcon, retrieve the icon basing just on file type + * \param largeIcon, retrieve large image + * + * If the file does not exist, a generic icon is always returned. + * + * To retrieve icon for a given file extension, simply provide ".extension" as \a path + * and set \a genericIcon to true. + */ +QPixmap DesktopUtil::getFileIcon(const QString &path, bool genericIcon, bool largeIcon) +{ + QPixmap icon; + +#ifdef Q_WS_WIN + + SHFILEINFO sfi; + + QFileInfo fi(path); + QString iconPath = path; + + UINT flags = SHGFI_ICON; + flags |= largeIcon ? SHGFI_LARGEICON : SHGFI_SMALLICON; + + if (genericIcon || !fi.exists()) { + flags |= SHGFI_USEFILEATTRIBUTES; + iconPath = "." + fi.suffix(); + } + else { + iconPath.replace('/', '\\'); + } + + if (SHGetFileInfo(iconPath.utf16(), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), flags)) { + icon = HIconUtil::convertHIconToPixmap(sfi.hIcon); + DestroyIcon(sfi.hIcon); + } + +#endif + + return icon; +} diff -rN -u old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.h new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.h --- old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.h 1970-01-01 01:00:00.000000000 +0100 +++ new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.h 2006-12-05 03:08:52.671875000 +0100 @@ -0,0 +1,11 @@ +#include +#include + +#ifdef Q_WS_WIN +#include "third-party/qt_hicon_win.h" +#endif + +namespace DesktopUtil +{ + QPixmap getFileIcon(const QString &path, bool genericIcon = false, bool largeIcon = true); +}; diff -rN -u old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.pri new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.pri --- old-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.pri 1970-01-01 01:00:00.000000000 +0100 +++ new-psi-ft-tmp-2/src/tools/desktoputil/desktoputil.pri 2006-12-05 03:08:52.687500000 +0100 @@ -0,0 +1,9 @@ +HEADERS += $$PWD/desktoputil.h +SOURCES += $$PWD/desktoputil.cpp +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +win32: { + HEADERS += $$PWD/third-party/qt_hicon_win.h + SOURCES += $$PWD/third-party/qt_hicon_win.cpp +} diff -rN -u old-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.cpp new-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.cpp --- old-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.cpp 2006-12-05 03:08:52.718750000 +0100 @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved. +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +/* From Qt 4.1.3, qwindowsstyle.cpp */ + +#include "qt_hicon_win.h" + +QPixmap HIconUtil::convertHIconToPixmap(const HICON icon) +{ + bool foundAlpha = false; + HDC screenDevice = qt_win_display_dc(); + HDC hdc = CreateCompatibleDC(screenDevice); + + ICONINFO iconinfo; + GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center + + //create image + HBITMAP winBitmap = CreateBitmap(iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 1, 32, 0); + HGDIOBJ oldhdc = SelectObject(hdc, winBitmap); + DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL); + QPixmap::HBitmapFormat alphaType = QPixmap::PremultipliedAlpha; + + BITMAP bitmapData; + GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bitmapData); + + QPixmap iconpixmap = QPixmap::fromWinHBITMAP(winBitmap, alphaType); + QImage img = iconpixmap.toImage(); + + if ( bitmapData.bmBitsPixel == 32 ) { //only check 32 bit images for alpha + for (int y = 0 ; y < iconpixmap.height() && !foundAlpha ; y++) { + QRgb *scanLine= reinterpret_cast(img.scanLine(y)); + for (int x = 0; x < img.width() ; x++) { + if (qAlpha(scanLine[x]) != 0) { + foundAlpha = true; + break; + } + } + } + } + + if (!foundAlpha) { + //If no alpha was found, we use the mask to set alpha values + HBITMAP winMask = CreateBitmap(iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 1, 32, 0); + SelectObject(hdc, winMask); + DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_MASK); + + QPixmap maskPixmap = QPixmap::fromWinHBITMAP(winMask, alphaType); + QImage mask = maskPixmap.toImage(); + + for (int y = 0 ; y< iconpixmap.height() ; y++){ + QRgb *scanlineImage = reinterpret_cast(img.scanLine(y)); + QRgb *scanlineMask = reinterpret_cast(mask.scanLine(y)); + for (int x = 0; x < img.width() ; x++){ + if (qRed(scanlineMask[x]) != 0) + scanlineImage[x] = 0; //mask out this pixel + else + scanlineImage[x] |= 0xff000000; // set the alpha channel to 255 + } + } + DeleteObject(winMask); + } + + //dispose resources created by iconinfo call + DeleteObject(iconinfo.hbmMask); + DeleteObject(iconinfo.hbmColor); + + SelectObject(hdc, oldhdc); //restore state + DeleteDC(hdc); + DeleteObject(winBitmap); + return QPixmap::fromImage(img); +} diff -rN -u old-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.h new-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.h --- old-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.h 1970-01-01 01:00:00.000000000 +0100 +++ new-psi-ft-tmp-2/src/tools/desktoputil/third-party/qt_hicon_win.h 2006-12-05 03:08:52.734375000 +0100 @@ -0,0 +1,7 @@ +#include +#include + +namespace HIconUtil +{ + QPixmap convertHIconToPixmap(const HICON icon); +};