From ef57d20a677ecac6f22e812cee5ee0e89014e3c7 Mon Sep 17 00:00:00 2001
From: Lasse Holmstedt <lasse.holmstedt@nokia.com>
Date: Mon, 2 Aug 2010 17:02:53 +0200
Subject: [PATCH] Utils: Changed crumblepath to use qpainter instead of
 stylesheets

---
 src/libs/utils/crumblepath.cpp                | 177 +++++++++++++-----
 src/libs/utils/crumblepath.h                  |   3 +
 .../images/crumblepath-segment-end.png}       | Bin
 .../images/crumblepath-segment-hover-end.png} | Bin
 .../images/crumblepath-segment-hover.png}     | Bin
 .../crumblepath-segment-selected-end.png}     | Bin
 .../images/crumblepath-segment-selected.png}  | Bin
 .../images/crumblepath-segment.png}           | Bin
 src/libs/utils/stylehelper.cpp                |  24 +++
 src/libs/utils/stylehelper.h                  |   2 +
 src/libs/utils/utils.qrc                      |   6 +
 11 files changed, 162 insertions(+), 50 deletions(-)
 rename src/libs/{qmljsdebugger/editor/images/segment-end.png => utils/images/crumblepath-segment-end.png} (100%)
 rename src/libs/{qmljsdebugger/editor/images/segment-hover-end.png => utils/images/crumblepath-segment-hover-end.png} (100%)
 rename src/libs/{qmljsdebugger/editor/images/segment-hover.png => utils/images/crumblepath-segment-hover.png} (100%)
 rename src/libs/{qmljsdebugger/editor/images/segment-selected-end.png => utils/images/crumblepath-segment-selected-end.png} (100%)
 rename src/libs/{qmljsdebugger/editor/images/segment-selected.png => utils/images/crumblepath-segment-selected.png} (100%)
 rename src/libs/{qmljsdebugger/editor/images/segment.png => utils/images/crumblepath-segment.png} (100%)

diff --git a/src/libs/utils/crumblepath.cpp b/src/libs/utils/crumblepath.cpp
index 1d5369229c7..b0b78976482 100644
--- a/src/libs/utils/crumblepath.cpp
+++ b/src/libs/utils/crumblepath.cpp
@@ -28,11 +28,14 @@
 **************************************************************************/
 
 #include "crumblepath.h"
+#include "stylehelper.h"
 
 #include <QHBoxLayout>
 #include <QPushButton>
 #include <QStyle>
 #include <QResizeEvent>
+#include <QPainter>
+#include <QImage>
 
 namespace Utils {
 
@@ -49,69 +52,126 @@ public:
 
     explicit CrumblePathButton(const QString &title, QWidget *parent = 0);
     void setSegmentType(int type);
+protected:
+    void paintEvent(QPaintEvent *);
+    void mouseMoveEvent(QMouseEvent *e);
+    void leaveEvent(QEvent *);
+    void mousePressEvent(QMouseEvent *e);
+    void mouseReleaseEvent(QMouseEvent *e);
+
+private:
+    void tintImages();
+
 private:
-    static QString middleSegmentSheet(bool useLeftPadding);
-    static QString lastSegmentSheet(bool useLeftPadding);
+    bool m_isHovering;
+    bool m_isPressed;
+    bool m_isEnd;
+    QColor m_baseColor;
+    QImage m_segment;
+    QImage m_segmentEnd;
+    QImage m_segmentSelected;
+    QImage m_segmentSelectedEnd;
+    QImage m_segmentHover;
+    QImage m_segmentHoverEnd;
+    QPoint m_textPos;
 };
 
 CrumblePathButton::CrumblePathButton(const QString &title, QWidget *parent)
