1 /***************************************************************************
2 * Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
21 #include "ktooltip_p.h"
23 #include <QApplication>
35 # include <X11/Xlib.h>
36 # include <X11/extensions/shape.h>
39 // compile with XShape older than 1.0
41 const int ShapeInput
= 2;
45 class KToolTipItemPrivate
48 QMap
<int, QVariant
> map
;
52 KToolTipItem::KToolTipItem(const QString
&text
, int type
)
53 : d(new KToolTipItemPrivate
)
55 d
->map
[Qt::DisplayRole
] = text
;
59 KToolTipItem::KToolTipItem(const QIcon
&icon
, const QString
&text
, int type
)
60 : d(new KToolTipItemPrivate
)
62 d
->map
[Qt::DecorationRole
] = icon
;
63 d
->map
[Qt::DisplayRole
] = text
;
67 KToolTipItem::~KToolTipItem()
72 int KToolTipItem::type() const
77 QString
KToolTipItem::text() const
79 return data(Qt::DisplayRole
).toString();
82 QIcon
KToolTipItem::icon() const
84 return qvariant_cast
<QIcon
>(data(Qt::DecorationRole
));
87 QVariant
KToolTipItem::data(int role
) const
89 return d
->map
.value(role
);
92 void KToolTipItem::setData(int role
, const QVariant
&data
)
95 KToolTipManager::instance()->update();
100 // ----------------------------------------------------------------------------
103 KStyleOptionToolTip::KStyleOptionToolTip()
104 : fontMetrics(QApplication::font())
109 // ----------------------------------------------------------------------------
113 KToolTipDelegate::KToolTipDelegate() : QObject()
117 KToolTipDelegate::~KToolTipDelegate()
121 QSize
KToolTipDelegate::sizeHint(const KStyleOptionToolTip
&option
, const KToolTipItem
&item
) const
124 size
.rwidth() = option
.fontMetrics
.width(item
.text());
125 size
.rheight() = option
.fontMetrics
.lineSpacing();
127 QIcon icon
= item
.icon();
128 if (!icon
.isNull()) {
129 const QSize iconSize
= icon
.actualSize(option
.decorationSize
);
130 size
.rwidth() += iconSize
.width() + 4;
131 size
.rheight() = qMax(size
.height(), iconSize
.height());
134 return size
+ QSize(20, 20);
138 void KToolTipDelegate::paint(QPainter
*painter
,
139 const KStyleOptionToolTip
&option
,
140 const KToolTipItem
&item
) const
142 bool haveAlpha
= haveAlphaChannel();
143 painter
->setRenderHint(QPainter::Antialiasing
);
147 path
.addRoundRect(option
.rect
.adjusted(0, 0, -1, -1), 25);
149 path
.addRect(option
.rect
.adjusted(0, 0, -1, -1));
151 QColor color
= option
.palette
.color(QPalette::ToolTipBase
);
152 QColor from
= color
.lighter(105);
153 QColor to
= color
.darker(120);
155 QLinearGradient
gradient(0, 0, 0, 1);
156 gradient
.setCoordinateMode(QGradient::ObjectBoundingMode
);
157 gradient
.setColorAt(0, from
);
158 gradient
.setColorAt(1, to
);
160 painter
->translate(.5, .5);
161 painter
->setPen(QPen(Qt::black
, 1));
162 painter
->setBrush(gradient
);
163 painter
->drawPath(path
);
164 painter
->translate(-.5, -.5);
167 QLinearGradient
mask(0, 0, 0, 1);
168 gradient
.setCoordinateMode(QGradient::ObjectBoundingMode
);
169 gradient
.setColorAt(0, QColor(0, 0, 0, 192));
170 gradient
.setColorAt(1, QColor(0, 0, 0, 72));
171 painter
->setCompositionMode(QPainter::CompositionMode_DestinationIn
);
172 painter
->fillRect(option
.rect
, gradient
);
173 painter
->setCompositionMode(QPainter::CompositionMode_SourceOver
);
176 QRect textRect
= option
.rect
.adjusted(10, 10, -10, -10);
178 QIcon icon
= item
.icon();
179 if (!icon
.isNull()) {
180 const QSize iconSize
= icon
.actualSize(option
.decorationSize
);
181 painter
->drawPixmap(textRect
.topLeft(), icon
.pixmap(iconSize
));
182 textRect
.adjust(iconSize
.width() + 4, 0, 0, 0);
184 painter
->drawText(textRect
, Qt::AlignLeft
| Qt::AlignVCenter
, item
.text());
187 QRegion
KToolTipDelegate::inputShape(const KStyleOptionToolTip
&option
) const
189 return QRegion(option
.rect
);
192 QRegion
KToolTipDelegate::shapeMask(const KStyleOptionToolTip
&option
) const
194 return QRegion(option
.rect
);
197 bool KToolTipDelegate::haveAlphaChannel() const
200 return QX11Info::isCompositingManagerRunning();
208 // ----------------------------------------------------------------------------
212 class KTipLabel
: public QWidget
216 void showTip(const QPoint
&pos
, const KToolTipItem
*item
);
217 void moveTip(const QPoint
&pos
);
221 void paintEvent(QPaintEvent
*);
222 QSize
sizeHint() const;
223 KStyleOptionToolTip
styleOption() const;
224 KToolTipDelegate
*delegate() const;
227 const KToolTipItem
*m_currentItem
;
230 KTipLabel::KTipLabel() : QWidget(0, Qt::ToolTip
)
233 if (QX11Info::isCompositingManagerRunning()) {
234 setAttribute(Qt::WA_TranslucentBackground
);
239 void KTipLabel::showTip(const QPoint
&pos
, const KToolTipItem
*item
)
241 m_currentItem
= item
;
246 void KTipLabel::hideTip()
252 void KTipLabel::moveTip(const QPoint
&pos
)
257 void KTipLabel::paintEvent(QPaintEvent
*)
259 KStyleOptionToolTip option
= styleOption();
260 option
.rect
= rect();
263 if (QX11Info::isCompositingManagerRunning())
264 XShapeCombineRegion(x11Info().display(), winId(), ShapeInput
, 0, 0,
265 delegate()->inputShape(option
).handle(), ShapeSet
);
268 setMask(delegate()->shapeMask(option
));
271 p
.setFont(option
.font
);
272 p
.setPen(QPen(option
.palette
.brush(QPalette::Text
), 0));
273 delegate()->paint(&p
, option
, *m_currentItem
);
276 QSize
KTipLabel::sizeHint() const
281 KStyleOptionToolTip option
= styleOption();
282 return delegate()->sizeHint(option
, *m_currentItem
);
285 KStyleOptionToolTip
KTipLabel::styleOption() const
287 KStyleOptionToolTip option
;
288 KToolTipManager::instance()->initStyleOption(&option
);
292 KToolTipDelegate
*KTipLabel::delegate() const
294 return KToolTipManager::instance()->delegate();
300 // ----------------------------------------------------------------------------
305 KToolTipManager
*KToolTipManager::s_instance
= 0;
307 KToolTipManager::KToolTipManager()
308 : m_label(new KTipLabel
), m_currentItem(0), m_delegate(0)
312 KToolTipManager::~KToolTipManager()
315 delete m_currentItem
;
318 void KToolTipManager::showTip(const QPoint
&pos
, KToolTipItem
*item
)
321 m_label
->showTip(pos
, item
);
322 m_currentItem
= item
;
326 void KToolTipManager::hideTip()
329 delete m_currentItem
;
333 void KToolTipManager::initStyleOption(KStyleOptionToolTip
*option
) const
335 option
->direction
= QApplication::layoutDirection();
336 option
->fontMetrics
= QFontMetrics(QToolTip::font());
337 option
->activeCorner
= KStyleOptionToolTip::TopLeftCorner
;
338 option
->palette
= QToolTip::palette();
339 option
->font
= QToolTip::font();
340 option
->rect
= QRect();
341 option
->state
= QStyle::State_None
;
342 option
->decorationSize
= QSize(32, 32);
345 void KToolTipManager::setDelegate(KToolTipDelegate
*delegate
)
347 m_delegate
= delegate
;
350 void KToolTipManager::update()
352 if (m_currentItem
== 0)
354 m_label
->showTip(m_tooltipPos
, m_currentItem
);
357 KToolTipDelegate
*KToolTipManager::delegate() const
364 // ----------------------------------------------------------------------------
370 void showText(const QPoint
&pos
, const QString
&text
, QWidget
*widget
, const QRect
&rect
)
374 KToolTipItem
*item
= new KToolTipItem(text
);
375 KToolTipManager::instance()->showTip(pos
, item
);
378 void showText(const QPoint
&pos
, const QString
&text
, QWidget
*widget
)
380 showText(pos
, text
, widget
, QRect());
383 void showTip(const QPoint
&pos
, KToolTipItem
*item
)
385 KToolTipManager::instance()->showTip(pos
, item
);
390 KToolTipManager::instance()->hideTip();
393 void setToolTipDelegate(KToolTipDelegate
*delegate
)
395 KToolTipManager::instance()->setDelegate(delegate
);