]> cloud.milkyroute.net Git - dolphin.git/blob - src/tooltips/ktooltip.cpp
Remove code that's no longer needed now that Qt supports ARGB windows.
[dolphin.git] / src / tooltips / ktooltip.cpp
1 /***************************************************************************
2 * Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org> *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19
20 #include "ktooltip.h"
21
22 #include <QApplication>
23 #include <QMap>
24 #include <QPixmap>
25 #include <QPainter>
26 #include <QVariant>
27 #include <QIcon>
28 #include <QWidget>
29 #include <QToolTip>
30 #include <QDebug>
31
32 #ifdef Q_WS_X11
33 # include <QX11Info>
34 # include <X11/Xlib.h>
35 # include <X11/extensions/shape.h>
36 #endif
37
38 #include "ktooltip_p.h"
39
40
41 // compile with XShape older than 1.0
42 #ifndef ShapeInput
43 const int ShapeInput = 2;
44 #endif
45
46
47 class KToolTipItemPrivate
48 {
49 public:
50 QMap<int, QVariant> map;
51 int type;
52 };
53
54 KToolTipItem::KToolTipItem(const QString &text, int type)
55 : d(new KToolTipItemPrivate)
56 {
57 d->map[Qt::DisplayRole] = text;
58 d->type = type;
59 }
60
61 KToolTipItem::KToolTipItem(const QIcon &icon, const QString &text, int type)
62 : d(new KToolTipItemPrivate)
63 {
64 d->map[Qt::DecorationRole] = icon;
65 d->map[Qt::DisplayRole] = text;
66 d->type = type;
67 }
68
69 KToolTipItem::~KToolTipItem()
70 {
71 delete d;
72 }
73
74 int KToolTipItem::type() const
75 {
76 return d->type;
77 }
78
79 QString KToolTipItem::text() const
80 {
81 return data(Qt::DisplayRole).toString();
82 }
83
84 QIcon KToolTipItem::icon() const
85 {
86 return qvariant_cast<QIcon>(data(Qt::DecorationRole));
87 }
88
89 QVariant KToolTipItem::data(int role) const
90 {
91 return d->map.value(role);
92 }
93
94 void KToolTipItem::setData(int role, const QVariant &data)
95 {
96 d->map[role] = data;
97 KToolTipManager::instance()->update();
98 }
99
100
101
102 // ----------------------------------------------------------------------------
103
104
105 KStyleOptionToolTip::KStyleOptionToolTip()
106 : fontMetrics(QApplication::font())
107 {
108 }
109
110
111 // ----------------------------------------------------------------------------
112
113
114
115 KToolTipDelegate::KToolTipDelegate() : QObject()
116 {
117 }
118
119 KToolTipDelegate::~KToolTipDelegate()
120 {
121 }
122
123 QSize KToolTipDelegate::sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const
124 {
125 QSize size;
126 size.rwidth() = option->fontMetrics.width(item->text());
127 size.rheight() = option->fontMetrics.lineSpacing();
128
129 QIcon icon = item->icon();
130 if (!icon.isNull()) {
131 const QSize iconSize = icon.actualSize(option->decorationSize);
132 size.rwidth() += iconSize.width() + 4;
133 size.rheight() = qMax(size.height(), iconSize.height());
134 }
135
136 return size + QSize(20, 20);
137
138 }
139
140 void KToolTipDelegate::paint(QPainter *painter, const KStyleOptionToolTip *option,
141 const KToolTipItem *item) const
142 {
143 bool haveAlpha = haveAlphaChannel();
144 painter->setRenderHint(QPainter::Antialiasing);
145
146 QPainterPath path;
147 if (haveAlpha)
148 path.addRoundRect(option->rect.adjusted(0, 0, -1, -1), 25);
149 else
150 path.addRect(option->rect.adjusted(0, 0, -1, -1));
151
152 QColor color = option->palette.color(QPalette::ToolTipBase);
153 QColor from = color.lighter(105);
154 QColor to = color.darker(120);
155
156 QLinearGradient gradient(0, 0, 0, 1);
157 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
158 gradient.setColorAt(0, from);
159 gradient.setColorAt(1, to);
160
161 painter->translate(.5, .5);
162 painter->setPen(QPen(Qt::black, 1));
163 painter->setBrush(gradient);
164 painter->drawPath(path);
165 painter->translate(-.5, -.5);
166
167 if (haveAlpha) {
168 QLinearGradient mask(0, 0, 0, 1);
169 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
170 gradient.setColorAt(0, QColor(0, 0, 0, 192));
171 gradient.setColorAt(1, QColor(0, 0, 0, 72));
172 painter->setCompositionMode(QPainter::CompositionMode_DestinationIn);
173 painter->fillRect(option->rect, gradient);
174 painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
175 }
176
177 QRect textRect = option->rect.adjusted(10, 10, -10, -10);
178
179 QIcon icon = item->icon();
180 if (!icon.isNull()) {
181 const QSize iconSize = icon.actualSize(option->decorationSize);
182 painter->drawPixmap(textRect.topLeft(), icon.pixmap(iconSize));
183 textRect.adjust(iconSize.width() + 4, 0, 0, 0);
184 }
185 painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, item->text());
186 }
187
188 QRegion KToolTipDelegate::inputShape(const KStyleOptionToolTip *option) const
189 {
190 return QRegion(option->rect);
191 }
192
193 QRegion KToolTipDelegate::shapeMask(const KStyleOptionToolTip *option) const
194 {
195 return QRegion(option->rect);
196 }
197
198 bool KToolTipDelegate::haveAlphaChannel() const
199 {
200 return QX11Info::isCompositingManagerRunning();
201 }
202
203
204
205 // ----------------------------------------------------------------------------
206
207
208
209 class KTipLabel : public QWidget
210 {
211 public:
212 KTipLabel();
213 void showTip(const QPoint &pos, const KToolTipItem *item);
214 void moveTip(const QPoint &pos);
215 void hideTip();
216
217 private:
218 void paintEvent(QPaintEvent*);
219 QSize sizeHint() const;
220 KStyleOptionToolTip styleOption() const;
221 KToolTipDelegate *delegate() const;
222
223 private:
224 const KToolTipItem *currentItem;
225 };
226
227 KTipLabel::KTipLabel() : QWidget(0, Qt::ToolTip)
228 {
229 if (QX11Info::isCompositingManagerRunning()) {
230 setAttribute(Qt::WA_TranslucentBackground);
231 }
232 }
233
234 void KTipLabel::showTip(const QPoint &pos, const KToolTipItem *item)
235 {
236 currentItem = item;
237 move(pos);
238 show();
239 }
240
241 void KTipLabel::hideTip()
242 {
243 hide();
244 currentItem = 0;
245 }
246
247 void KTipLabel::moveTip(const QPoint &pos)
248 {
249 move(pos);
250 }
251
252 void KTipLabel::paintEvent(QPaintEvent*)
253 {
254 KStyleOptionToolTip option = styleOption();
255 option.rect = rect();
256
257 if (QX11Info::isCompositingManagerRunning())
258 XShapeCombineRegion(x11Info().display(), winId(), ShapeInput, 0, 0,
259 delegate()->inputShape(&option).handle(), ShapeSet);
260 else
261 setMask(delegate()->shapeMask(&option));
262
263 QPainter p(this);
264 p.setFont(option.font);
265 p.setPen(QPen(option.palette.brush(QPalette::Text), 0));
266 delegate()->paint(&p, &option, currentItem);
267 }
268
269 QSize KTipLabel::sizeHint() const
270 {
271 if (!currentItem)
272 return QSize();
273
274 KStyleOptionToolTip option = styleOption();
275 return delegate()->sizeHint(&option, currentItem);
276 }
277
278 KStyleOptionToolTip KTipLabel::styleOption() const
279 {
280 KStyleOptionToolTip option;
281 KToolTipManager::instance()->initStyleOption(&option);
282 return option;
283 }
284
285 KToolTipDelegate *KTipLabel::delegate() const
286 {
287 return KToolTipManager::instance()->delegate();
288 }
289
290
291
292
293 // ----------------------------------------------------------------------------
294
295
296
297
298 KToolTipManager *KToolTipManager::s_instance = 0;
299
300 KToolTipManager::KToolTipManager()
301 : label(new KTipLabel), currentItem(0), m_delegate(0)
302 {
303 }
304
305 KToolTipManager::~KToolTipManager()
306 {
307 delete label;
308 delete currentItem;
309 }
310
311 void KToolTipManager::showTip(const QPoint &pos, KToolTipItem *item)
312 {
313 hideTip();
314 label->showTip(pos, item);
315 currentItem = item;
316 m_tooltipPos = pos;
317 }
318
319 void KToolTipManager::hideTip()
320 {
321 label->hideTip();
322 delete currentItem;
323 currentItem = 0;
324 }
325
326 void KToolTipManager::initStyleOption(KStyleOptionToolTip *option) const
327 {
328 option->direction = QApplication::layoutDirection();
329 option->fontMetrics = QFontMetrics(QToolTip::font());
330 option->activeCorner = KStyleOptionToolTip::TopLeftCorner;
331 option->palette = QToolTip::palette();
332 option->font = QToolTip::font();
333 option->rect = QRect();
334 option->state = QStyle::State_None;
335 option->decorationSize = QSize(32, 32);
336 }
337
338 void KToolTipManager::setDelegate(KToolTipDelegate *delegate)
339 {
340 m_delegate = delegate;
341 }
342
343 void KToolTipManager::update()
344 {
345 if (currentItem == 0)
346 return;
347 label->showTip(m_tooltipPos, currentItem);
348 }
349
350 KToolTipDelegate *KToolTipManager::delegate() const
351 {
352 return m_delegate;
353 }
354
355
356
357 // ----------------------------------------------------------------------------
358
359
360
361 namespace KToolTip
362 {
363 void showText(const QPoint &pos, const QString &text, QWidget *widget, const QRect &rect)
364 {
365 Q_UNUSED(widget)
366 Q_UNUSED(rect)
367 KToolTipItem *item = new KToolTipItem(text);
368 KToolTipManager::instance()->showTip(pos, item);
369 }
370
371 void showText(const QPoint &pos, const QString &text, QWidget *widget)
372 {
373 showText(pos, text, widget, QRect());
374 }
375
376 void showTip(const QPoint &pos, KToolTipItem *item)
377 {
378 KToolTipManager::instance()->showTip(pos, item);
379 }
380
381 void hideTip()
382 {
383 KToolTipManager::instance()->hideTip();
384 }
385
386 void setToolTipDelegate(KToolTipDelegate *delegate)
387 {
388 KToolTipManager::instance()->setDelegate(delegate);
389 }
390 }
391