Plasma-framework

tooltip.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
3 SPDX-FileCopyrightText: 2011 Artur Duque de Souza <asouza@kde.org>
4 SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
5 SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "tooltip.h"
11#include "appletquickitem.h"
12#include "tooltipdialog.h"
13
14#include <QDebug>
15#include <QQmlEngine>
16#include <QStandardPaths>
17
18#include <KDirWatch>
19#include <KSharedConfig>
20#include <KWindowEffects>
21#include <Plasma/Applet>
22
23ToolTipDialog *ToolTip::s_dialog = nullptr;
24int ToolTip::s_dialogUsers = 0;
25
26ToolTip::ToolTip(QQuickItem *parent)
27 : QQuickItem(parent)
28 , m_tooltipsEnabledGlobally(false)
29 , m_containsMouse(false)
30 , m_location(Plasma::Types::Floating)
31 , m_textFormat(Qt::AutoText)
32 , m_active(true)
33 , m_interactive(false)
34 , m_timeout(-1)
35 , m_usingDialog(false)
36{
37 setAcceptHoverEvents(true);
38 setFiltersChildMouseEvents(true);
39
40 m_showTimer = new QTimer(this);
41 m_showTimer->setSingleShot(true);
42 connect(m_showTimer, &QTimer::timeout, this, &ToolTip::showToolTip);
43
44 loadSettings();
45
46 const QString configFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/plasmarc");
47 KDirWatch::self()->addFile(configFile);
48 QObject::connect(KDirWatch::self(), &KDirWatch::created, this, &ToolTip::settingsChanged);
49 QObject::connect(KDirWatch::self(), &KDirWatch::dirty, this, &ToolTip::settingsChanged);
50}
51
52ToolTip::~ToolTip()
53{
54 if (s_dialog && s_dialog->owner() == this) {
55 s_dialog->setVisible(false);
56 }
57
58 if (m_usingDialog) {
59 --s_dialogUsers;
60 }
61
62 if (s_dialogUsers == 0) {
63 delete s_dialog;
64 s_dialog = nullptr;
65 }
66}
67
68void ToolTip::settingsChanged(const QString &file)
69{
70 if (!file.endsWith(QLatin1String("plasmarc"))) {
71 return;
72 }
73
74 KSharedConfig::openConfig(QStringLiteral("plasmarc"))->reparseConfiguration();
75 loadSettings();
76}
77
78void ToolTip::loadSettings()
79{
80 KConfigGroup cfg = KConfigGroup(KSharedConfig::openConfig(QStringLiteral("plasmarc")), QStringLiteral("PlasmaToolTips"));
81 m_interval = cfg.readEntry("Delay", 700);
82 m_tooltipsEnabledGlobally = (m_interval > 0);
83}
84
86{
87 return m_mainItem.data();
88}
89
90ToolTipDialog *ToolTip::tooltipDialogInstance()
91{
92 if (!s_dialog) {
93 s_dialog = new ToolTipDialog;
94 }
95
96 if (!m_usingDialog) {
97 s_dialogUsers++;
98 m_usingDialog = true;
99 }
100
101 return s_dialog;
102}
103
104void ToolTip::setMainItem(QQuickItem *mainItem)
105{
106 if (m_mainItem.data() != mainItem) {
107 m_mainItem = mainItem;
108
109 Q_EMIT mainItemChanged();
110
111 if (!isValid() && s_dialog && s_dialog->owner() == this) {
112 s_dialog->setVisible(false);
113 }
114 }
115}
116
118{
119 if (!m_active) {
120 return;
121 }
122
124
125 ToolTipDialog *dlg = tooltipDialogInstance();
126
127 if (!mainItem()) {
128 setMainItem(dlg->loadDefaultItem());
129 }
130
131 // Unset the dialog's old contents before reparenting the dialog.
132 dlg->setMainItem(nullptr);
133
135 if (m_location == Plasma::Types::Floating) {
136 QQuickItem *p = parentItem();
137 while (p) {
138 PlasmaQuick::AppletQuickItem *appletItem = qobject_cast<PlasmaQuick::AppletQuickItem *>(p);
139 if (appletItem) {
140 location = appletItem->applet()->location();
141 break;
142 }
143 p = p->parentItem();
144 }
145 }
146
147 if (mainItem()) {
148 mainItem()->setProperty("toolTip", QVariant::fromValue(this));
149 mainItem()->setVisible(true);
150 }
151
153
154 dlg->setHideTimeout(m_timeout);
155 dlg->setOwner(this);
156 dlg->setVisualParent(this);
157 dlg->setMainItem(mainItem());
158 dlg->setInteractive(m_interactive);
159
160 switch (location) {
164 dlg->setFloating(true);
165 dlg->setPopupDirection(Qt::BottomEdge);
166 break;
168 dlg->setFloating(false);
169 dlg->setPopupDirection(Qt::BottomEdge);
170 break;
172 dlg->setFloating(false);
173 dlg->setPopupDirection(Qt::TopEdge);
174 break;
176 dlg->setFloating(false);
177 dlg->setPopupDirection(Qt::RightEdge);
178 break;
180 dlg->setFloating(false);
181 dlg->setPopupDirection(Qt::LeftEdge);
182 break;
183 }
184
185 dlg->setVisible(true);
186 // In case the last owner triggered a dismiss but the dialog is still shown,
187 // showEvent won't be reached and the old timeout will still be effective.
188 // Call keepalive() to make it use the new timeout.
189 dlg->keepalive();
190}
191
193{
194 return m_mainText;
195}
196
197void ToolTip::setMainText(const QString &mainText)
198{
199 if (mainText == m_mainText) {
200 return;
201 }
202
203 m_mainText = mainText;
204 Q_EMIT mainTextChanged();
205
206 if (!isValid() && s_dialog && s_dialog->owner() == this) {
207 s_dialog->setVisible(false);
208 }
209}
210
212{
213 return m_subText;
214}
215
216void ToolTip::setSubText(const QString &subText)
217{
218 if (subText == m_subText) {
219 return;
220 }
221
222 m_subText = subText;
223 Q_EMIT subTextChanged();
224
225 if (!isValid() && s_dialog && s_dialog->owner() == this) {
226 s_dialog->setVisible(false);
227 }
228}
229
230int ToolTip::textFormat() const
231{
232 return m_textFormat;
233}
234
235void ToolTip::setTextFormat(int format)
236{
237 if (m_textFormat == format) {
238 return;
239 }
240
241 m_textFormat = format;
242 Q_EMIT textFormatChanged();
243}
244
246{
247 return m_location;
248}
249
250void ToolTip::setLocation(Plasma::Types::Location location)
251{
252 if (m_location == location) {
253 return;
254 }
255 m_location = location;
256 Q_EMIT locationChanged();
257}
258
259void ToolTip::setActive(bool active)
260{
261 if (m_active == active) {
262 return;
263 }
264
265 m_active = active;
266 if (!active) {
267 tooltipDialogInstance()->dismiss();
268 }
269 Q_EMIT activeChanged();
270}
271
272void ToolTip::setInteractive(bool interactive)
273{
274 if (m_interactive == interactive) {
275 return;
276 }
277
278 m_interactive = interactive;
279
280 Q_EMIT interactiveChanged();
281}
282
283void ToolTip::setTimeout(int timeout)
284{
285 m_timeout = timeout;
286}
287
289{
290 m_showTimer->stop();
291 tooltipDialogInstance()->dismiss();
292}
293
295{
296 m_showTimer->stop();
297 tooltipDialogInstance()->setVisible(false);
298}
299
301{
302 if (m_icon.isValid()) {
303 return m_icon;
304 } else {
305 return QString();
306 }
307}
308
309void ToolTip::setIcon(const QVariant &icon)
310{
311 if (icon == m_icon) {
312 return;
313 }
314
315 m_icon = icon;
316 Q_EMIT iconChanged();
317}
318
320{
321 if (m_image.isValid()) {
322 return m_image;
323 } else {
324 return QString();
325 }
326}
327
328void ToolTip::setImage(const QVariant &image)
329{
330 if (image == m_image) {
331 return;
332 }
333
334 m_image = image;
335 Q_EMIT imageChanged();
336}
337
338bool ToolTip::containsMouse() const
339{
340 return m_containsMouse;
341}
342
343void ToolTip::setContainsMouse(bool contains)
344{
345 if (m_containsMouse != contains) {
346 m_containsMouse = contains;
347 Q_EMIT containsMouseChanged();
348 }
349 if (!contains) {
350 tooltipDialogInstance()->dismiss();
351 }
352}
353
355{
356 Q_UNUSED(event)
357 setContainsMouse(true);
358
359 if (!m_tooltipsEnabledGlobally) {
360 return;
361 }
362
363 if (!isValid()) {
364 return;
365 }
366
367 if (tooltipDialogInstance()->isVisible()) {
368 // We signal the tooltipmanager that we're "potentially interested,
369 // and ask to keep it open for a bit, so other items get the chance
370 // to update the content before the tooltip hides -- this avoids
371 // flickering
372 // It need to be considered only when other items can deal with tooltip area
373 if (m_active) {
374 tooltipDialogInstance()->keepalive();
375 // FIXME: showToolTip needs to be renamed in sync or something like that
376 showToolTip();
377 }
378 } else {
379 m_showTimer->start(m_interval);
380 }
381}
382
384{
385 Q_UNUSED(event)
386 setContainsMouse(false);
387 m_showTimer->stop();
388}
389
391{
392 if (event->type() == QEvent::MouseButtonPress) {
393 hideToolTip();
394 }
396}
397
398bool ToolTip::isValid() const
399{
400 return m_mainItem || !mainText().isEmpty() || !subText().isEmpty();
401}
402
403#include "moc_tooltip.cpp"
QString readEntry(const char *key, const char *aDefault=nullptr) const
void addFile(const QString &file)
static KDirWatch * self()
void dirty(const QString &path)
void created(const QString &path)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Plasma::Types::Location location
The location of the scene which is displaying applet.
Definition applet.h:95
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
Definition plasma.h:81
@ RightEdge
Along the right side of the screen.
Definition plasma.h:90
@ Floating
Free floating.
Definition plasma.h:82
@ FullScreen
Full screen.
Definition plasma.h:86
@ TopEdge
Along the top of the screen.
Definition plasma.h:87
@ Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
Definition plasma.h:84
@ LeftEdge
Along the left side of the screen.
Definition plasma.h:89
@ BottomEdge
Along the bottom of the screen.
Definition plasma.h:88
int timeout
Timeout in milliseconds after which the tooltip will hide itself.
Definition tooltip.h:118
QString subText
The description of this tooltip.
Definition tooltip.h:67
bool interactive
If interactive is false (default), the tooltip will automatically hide itself as soon as the mouse le...
Definition tooltip.h:112
void toolTipVisibleChanged(bool toolTipVisible)
Emitted when the tooltip's visibility changes.
void hideImmediately()
Hides the tooltip immediately, in comparison to hideToolTip.
Definition tooltip.cpp:294
QQuickItem * mainItem
The item shown inside the tooltip.
Definition tooltip.h:57
QVariant icon
An icon for this tooltip, accepted values are an icon name, a QIcon, QImage or QPixmap.
Definition tooltip.h:82
QString mainText
The main text of this tooltip.
Definition tooltip.h:62
bool containsMouse
Returns whether the mouse is inside the item.
Definition tooltip.h:87
void hideToolTip()
Hides the tooltip after a grace period if shown.
Definition tooltip.cpp:288
void aboutToShow()
Emitted just before the tooltip dialog is shown.
QVariant image
TODO: single property for images? An image for this tooltip, accepted values are an icon name,...
Definition tooltip.h:98
int textFormat
how to handle the text format of the tooltip subtext:
Definition tooltip.h:77
void showToolTip()
Shows the tooltip.
Definition tooltip.cpp:117
Plasma::Types::Location location
Plasma Location of the dialog window.
Definition tooltip.h:92
bool active
Property that controls if a tooltips will show on mouse over.
Definition tooltip.h:104
Namespace for everything in libplasma.
MouseButtonPress
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool setProperty(const char *name, QVariant &&value)
T * data() const const
virtual bool childMouseEventFilter(QQuickItem *item, QEvent *event)
virtual bool contains(const QPointF &point) const const
virtual bool event(QEvent *ev) override
virtual void hoverEnterEvent(QHoverEvent *event)
virtual void hoverLeaveEvent(QHoverEvent *event)
QQuickItem * parentItem() const const
void setVisible(bool)
QString writableLocation(StandardLocation type)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
UniqueConnection
BottomEdge
AutoText
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void start()
void stop()
void timeout()
QVariant fromValue(T &&value)
bool isValid() const const
void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 10 2024 11:48:21 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.