]> cloud.milkyroute.net Git - dolphin.git/blob - src/tooltips/ktooltip.cpp
win32 compile fix
[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 #ifdef Q_WS_X11
201 return QX11Info::isCompositingManagerRunning();
202 #else
203 return false;
204 #endif
205 }
206
207
208
209 // ----------------------------------------------------------------------------
210
211
212
213 class KTipLabel : public QWidget
214 {
215 public:
216 KTipLabel();
217 void showTip(const QPoint &pos, const KToolTipItem *item);
218 void moveTip(const QPoint &pos);
219 void hideTip();
220
221 private:
222 void paintEvent(QPaintEvent*);
223 QSize sizeHint() const;
224 KStyleOptionToolTip styleOption() const;
225 KToolTipDelegate *delegate() const;
226
227 private:
228 const KToolTipItem *currentItem;
229 };
230
231 KTipLabel::KTipLabel() : QWidget(0, Qt::ToolTip)
232 {
233 #ifdef Q_WS_X11
234 if (QX11Info::isCompositingManagerRunning()) {
235 setAttribute(Qt::WA_TranslucentBackground);
236 }
237 #endif
238 }
239
240 void KTipLabel::showTip(const QPoint &pos, const KToolTipItem *item)
241 {
242 currentItem = item;
243 move(pos);
244 show();
245 }
246
247 void KTipLabel::hideTip()
248 {
249 hide();
250 currentItem = 0;
251 }
252
253 void KTipLabel::moveTip(const QPoint &pos)
254 {
255 move(pos);
256 }
257
258 void KTipLabel::paintEvent(QPaintEvent*)
259 {
260 KStyleOptionToolTip option = styleOption();
261 option.rect = rect();
262
263 #ifdef Q_WS_X11
264 if (QX11Info::isCompositingManagerRunning())
265 XShapeCombineRegion(x11Info().display(), winId(), ShapeInput, 0, 0,
266 delegate()->inputShape(&option).handle(), ShapeSet);
267 else
268 #endif
269 setMask(delegate()->shapeMask(&option));
270
271 QPainter p(this);
272 p.setFont(option.font);
273 p.setPen(QPen(option.palette.brush(QPalette::Text), 0));
274 delegate()->paint(&p, &option, currentItem);
275 }
276
277 QSize KTipLabel::sizeHint() const
278 {
279 if (!currentItem)
280 return QSize();
281
282 KStyleOptionToolTip option = styleOption();
283 return delegate()->sizeHint(&option, currentItem);
284 }
285
286 KStyleOptionToolTip KTipLabel::styleOption() const
287 {
288 KStyleOptionToolTip option;
289 KToolTipManager::instance()->initStyleOption(&option);
290 return option;
291 }
292
293 KToolTipDelegate *KTipLabel::delegate() const
294 {
295 return KToolTipManager::instance()->delegate();
296 }
297
298
299
300
301 // ----------------------------------------------------------------------------
302
303
304
305
306 KToolTipManager *KToolTipManager::s_instance = 0;
307
308 KToolTipManager::KToolTipManager()
309 : label(new KTipLabel), currentItem(0), m_delegate(0)
310 {
311 }
312
313 KToolTipManager::~KToolTipManager()
314 {
315 delete label;
316 delete currentItem;
317 }
318
319 void KToolTipManager::showTip(const QPoint &pos, KToolTipItem *item)
320 {
321 hideTip();
322 label->showTip(pos, item);
323 currentItem = item;
324 m_tooltipPos = pos;
325 }
326
327 void KToolTipManager::hideTip()
328 {
329 label->hideTip();
330 delete currentItem;
331 currentItem = 0;
332 }
333
334 void KToolTipManager::initStyleOption(KStyleOptionToolTip *option) const
335 {
336 option->direction = QApplication::layoutDirection();
337 option->fontMetrics = QFontMetrics(QToolTip::font());
338 option->activeCorner = KStyleOptionToolTip::TopLeftCorner;
339 option->palette = QToolTip::palette();
340 option->font = QToolTip::font();
341 option->rect = QRect();
342 option->state = QStyle::State_None;
343 option->decorationSize = QSize(32, 32);
344 }
345
346 void KToolTipManager::setDelegate(KToolTipDelegate *delegate)
347 {
348 m_delegate = delegate;
349 }
350
351 void KToolTipManager::update()
352 {
353 if (currentItem == 0)
354 return;
355 label->showTip(m_tooltipPos, currentItem);
356 }
357
358 KToolTipDelegate *KToolTipManager::delegate() const
359 {
360 return m_delegate;
361 }
362
363
364
365 // ----------------------------------------------------------------------------
366
367
368
369 namespace KToolTip
370 {
371 void showText(const QPoint &pos, const QString &text, QWidget *widget, const QRect &rect)
372 {
373 Q_UNUSED(widget)
374 Q_UNUSED(rect)
375 KToolTipItem *item = new KToolTipItem(text);
376 KToolTipManager::instance()->showTip(pos, item);
377 }
378
379 void showText(const QPoint &pos, const QString &text, QWidget *widget)
380 {
381 showText(pos, text, widget, QRect());
382 }
383
384 void showTip(const QPoint &pos, KToolTipItem *item)
385 {
386 KToolTipManager::instance()->showTip(pos, item);
387 }
388
389 void hideTip()
390 {
391 KToolTipManager::instance()->hideTip();
392 }
393
394 void setToolTipDelegate(KToolTipDelegate *delegate)
395 {
396 KToolTipManager::instance()->setDelegate(delegate);
397 }
398 }
399