File indexing completed on 2024-05-12 04:57:49

0001 /**************************************************************************
0002 **
0003 ** This file is part of Qt Creator
0004 **
0005 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
0006 **
0007 ** Contact: Nokia Corporation (qt-info@nokia.com)
0008 **
0009 ** Commercial Usage
0010 **
0011 ** Licensees holding valid Qt Commercial licenses may use this file in
0012 ** accordance with the Qt Commercial License Agreement provided with the
0013 ** Software or, alternatively, in accordance with the terms contained in
0014 ** a written agreement between you and Nokia.
0015 **
0016 ** GNU Lesser General Public License Usage
0017 **
0018 ** Alternatively, this file may be used under the terms of the GNU Lesser
0019 ** General Public License version 2.1 as published by the Free Software
0020 ** Foundation and appearing in the file LICENSE.LGPL included in the
0021 ** packaging of this file.  Please review the following information to
0022 ** ensure the GNU Lesser General Public License version 2.1 requirements
0023 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0024 **
0025 ** If you are unsure which license is appropriate for your use, please
0026 ** contact the sales department at http://qt.nokia.com/contact.
0027 **
0028 **************************************************************************/
0029 
0030 #include "stylehelper.h"
0031 
0032 #include <QPixmapCache>
0033 #include <QWidget>
0034 #include <QtCore/QRect>
0035 #include <QPainter>
0036 #include <QApplication>
0037 #include <QPalette>
0038 #include <QStyleOption>
0039 #include <QtCore/QObject>
0040 
0041 // Clamps float color values within (0, 255)
0042 static int clamp(float x)
0043 {
0044     const int val = x > 255 ? 255 : static_cast<int>(x);
0045     return val < 0 ? 0 : val;
0046 }
0047 
0048 namespace Utils
0049 {
0050 
0051 qreal StyleHelper::sidebarFontSize()
0052 {
0053 #if defined(Q_OS_MACOS)
0054     return 10;
0055 #else
0056     return 7.5;
0057 #endif
0058 }
0059 
0060 QColor StyleHelper::panelTextColor(bool lightColored)
0061 {
0062     if (!lightColored) {
0063         return Qt::white;
0064     }
0065     else {
0066         return Qt::black;
0067     }
0068 }
0069 
0070 // Invalid by default, setBaseColor needs to be called at least once
0071 QColor StyleHelper::m_baseColor;
0072 QColor StyleHelper::m_requestedBaseColor;
0073 
0074 QColor StyleHelper::baseColor(bool lightColored)
0075 {
0076     if (!lightColored) {
0077         return m_baseColor;
0078     }
0079     else {
0080         return m_baseColor.lighter(230);
0081     }
0082 }
0083 
0084 QColor StyleHelper::highlightColor(bool lightColored)
0085 {
0086     QColor result = baseColor(lightColored);
0087     if (!lightColored)
0088         result.setHsv(result.hue(),
0089                       clamp(result.saturation()),
0090                       clamp(result.value() * 1.16));
0091     else
0092         result.setHsv(result.hue(),
0093                       clamp(result.saturation()),
0094                       clamp(result.value() * 1.06));
0095     return result;
0096 }
0097 
0098 QColor StyleHelper::shadowColor(bool lightColored)
0099 {
0100     QColor result = baseColor(lightColored);
0101     result.setHsv(result.hue(),
0102                   clamp(result.saturation() * 1.1),
0103                   clamp(result.value() * 0.70));
0104     return result;
0105 }
0106 
0107 QColor StyleHelper::borderColor(bool lightColored)
0108 {
0109     QColor result = baseColor(lightColored);
0110     result.setHsv(result.hue(),
0111                   result.saturation(),
0112                   result.value() / 2);
0113     return result;
0114 }
0115 
0116 // We try to ensure that the actual color used are within
0117 // reasonalbe bounds while generating the actual baseColor
0118 // from the users request.
0119 void StyleHelper::setBaseColor(const QColor &newcolor)
0120 {
0121     m_requestedBaseColor = newcolor;
0122 
0123     QColor color;
0124     color.setHsv(newcolor.hue(),
0125                  newcolor.saturation() * 0.7,
0126                  64 + newcolor.value() / 3);
0127 
0128     if (color.isValid() && color != m_baseColor) {
0129         m_baseColor = color;
0130 
0131         auto const l_topLevelWidgets = QApplication::topLevelWidgets();
0132         for (QWidget* w : l_topLevelWidgets) {
0133             w->update();
0134         }
0135     }
0136 }
0137 
0138 static void verticalGradientHelper(QPainter* p, const QRect &spanRect, const QRect &rect, bool lightColored)
0139 {
0140     QColor highlight = StyleHelper::highlightColor(lightColored);
0141     QColor shadow = StyleHelper::shadowColor(lightColored);
0142     QLinearGradient grad(spanRect.topRight(), spanRect.topLeft());
0143     grad.setColorAt(0, highlight.lighter(117));
0144     grad.setColorAt(1, shadow.darker(109));
0145     p->fillRect(rect, grad);
0146 
0147     QColor light(255, 255, 255, 80);
0148     p->setPen(light);
0149     p->drawLine(rect.topRight() - QPoint(1, 0), rect.bottomRight() - QPoint(1, 0));
0150     QColor dark(0, 0, 0, 90);
0151     p->setPen(dark);
0152     p->drawLine(rect.topLeft(), rect.bottomLeft());
0153 }
0154 
0155 void StyleHelper::verticalGradient(QPainter* painter, const QRect &spanRect, const QRect &clipRect, bool lightColored)
0156 {
0157     if (StyleHelper::usePixmapCache()) {
0158         QString key;
0159         QColor keyColor = baseColor(lightColored);
0160         key.asprintf("mh_vertical %d %d %d %d %d",
0161                      spanRect.width(), spanRect.height(), clipRect.width(),
0162                      clipRect.height(), keyColor.rgb());
0163 
0164         QPixmap pixmap;
0165         if (!QPixmapCache::find(key, &pixmap)) {
0166             pixmap = QPixmap(clipRect.size());
0167             QPainter p(&pixmap);
0168             QRect rect(0, 0, clipRect.width(), clipRect.height());
0169             verticalGradientHelper(&p, spanRect, rect, lightColored);
0170             p.end();
0171             QPixmapCache::insert(key, pixmap);
0172         }
0173 
0174         painter->drawPixmap(clipRect.topLeft(), pixmap);
0175     }
0176     else {
0177         verticalGradientHelper(painter, spanRect, clipRect, lightColored);
0178     }
0179 }
0180 
0181 // Draws a cached pixmap with shadow
0182 void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
0183                                      QPainter* p, QIcon::Mode iconMode, int radius, const QColor &color, const QPoint &offset)
0184 {
0185     QPixmap cache;
0186     QString pixmapName = QSL("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height());
0187 
0188     if (!QPixmapCache::find(pixmapName, &cache)) {
0189         QPixmap px = icon.pixmap(rect.size(), iconMode);
0190         px.setDevicePixelRatio(qApp->devicePixelRatio());
0191         cache = QPixmap(px.size() + QSize(radius * 2, radius * 2));
0192         cache.setDevicePixelRatio(px.devicePixelRatioF());
0193         cache.fill(Qt::transparent);
0194 
0195         QPainter cachePainter(&cache);
0196 
0197         // Draw shadow
0198         QImage tmp(px.size() + QSize(radius * 2, radius * 2 + 1), QImage::Format_ARGB32_Premultiplied);
0199         tmp.setDevicePixelRatio(px.devicePixelRatioF());
0200         tmp.fill(Qt::transparent);
0201 
0202         QPainter tmpPainter(&tmp);
0203         tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
0204         tmpPainter.drawPixmap(QPoint(radius, radius), px);
0205         tmpPainter.end();
0206 
0207         // blur the alpha channel
0208         QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
0209         blurred.fill(Qt::transparent);
0210         QPainter blurPainter(&blurred);
0211         qt_blurImage(&blurPainter, tmp, radius, false, true);
0212         blurPainter.end();
0213 
0214         tmp = blurred;
0215 
0216         // blacken the image...
0217         tmpPainter.begin(&tmp);
0218         tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
0219         tmpPainter.fillRect(tmp.rect(), color);
0220         tmpPainter.end();
0221 
0222         tmpPainter.begin(&tmp);
0223         tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
0224         tmpPainter.fillRect(tmp.rect(), color);
0225         tmpPainter.end();
0226 
0227         // draw the blurred drop shadow...
0228         cachePainter.drawImage(QRect(0, 0, cache.rect().width() / cache.devicePixelRatioF(), cache.rect().height() / cache.devicePixelRatioF()), tmp);
0229 
0230         // Draw the actual pixmap...
0231         cachePainter.drawPixmap(QPoint(radius, radius) + offset, px);
0232         QPixmapCache::insert(pixmapName, cache);
0233     }
0234 
0235     QRect targetRect = cache.rect();
0236     targetRect.setWidth(cache.rect().width() / cache.devicePixelRatioF());
0237     targetRect.setHeight(cache.rect().height() / cache.devicePixelRatioF());
0238     targetRect.moveCenter(rect.center());
0239     p->drawPixmap(targetRect.topLeft() - offset, cache);
0240 }
0241 
0242 } // namespace Utils