-    : QPushButton(title, parent)
+    : QPushButton(title, parent), m_isHovering(false), m_isPressed(false), m_isEnd(true)
 {
     setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
     setToolTip(title);
     setMinimumHeight(24);
     setMaximumHeight(24);
-    setStyleSheet(lastSegmentSheet(true));
-}
-
-QString CrumblePathButton::middleSegmentSheet(bool useLeftPadding)
-{
-    QString sheet = QString(
-                "QPushButton {"
-                "text-align: left;"
-                "color: #eeeeee;"
-                "border-image: url(:/qml/images/segment.png)  0 12 0 2;"
-                "border-width: 0 12px 0 2px;"
-                "padding-left:%1px;"
-                "}"
-                "QPushButton:hover {"
-                "    border-image: url(:/qml/images/segment-hover.png)  0 12 0 2;"
-                "}"
-                "QPushButton:pressed {"
-                "    border-image: url(:/qml/images/segment-selected.png)  0 12 0 2;"
-                "}"
-                ).arg(useLeftPadding ? "18" : "4");
-    return sheet;
-}
-
-QString CrumblePathButton::lastSegmentSheet(bool useLeftPadding)
-{
-    QString sheet = QString(
-                "QPushButton {"
-                "text-align: left;"
-                "color: #eeeeee;"
-                "border-image: url(:/qml/images/segment-end.png)  0 2 0 2;"
-                "border-width: 0 2px 0 2px;"
-                "padding-left:%1px;"
-                "}"
-                "QPushButton:hover {"
-                "    border-image: url(:/qml/images/segment-hover-end.png)  0 2 0 2;"
-                "}"
-                "QPushButton:pressed {"
-                "    border-image: url(:/qml/images/segment-selected-end.png)  0 2 0 2;"
-                "}"
-                ).arg(useLeftPadding ? "18" : "4");
-    return sheet;
+    setMouseTracking(true);
+    m_textPos.setX(18);
+    m_textPos.setY(height());
+    m_baseColor = StyleHelper::baseColor();
+
+    m_segment = QImage(":/utils/images/crumblepath-segment.png");
+    m_segmentSelected = QImage(":/utils/images/crumblepath-segment-selected.png");
+    m_segmentHover = QImage(":/utils/images/crumblepath-segment-hover.png");
+    m_segmentEnd = QImage(":/utils/images/crumblepath-segment-end.png");
+    m_segmentSelectedEnd = QImage(":/utils/images/crumblepath-segment-selected-end.png");
+    m_segmentHoverEnd = QImage(":/utils/images/crumblepath-segment-hover-end.png");
+
+    tintImages();
+}
+
+void CrumblePathButton::paintEvent(QPaintEvent *)
+{
+    QPainter p(this);
+    QRect geom(0, 0, geometry().width(), geometry().height());
+
+    if (StyleHelper::baseColor() != m_baseColor) {
+        m_baseColor = StyleHelper::baseColor();
+        tintImages();
+    }
+
+    if (m_isEnd) {
+        if (m_isPressed) {
+            Utils::StyleHelper::drawCornerImage(m_segmentSelectedEnd, &p, geom, 2, 0, 2, 0);
+        } else if (m_isHovering) {
+            Utils::StyleHelper::drawCornerImage(m_segmentHoverEnd, &p, geom, 2, 0, 2, 0);
+        } else {
+            Utils::StyleHelper::drawCornerImage(m_segmentEnd, &p, geom, 2, 0, 2, 0);
+        }
+    } else {
+        if (m_isPressed) {
+            Utils::StyleHelper::drawCornerImage(m_segmentSelected, &p, geom, 2, 0, 12, 0);
+        } else if (m_isHovering) {
+            Utils::StyleHelper::drawCornerImage(m_segmentHover, &p, geom, 2, 0, 12, 0);
+        } else {
+            Utils::StyleHelper::drawCornerImage(m_segment, &p, geom, 2, 0, 12, 0);
+        }
+    }
+    p.setPen(StyleHelper::panelTextColor());
+    p.drawText(QRectF(m_textPos.x(), 4, geom.width(), geom.height()), text());
+}
+
+void CrumblePathButton::tintImages()
+{
+    StyleHelper::tintImage(m_segmentEnd, m_baseColor);
+    StyleHelper::tintImage(m_segmentSelectedEnd, m_baseColor);
+    StyleHelper::tintImage(m_segmentHoverEnd, m_baseColor);
+    StyleHelper::tintImage(m_segmentSelected, m_baseColor);
+    StyleHelper::tintImage(m_segmentHover, m_baseColor);
+    StyleHelper::tintImage(m_segment, m_baseColor);
+}
+
+void CrumblePathButton::leaveEvent(QEvent *e)
+{
+    QPushButton::leaveEvent(e);
+    m_isHovering = false;
+    update();
+}
+
+void CrumblePathButton::mouseMoveEvent(QMouseEvent *e)
+{
+    QPushButton::mouseMoveEvent(e);
+    m_isHovering = true;
+    update();
+}
+
+void CrumblePathButton::mousePressEvent(QMouseEvent *e)
+{
+    QPushButton::mousePressEvent(e);
+    m_isPressed = true;
+    update();
+}
+
+void CrumblePathButton::mouseReleaseEvent(QMouseEvent *e)
+{
+    QPushButton::mouseReleaseEvent(e);
+    m_isPressed = false;
+    update();
 }
 
 void CrumblePathButton::setSegmentType(int type)
 {
     bool useLeftPadding = !(type & FirstSegment);
-    if (type & LastSegment) {
-        setStyleSheet(lastSegmentSheet(useLeftPadding));
-    } else if (type & MiddleSegment) {
-        setStyleSheet(middleSegmentSheet(useLeftPadding));
-    }
+    m_isEnd = (type & LastSegment);
+    m_textPos.setX(useLeftPadding ? 18 : 4);
 }
 
 //
