📄 qicon.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qicon.h"#include "qiconengine.h"#include "qiconengineplugin.h"#include "private/qfactoryloader_p.h"#include "qapplication.h"#include "qstyleoption.h"#include "qpainter.h"#include "qfileinfo.h"#include "qstyle.h"#include "qpixmapcache.h"#include "qvariant.h"#include "qdebug.h"/*! \enum QIcon::Mode This enum type describes the mode for which a pixmap is intended to be used. The currently defined modes are: \value Normal Display the pixmap when the user is not interacting with the icon, but the functionality represented by the icon is available. \value Disabled Display the pixmap when the functionality represented by the icon is not available. \value Active Display the pixmap when the functionality represented by the icon is available and the user is interacting with the icon, for example, moving the mouse over it or clicking it. \value Selected Display the pixmap when the item represented by the icon is selected.*//*! \enum QIcon::State This enum describes the state for which a pixmap is intended to be used. The \e state can be: \value Off Display the pixmap when the widget is in an "off" state \value On Display the pixmap when the widget is in an "on" state*/extern Q_GUI_EXPORT qint64 qt_pixmap_id(const QPixmap &pixmap);QBasicAtomic serialNumCounter = Q_ATOMIC_INIT(1);class QIconPrivate{public: QIconPrivate():ref(1), engine(0), serialNum(serialNumCounter.fetchAndAdd(1)), detach_no(0), engine_version(2) {} ~QIconPrivate() { delete engine; } QAtomic ref; QIconEngine *engine; int serialNum; int detach_no; int engine_version;};struct QPixmapIconEngineEntry{ QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){} QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) :pixmap(pm), size(pm.size()), mode(m), state(s){} QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) :fileName(file), size(sz), mode(m), state(s){} QPixmap pixmap; QString fileName; QSize size; QIcon::Mode mode; QIcon::State state; bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }};class QPixmapIconEngine : public QIconEngineV2 {public: QPixmapIconEngine(); QPixmapIconEngine(const QPixmapIconEngine &); ~QPixmapIconEngine(); void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state); QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly); QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state); void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state); // v2 functions QString key() const; QIconEngineV2 *clone() const; bool read(QDataStream &in); bool write(QDataStream &out) const;private: QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state); QVector<QPixmapIconEngineEntry> pixmaps; friend QDataStream &operator<<(QDataStream &s, const QIcon &icon);};QPixmapIconEngine::QPixmapIconEngine(){}QPixmapIconEngine::QPixmapIconEngine(const QPixmapIconEngine &other) : QIconEngineV2(other), pixmaps(other.pixmaps){}QPixmapIconEngine::~QPixmapIconEngine(){}void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state){ painter->drawPixmap(rect, pixmap(rect.size(), mode, state));}static inline int area(const QSize &s) { return s.width() * s.height(); }// returns the smallest of the two that is still larger than or equal to size.static QPixmapIconEngineEntry *bestSizeMatch( const QSize &size, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb){ int s = area(size); if (pa->size == QSize() && pa->pixmap.isNull()) { pa->pixmap = QPixmap(pa->fileName); pa->size = pa->pixmap.size(); } int a = area(pa->size); if (pb->size == QSize() && pb->pixmap.isNull()) { pb->pixmap = QPixmap(pb->fileName); pb->size = pb->pixmap.size(); } int b = area(pb->size); int res = a; if (qMin(a,b) >= s) res = qMin(a,b); else res = qMax(a,b); if (res == a) return pa; return pb;}QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state){ QPixmapIconEngineEntry *pe = 0; for (int i = 0; i < pixmaps.count(); ++i) if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) { if (pe) pe = bestSizeMatch(size, &pixmaps[i], pe); else pe = &pixmaps[i]; } return pe;}QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly){ QPixmapIconEngineEntry *pe = tryMatch(size, mode, state); while (!pe){ QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On; if (mode == QIcon::Disabled || mode == QIcon::Selected) { QIcon::Mode oppositeMode = (mode == QIcon::Disabled) ? QIcon::Selected : QIcon::Disabled; if ((pe = tryMatch(size, QIcon::Normal, state))) break; if ((pe = tryMatch(size, QIcon::Active, state))) break; if ((pe = tryMatch(size, mode, oppositeState))) break; if ((pe = tryMatch(size, QIcon::Normal, oppositeState))) break; if ((pe = tryMatch(size, QIcon::Active, oppositeState))) break; if ((pe = tryMatch(size, oppositeMode, state))) break; if ((pe = tryMatch(size, oppositeMode, oppositeState))) break; } else { QIcon::Mode oppositeMode = (mode == QIcon::Normal) ? QIcon::Active : QIcon::Normal; if ((pe = tryMatch(size, oppositeMode, state))) break; if ((pe = tryMatch(size, mode, oppositeState))) break; if ((pe = tryMatch(size, oppositeMode, oppositeState))) break; if ((pe = tryMatch(size, QIcon::Disabled, state))) break; if ((pe = tryMatch(size, QIcon::Selected, state))) break; if ((pe = tryMatch(size, QIcon::Disabled, oppositeState))) break; if ((pe = tryMatch(size, QIcon::Selected, oppositeState))) break; } if (!pe) return pe; } if (sizeOnly ? (pe->size.isNull() || !pe->size.isValid()) : pe->pixmap.isNull()) { pe->pixmap = QPixmap(pe->fileName); if (!pe->pixmap.isNull()) pe->size = pe->pixmap.size(); } return pe;}QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state){ QPixmap pm; QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, false); if (pe) pm = pe->pixmap; if (pm.isNull()) return pm; QSize actualSize = pm.size(); if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); QString key = QLatin1String("$qt_icon_") + QString::number(qt_pixmap_id(pm)) + QString::number(actualSize.width()) + QLatin1Char('_') + QString::number(actualSize.height()) + QLatin1Char('_'); if (mode == QIcon::Active) { if (QPixmapCache::find(key + QString::number(mode), pm)) return pm; // horray if (QPixmapCache::find(key + QString::number(QIcon::Normal), pm)) { QStyleOption opt(0); opt.palette = QApplication::palette(); QPixmap active = QApplication::style()->generatedIconPixmap(QIcon::Active, pm, &opt); if (qt_pixmap_id(pm) == qt_pixmap_id(active)) return pm; } } if (!QPixmapCache::find(key + QString::number(mode), pm)) { if (pe->mode != mode && mode != QIcon::Normal) { QStyleOption opt(0); opt.palette = QApplication::palette(); QPixmap generated = QApplication::style()->generatedIconPixmap(mode, pm, &opt); if (!generated.isNull()) pm = generated; } if (pm.size() != actualSize) pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QPixmapCache::insert(key + QString::number(mode), pm); } return pm;}QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state){ QSize actualSize; if (QPixmapIconEngineEntry *pe = bestMatch(size, mode, state, true)) actualSize = pe->size; if (actualSize.isNull()) return actualSize; if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); return actualSize;}void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state){ if (!pixmap.isNull()) pixmaps += QPixmapIconEngineEntry(pixmap, mode, state);}void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state){ if (!fileName.isEmpty()) { QString abs = fileName; if (fileName.at(0) != QLatin1Char(':')) abs = QFileInfo(fileName).absoluteFilePath(); pixmaps += QPixmapIconEngineEntry(abs, size, mode, state); }}QString QPixmapIconEngine::key() const{ return QLatin1String("QPixmapIconEngine");}QIconEngineV2 *QPixmapIconEngine::clone() const{ return new QPixmapIconEngine(*this);}bool QPixmapIconEngine::read(QDataStream &in){ int num_entries;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -