Plasma

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

KDE's Doxygen guidelines are available online.