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