@@ -120,11 +180,13 @@ void CrumblePathButton::setSegmentType(int type)
 CrumblePath::CrumblePath(QWidget *parent) :
     QWidget(parent), m_background(new QWidget(this))
 {
+    m_baseColor = StyleHelper::baseColor();
+
     setMinimumHeight(25);
     setMaximumHeight(25);
     setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
 
-    m_background->setStyleSheet("QWidget { background-color:#2d2d2d;}");
+    setBackgroundStyle();
     m_background->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
 }
 
@@ -134,6 +196,11 @@ CrumblePath::~CrumblePath()
     m_buttons.clear();
 }
 
+void CrumblePath::setBackgroundStyle()
+{
+    m_background->setStyleSheet("QWidget { background-color:" + m_baseColor.name() + ";}");
+}
+
 void CrumblePath::pushElement(const QString &title)
 {
     CrumblePathButton *newButton = new CrumblePathButton(title, this);
@@ -248,4 +315,14 @@ void CrumblePath::mapContextMenuRequestToIndex()
     }
 }
 
+void CrumblePath::paintEvent(QPaintEvent *event)
+{
+    if (StyleHelper::baseColor() != m_baseColor) {
+        m_baseColor = StyleHelper::baseColor();
+        setBackgroundStyle();
+    }
+
+    QWidget::paintEvent(event);
+}
+
 } // namespace QmlViewer
diff --git a/src/libs/utils/crumblepath.h b/src/libs/utils/crumblepath.h
index 5a78a96e999..36ca40b1dfd 100644
--- a/src/libs/utils/crumblepath.h
+++ b/src/libs/utils/crumblepath.h
@@ -58,6 +58,7 @@ signals:
 
 protected:
     void resizeEvent(QResizeEvent *);
+    void paintEvent(QPaintEvent *);
 
 private slots:
     void mapClickToIndex();
@@ -65,8 +66,10 @@ private slots:
 
 private:
     void resizeButtons();
+    void setBackgroundStyle();
 
 private:
