1 /*
2     SPDX-FileCopyrightText: 2000 Peter Putzer <putzer@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "kurllabel.h"
8 
9 #include <QApplication>
10 #include <QMouseEvent>
11 #include <QPalette>
12 #include <QTimer>
13 
14 class KUrlLabelPrivate
15 {
16 public:
KUrlLabelPrivate(const QString & _url,KUrlLabel * _parent)17     KUrlLabelPrivate(const QString &_url, KUrlLabel *_parent)
18         : parent(_parent)
19         , url(_url)
20         , tipText(url)
21         , linkColor(_parent->palette().color(QPalette::Active, QPalette::Link))
22         , highlightedLinkColor(_parent->palette().color(QPalette::Active, QPalette::BrightText))
23         , cursor(nullptr)
24         , textUnderlined(true)
25         , realUnderlined(true)
26         , useTips(false)
27         , useCursor(false)
28         , glowEnabled(true)
29         , floatEnabled(false)
30         , timer(new QTimer(parent))
31     {
32         QObject::connect(timer, &QTimer::timeout, parent, [this]() {
33             updateColor();
34         });
35     }
36 
updateColor()37     void updateColor()
38     {
39         timer->stop();
40 
41         if (!(glowEnabled || floatEnabled) || !parent->rect().contains(parent->mapFromGlobal(QCursor::pos()))) {
42             setLinkColor(linkColor);
43         }
44     }
45 
setLinkColor(const QColor & color)46     void setLinkColor(const QColor &color)
47     {
48         QPalette palette = parent->palette();
49         palette.setColor(QPalette::WindowText, color);
50         parent->setPalette(palette);
51 
52         parent->update();
53     }
54 
55     KUrlLabel *parent;
56 
57     QString url;
58     QString tipText;
59     QColor linkColor;
60     QColor highlightedLinkColor;
61     QCursor *cursor;
62     bool textUnderlined : 1;
63     bool realUnderlined : 1;
64     bool useTips : 1;
65     bool useCursor : 1;
66     bool glowEnabled : 1;
67     bool floatEnabled : 1;
68     QPixmap alternatePixmap;
69     QPixmap realPixmap;
70     QTimer *timer;
71 };
72 
KUrlLabel(const QString & url,const QString & text,QWidget * parent)73 KUrlLabel::KUrlLabel(const QString &url, const QString &text, QWidget *parent)
74     : QLabel(!text.isNull() ? text : url, parent)
75     , d(new KUrlLabelPrivate(url, this))
76 {
77     setFont(font());
78     setCursor(QCursor(Qt::PointingHandCursor));
79     d->setLinkColor(d->linkColor);
80 }
81 
KUrlLabel(QWidget * parent)82 KUrlLabel::KUrlLabel(QWidget *parent)
83     : QLabel(parent)
84     , d(new KUrlLabelPrivate(QString(), this))
85 {
86     setFont(font());
87     setCursor(QCursor(Qt::PointingHandCursor));
88     d->setLinkColor(d->linkColor);
89 }
90 
91 KUrlLabel::~KUrlLabel() = default;
92 
mouseReleaseEvent(QMouseEvent * event)93 void KUrlLabel::mouseReleaseEvent(QMouseEvent *event)
94 {
95     QLabel::mouseReleaseEvent(event);
96 
97     d->setLinkColor(d->highlightedLinkColor);
98     d->timer->start(300);
99 
100     switch (event->button()) {
101     case Qt::LeftButton:
102         Q_EMIT leftClickedUrl();
103 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 65)
104         Q_EMIT leftClickedUrl(d->url);
105 #endif
106         break;
107 
108     case Qt::MiddleButton:
109         Q_EMIT middleClickedUrl();
110 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 65)
111         Q_EMIT middleClickedUrl(d->url);
112 #endif
113         break;
114 
115     case Qt::RightButton:
116         Q_EMIT rightClickedUrl();
117 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 65)
118         Q_EMIT rightClickedUrl(d->url);
119 #endif
120         break;
121 
122     default:
123         break;
124     }
125 }
126 
setFont(const QFont & font)127 void KUrlLabel::setFont(const QFont &font)
128 {
129     QFont newFont = font;
130     newFont.setUnderline(d->textUnderlined);
131 
132     QLabel::setFont(newFont);
133 }
134 
setUnderline(bool on)135 void KUrlLabel::setUnderline(bool on)
136 {
137     d->textUnderlined = on;
138 
139     setFont(font());
140 }
141 
setUrl(const QString & url)142 void KUrlLabel::setUrl(const QString &url)
143 {
144     if (d->tipText == d->url) { // update the tip as well
145         d->tipText = url;
146         setUseTips(d->useTips);
147     }
148 
149     d->url = url;
150 }
151 
url() const152 QString KUrlLabel::url() const
153 {
154     return d->url;
155 }
156 
setUseCursor(bool on,QCursor * cursor)157 void KUrlLabel::setUseCursor(bool on, QCursor *cursor)
158 {
159     d->useCursor = on;
160     d->cursor = cursor;
161 
162     if (on) {
163         if (cursor) {
164             setCursor(*cursor);
165         } else {
166             setCursor(QCursor(Qt::PointingHandCursor));
167         }
168     } else {
169         unsetCursor();
170     }
171 }
172 
useCursor() const173 bool KUrlLabel::useCursor() const
174 {
175     return d->useCursor;
176 }
177 
setUseTips(bool on)178 void KUrlLabel::setUseTips(bool on)
179 {
180     d->useTips = on;
181 
182     if (on) {
183         setToolTip(d->tipText);
184     } else {
185         setToolTip(QString());
186     }
187 }
188 
setTipText(const QString & tipText)189 void KUrlLabel::setTipText(const QString &tipText)
190 {
191     d->tipText = tipText;
192 
193     setUseTips(d->useTips);
194 }
195 
useTips() const196 bool KUrlLabel::useTips() const
197 {
198     return d->useTips;
199 }
200 
tipText() const201 QString KUrlLabel::tipText() const
202 {
203     return d->tipText;
204 }
205 
setHighlightedColor(const QColor & color)206 void KUrlLabel::setHighlightedColor(const QColor &color)
207 {
208     d->linkColor = color;
209 
210     if (!d->timer->isActive()) {
211         d->setLinkColor(color);
212     }
213 }
214 
setHighlightedColor(const QString & color)215 void KUrlLabel::setHighlightedColor(const QString &color)
216 {
217     setHighlightedColor(QColor(color));
218 }
219 
setSelectedColor(const QColor & color)220 void KUrlLabel::setSelectedColor(const QColor &color)
221 {
222     d->highlightedLinkColor = color;
223 
224     if (d->timer->isActive()) {
225         d->setLinkColor(color);
226     }
227 }
228 
setSelectedColor(const QString & color)229 void KUrlLabel::setSelectedColor(const QString &color)
230 {
231     setSelectedColor(QColor(color));
232 }
233 
setGlowEnabled(bool glowEnabled)234 void KUrlLabel::setGlowEnabled(bool glowEnabled)
235 {
236     d->glowEnabled = glowEnabled;
237 }
238 
setFloatEnabled(bool floatEnabled)239 void KUrlLabel::setFloatEnabled(bool floatEnabled)
240 {
241     d->floatEnabled = floatEnabled;
242 }
243 
isGlowEnabled() const244 bool KUrlLabel::isGlowEnabled() const
245 {
246     return d->glowEnabled;
247 }
248 
isFloatEnabled() const249 bool KUrlLabel::isFloatEnabled() const
250 {
251     return d->floatEnabled;
252 }
253 
setAlternatePixmap(const QPixmap & pixmap)254 void KUrlLabel::setAlternatePixmap(const QPixmap &pixmap)
255 {
256     d->alternatePixmap = pixmap;
257 }
258 
alternatePixmap() const259 const QPixmap *KUrlLabel::alternatePixmap() const
260 {
261     return &d->alternatePixmap;
262 }
263 
enterEvent(QEvent * event)264 void KUrlLabel::enterEvent(QEvent *event)
265 {
266     QLabel::enterEvent(event);
267 
268     if (!d->alternatePixmap.isNull()) {
269         const auto currentPixmap = pixmap(Qt::ReturnByValue);
270         if (!currentPixmap.isNull()) {
271             d->realPixmap = currentPixmap;
272             setPixmap(d->alternatePixmap);
273         }
274     }
275 
276     if (d->glowEnabled || d->floatEnabled) {
277         d->timer->stop();
278 
279         d->setLinkColor(d->highlightedLinkColor);
280 
281         d->realUnderlined = d->textUnderlined;
282 
283         if (d->floatEnabled) {
284             setUnderline(true);
285         }
286     }
287     Q_EMIT enteredUrl();
288 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 65)
289     Q_EMIT enteredUrl(d->url);
290 #endif
291 }
292 
leaveEvent(QEvent * event)293 void KUrlLabel::leaveEvent(QEvent *event)
294 {
295     QLabel::leaveEvent(event);
296 
297     if (!d->alternatePixmap.isNull() && !pixmap(Qt::ReturnByValue).isNull()) {
298         setPixmap(d->realPixmap);
299     }
300 
301     if ((d->glowEnabled || d->floatEnabled) && !d->timer->isActive()) {
302         d->setLinkColor(d->linkColor);
303     }
304 
305     setUnderline(d->realUnderlined);
306     Q_EMIT leftUrl();
307 #if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(5, 65)
308     Q_EMIT leftUrl(d->url);
309 #endif
310 }
311 
event(QEvent * event)312 bool KUrlLabel::event(QEvent *event)
313 {
314     if (event->type() == QEvent::PaletteChange) {
315         // Use parentWidget() unless you are a toplevel widget, then try qAapp
316         QPalette palette = parentWidget() ? parentWidget()->palette() : qApp->palette();
317 
318         palette.setBrush(QPalette::Base, palette.brush(QPalette::Normal, QPalette::Window));
319         palette.setColor(QPalette::WindowText, this->palette().color(QPalette::Active, QPalette::WindowText));
320         setPalette(palette);
321 
322         d->linkColor = palette.color(QPalette::Active, QPalette::Link);
323         d->updateColor();
324 
325         return true;
326     } else {
327         return QLabel::event(event);
328     }
329 }
330 
331 #include "moc_kurllabel.cpp"
332