diff --git a/include/KtUtils/IconHelper.hpp b/include/KtUtils/IconHelper.hpp index 79ead77..90cfe81 100644 --- a/include/KtUtils/IconHelper.hpp +++ b/include/KtUtils/IconHelper.hpp @@ -2037,27 +2037,30 @@ class KTUTILS_EXPORT IconHelper : public QObject { /** * \brief Generate QPixmap for given icon * \note This function is SLOW, please hold the result and reuse it - * instead of call multiple times. + * instead of call multiple times, or turn on cached parameter. * \param iconType Enum value for wanted icon. * \param size Pixel size for generated image. * \param color Fill color of the icon. + * \param cached Cache the generated pixmap, return it next time. * \return Generated QPixmap for the icon with given size and color. * \sa Icon, icon */ static QPixmap pixmap(Icon iconType, int size = 16, - const QColor& color = Qt::white); + const QColor& color = Qt::white, bool cached = true); /** * \brief Generate QIcon for given icon with available sizes: 16, 24, 32, 36, * 48, 64, 72, 96, 128, 144, 192, 256. * \note This function is EXTREMELY SLOW, please hold the result and reuse it - * instead of call multiple times. + * instead of call multiple times, or turn on cached parameter. * \param iconType Enum value for wanted icon. * \param color Fill color of the icon, QIcon::Disabled will for to gray. + * \param cached Cache the generated icon, return it next time. * \return Generated QIcon for the icon with given size and color. * \sa Icon, pixmap, icon */ - static QIcon icon(Icon iconType, const QColor& color = Qt::white); + static QIcon icon(Icon iconType, const QColor& color = Qt::white, + bool cached = true); // Enumeration for font files enum Font { Brand, Regular, Solid }; @@ -2071,33 +2074,38 @@ class KTUTILS_EXPORT IconHelper : public QObject { * of specified color and weight. */ static QPixmap pixmap(Font fontType, QChar ch, int size = 16, const QColor& color = Qt::white, - QFont::Weight weight = QFont::Normal); + QFont::Weight weight = QFont::Normal, + bool cached = true); /** \brief Generate QIcon with given font and charactor code of specified * color and weight. */ static QIcon icon(Font fontType, QChar ch, const QColor& color = Qt::white, - QFont::Weight weight = QFont::Normal); + QFont::Weight weight = QFont::Normal, bool cached = true); /** * \brief Set icon to given widget - * \note This function is EXTREMELY SLOW, please avoid calling multiple times. + * \note This function is EXTREMELY SLOW, please avoid calling multiple times, + * or turn on cached parameter. * \tparam T Type of given widget. * \param widget Widget to be set icon fpr. * \param iconType Enum value for wanted icon. * \param color Fill color of the icon, QIcon::Disabled will for to gray. + * \param cached Cache the generated icon, return it next time. * \sa Icon, pixmap, icon */ template inline static void SetIcon(T* widget, Icon iconType, - const QColor& color = Qt::white) { - widget->setProperty("icon", icon(iconType, color)); + const QColor& color = Qt::white, + bool cached = true) { + widget->setProperty("icon", icon(iconType, color, cached)); } /** \brief Set widget icon with given font and charactor code of specified * color and weight. */ template inline static void SetIcon(T* widget, Font fontType, QChar ch, const QColor& color = Qt::white, - QFont::Weight weight = QFont::Normal) { - widget->setProperty("icon", icon(fontType, ch, color, weight)); + QFont::Weight weight = QFont::Normal, + bool cached = true) { + widget->setProperty("icon", icon(fontType, ch, color, weight, cached)); } private: diff --git a/src/IconHelper.cpp b/src/IconHelper.cpp index 583334a..592696e 100644 --- a/src/IconHelper.cpp +++ b/src/IconHelper.cpp @@ -116,15 +116,54 @@ QPixmap RenderPixmap(QSharedPointer renderer, int size) { return pixmap; } -QPixmap IconHelper::pixmap(Icon iconType, int size, const QColor& color) { +QPixmap IconHelper::pixmap(Icon iconType, int size, const QColor& color, + bool cached) { + static QMutex mutex; + using Key = std::tuple; + static std::vector> cache; + if (cached) { + QMutexLocker locker(&mutex); + auto it = std::find_if(cache.begin(), cache.end(), + [&](const std::pair& p) { + return std::get<0>(p.first) == iconType && + std::get<1>(p.first) == size && + std::get<2>(p.first) == color && + std::get<3>(p.first) == cached; + }); + if (it != cache.end()) { + return it->second; + } + } + QSharedPointer renderer = GetRenderer(iconType, color); - return RenderPixmap(renderer, size); + QPixmap pixmap = RenderPixmap(renderer, size); + if (cached) { + QMutexLocker locker(&mutex); + cache.emplace_back(Key{iconType, size, color, cached}, pixmap); + } + return pixmap; } -QIcon IconHelper::icon(Icon iconType, const QColor& color) { +QIcon IconHelper::icon(Icon iconType, const QColor& color, bool cached) { static const QVector sizes = {16, 24, 32, 36, 48, 64, 72, 96, 128, 144, 192, 256}; + static QMutex mutex; + using Key = std::tuple; + static std::vector> cache; + if (cached) { + QMutexLocker locker(&mutex); + auto it = std::find_if(cache.begin(), cache.end(), + [&](const std::pair& p) { + return std::get<0>(p.first) == iconType && + std::get<1>(p.first) == color && + std::get<2>(p.first) == cached; + }); + if (it != cache.end()) { + return it->second; + } + } + QIcon icon; QSharedPointer renderer = GetRenderer(iconType, color); QSharedPointer renderer_gray = GetRenderer(iconType, Qt::gray); @@ -141,6 +180,10 @@ QIcon IconHelper::icon(Icon iconType, const QColor& color) { icon.addPixmap(px, QIcon::Disabled, QIcon::On); icon.addPixmap(px, QIcon::Disabled, QIcon::Off); } + if (cached) { + QMutexLocker locker(&mutex); + cache.emplace_back(Key{iconType, color, cached}, icon); + } return icon; } @@ -160,7 +203,27 @@ QFont IconHelper::font(Font fontType) { } QPixmap IconHelper::pixmap(Font fontType, QChar ch, int size, - const QColor& color, QFont::Weight weight) { + const QColor& color, QFont::Weight weight, + bool cached) { + static QMutex mutex; + using Key = std::tuple; + static std::vector> cache; + + if (cached) { + QMutexLocker locker(&mutex); + auto it = std::find_if( + cache.begin(), cache.end(), [&](const std::pair& p) { + return std::get<0>(p.first) == fontType && + std::get<1>(p.first) == ch && std::get<2>(p.first) == size && + std::get<3>(p.first) == color && + std::get<4>(p.first) == weight && + std::get<5>(p.first) == cached; + }); + if (it != cache.end()) { + return it->second; + } + } + QFont font = IconHelper::font(fontType); font.setPixelSize(size); font.setWeight(weight); @@ -173,14 +236,36 @@ QPixmap IconHelper::pixmap(Font fontType, QChar ch, int size, painter.setFont(font); painter.drawText(QRect(0, 0, size, size), Qt::AlignCenter, QString(ch)); painter.end(); + if (cached) { + QMutexLocker locker(&mutex); + cache.emplace_back(Key{fontType, ch, size, color, weight, cached}, pixmap); + } return pixmap; } QIcon IconHelper::icon(Font fontType, QChar ch, const QColor& color, - QFont::Weight weight) { + QFont::Weight weight, bool cached) { static const QVector sizes = {16, 24, 32, 36, 48, 64, 72, 96, 128, 144, 192, 256}; + static QMutex mutex; + using Key = std::tuple; + static std::vector> cache; + + if (cached) { + QMutexLocker locker(&mutex); + auto it = std::find_if( + cache.begin(), cache.end(), [&](const std::pair& p) { + return std::get<0>(p.first) == fontType && + std::get<1>(p.first) == ch && std::get<2>(p.first) == color && + std::get<3>(p.first) == weight && + std::get<4>(p.first) == cached; + }); + if (it != cache.end()) { + return it->second; + } + } + QIcon icon; for (const int size : sizes) { QPixmap px = pixmap(fontType, ch, size, color, weight); @@ -195,6 +280,10 @@ QIcon IconHelper::icon(Font fontType, QChar ch, const QColor& color, icon.addPixmap(px, QIcon::Disabled, QIcon::On); icon.addPixmap(px, QIcon::Disabled, QIcon::Off); } + if (cached) { + QMutexLocker locker(&mutex); + cache.emplace_back(Key{fontType, ch, color, weight, cached}, icon); + } return icon; } } // namespace KtUtils