+    QColor m_baseColor;
     QList<CrumblePathButton*> m_buttons;
     QWidget *m_background;
 };
diff --git a/src/libs/qmljsdebugger/editor/images/segment-end.png b/src/libs/utils/images/crumblepath-segment-end.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment-end.png
rename to src/libs/utils/images/crumblepath-segment-end.png
diff --git a/src/libs/qmljsdebugger/editor/images/segment-hover-end.png b/src/libs/utils/images/crumblepath-segment-hover-end.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment-hover-end.png
rename to src/libs/utils/images/crumblepath-segment-hover-end.png
diff --git a/src/libs/qmljsdebugger/editor/images/segment-hover.png b/src/libs/utils/images/crumblepath-segment-hover.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment-hover.png
rename to src/libs/utils/images/crumblepath-segment-hover.png
diff --git a/src/libs/qmljsdebugger/editor/images/segment-selected-end.png b/src/libs/utils/images/crumblepath-segment-selected-end.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment-selected-end.png
rename to src/libs/utils/images/crumblepath-segment-selected-end.png
diff --git a/src/libs/qmljsdebugger/editor/images/segment-selected.png b/src/libs/utils/images/crumblepath-segment-selected.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment-selected.png
rename to src/libs/utils/images/crumblepath-segment-selected.png
diff --git a/src/libs/qmljsdebugger/editor/images/segment.png b/src/libs/utils/images/crumblepath-segment.png
similarity index 100%
rename from src/libs/qmljsdebugger/editor/images/segment.png
rename to src/libs/utils/images/crumblepath-segment.png
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index a98cceb5564..0bd511e6988 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -479,4 +479,28 @@ void StyleHelper::drawCornerImage(const QImage &img, QPainter *painter, QRect re
     }
 }
 
+// Tints an image with tintColor, while preserving alpha and lightness
+void StyleHelper::tintImage(QImage &img, const QColor &tintColor)
+{
+    QPainter p(&img);
+    p.setCompositionMode(QPainter::CompositionMode_Screen);
+
+    for (int x = 0; x < img.width(); ++x) {
+        for (int y = 0; y < img.height(); ++y) {
+            QRgb rgbColor = img.pixel(x, y);
+            int alpha = qAlpha(rgbColor);
+            QColor c = QColor(rgbColor);
+
+            if (alpha > 0) {
+                c.toHsl();
+                qreal l = c.lightnessF();
+                QColor newColor = QColor::fromHslF(tintColor.hslHueF(), tintColor.hslSaturationF(), l);
+                newColor.setAlpha(alpha);
+                img.setPixel(x, y, newColor.rgba());
+            }
+        }
+    }
+}
+
+
 } // namespace Utils
diff --git a/src/libs/utils/stylehelper.h b/src/libs/utils/stylehelper.h
index 75435c4f889..99ae20a9914 100644
--- a/src/libs/utils/stylehelper.h
+++ b/src/libs/utils/stylehelper.h
@@ -88,6 +88,8 @@ public:
     static void drawCornerImage(const QImage &img, QPainter *painter, QRect rect,
                          int left = 0, int top = 0, int right = 0, int bottom = 0);
 
+    static void tintImage(QImage &img, const QColor &tintColor);
+
 private:
     static QColor m_baseColor;
     static QColor m_requestedBaseColor;
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index 6642ce74749..43fbbd1096b 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -2,5 +2,11 @@
     <qresource prefix="/utils">
         <file>images/removesubmitfield.png</file>
         <file>images/arrow.png</file>
+        <file>images/crumblepath-segment.png</file>
+        <file>images/crumblepath-segment-end.png</file>
+        <file>images/crumblepath-segment-hover-end.png</file>
+        <file>images/crumblepath-segment-hover.png</file>
+        <file>images/crumblepath-segment-selected-end.png</file>
+        <file>images/crumblepath-segment-selected.png</file>
     </qresource>
 </RCC>
-- 
GitLab