2 * SPDX-FileCopyrightText: 2008 Konstantin Heil <konst.heil@stud.uni-heidelberg.de>
4 * SPDX-License-Identifier: GPL-2.0-or-later
7 #include "tooltipmanager.h"
9 #include "dolphinfilemetadatawidget.h"
11 #include <KConfigGroup>
12 #include <KIO/PreviewJob>
13 #include <KIconLoader>
14 #include <KJobWidgets>
15 #include <KSharedConfig>
16 #include <KToolTipWidget>
18 #include <QApplication>
23 class IconLoaderSingleton
26 IconLoaderSingleton() = default;
31 Q_GLOBAL_STATIC(IconLoaderSingleton
, iconLoader
)
33 ToolTipManager::ToolTipManager(QWidget
*parent
)
35 , m_showToolTipTimer(nullptr)
36 , m_contentRetrievalTimer(nullptr)
37 , m_transientParent(nullptr)
38 , m_toolTipRequested(false)
39 , m_metaDataRequested(false)
40 , m_appliedWaitCursor(false)
46 m_margin
= qMax(m_margin
, parent
->style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth
));
49 m_showToolTipTimer
= new QTimer(this);
50 m_showToolTipTimer
->setSingleShot(true);
51 m_showToolTipTimer
->setInterval(500);
52 connect(m_showToolTipTimer
, &QTimer::timeout
, this, QOverload
<>::of(&ToolTipManager::showToolTip
));
54 m_contentRetrievalTimer
= new QTimer(this);
55 m_contentRetrievalTimer
->setSingleShot(true);
56 m_contentRetrievalTimer
->setInterval(200);
57 connect(m_contentRetrievalTimer
, &QTimer::timeout
, this, &ToolTipManager::startContentRetrieval
);
59 Q_ASSERT(m_contentRetrievalTimer
->interval() < m_showToolTipTimer
->interval());
62 ToolTipManager::~ToolTipManager()
64 if (!m_fileMetaDatWidgetOwnershipTransferred
) {
65 delete m_fileMetaDataWidget
;
69 void ToolTipManager::showToolTip(const KFileItem
&item
, const QRectF
&itemRect
, QWindow
*transientParent
)
71 hideToolTip(HideBehavior::Instantly
);
73 m_itemRect
= itemRect
.toRect();
75 m_itemRect
.adjust(-m_margin
, -m_margin
, m_margin
, m_margin
);
78 m_transientParent
= transientParent
;
80 // Only start the retrieving of the content, when the mouse has been over this
81 // item for 200 milliseconds. This prevents a lot of useless preview jobs and
82 // meta data retrieval, when passing rapidly over a lot of items.
83 if (!m_fileMetaDataWidget
) {
84 m_fileMetaDataWidget
= new DolphinFileMetaDataWidget();
85 connect(m_fileMetaDataWidget
, &DolphinFileMetaDataWidget::metaDataRequestFinished
, this, &ToolTipManager::slotMetaDataRequestFinished
);
86 connect(m_fileMetaDataWidget
, &DolphinFileMetaDataWidget::urlActivated
, this, &ToolTipManager::urlActivated
);
89 m_contentRetrievalTimer
->start();
90 m_showToolTipTimer
->start();
91 m_toolTipRequested
= true;
92 Q_ASSERT(!m_metaDataRequested
);
95 void ToolTipManager::hideToolTip(const HideBehavior behavior
)
97 if (m_appliedWaitCursor
) {
98 QApplication::restoreOverrideCursor();
99 m_appliedWaitCursor
= false;
102 m_toolTipRequested
= false;
103 m_metaDataRequested
= false;
104 m_showToolTipTimer
->stop();
105 m_contentRetrievalTimer
->stop();
106 if (m_tooltipWidget
) {
108 case HideBehavior::Instantly
:
109 m_tooltipWidget
->hide();
111 case HideBehavior::Later
:
112 m_tooltipWidget
->hideLater();
118 void ToolTipManager::startContentRetrieval()
120 if (!m_toolTipRequested
) {
124 m_fileMetaDataWidget
->setName(m_item
.text());
126 // Request the retrieval of meta-data. The slot
127 // slotMetaDataRequestFinished() is invoked after the
128 // meta-data have been received.
129 m_metaDataRequested
= true;
130 m_fileMetaDataWidget
->setItems(KFileItemList() << m_item
);
131 m_fileMetaDataWidget
->adjustSize();
133 // Request a preview of the item
134 m_fileMetaDataWidget
->setPreview(QPixmap());
136 const KConfigGroup
globalConfig(KSharedConfig::openConfig(), QLatin1String("PreviewSettings"));
137 const QStringList plugins
= globalConfig
.readEntry("Plugins", KIO::PreviewJob::defaultPlugins());
138 KIO::PreviewJob
*job
= new KIO::PreviewJob(KFileItemList() << m_item
, QSize(512, 512), &plugins
);
139 job
->setDevicePixelRatio(m_fileMetaDataWidget
->devicePixelRatioF());
140 job
->setIgnoreMaximumSize(m_item
.isLocalFile() && !m_item
.isSlow());
141 if (job
->uiDelegate()) {
142 KJobWidgets::setWindow(job
, qApp
->activeWindow());
145 connect(job
, &KIO::PreviewJob::gotPreview
, this, &ToolTipManager::setPreviewPix
);
146 connect(job
, &KIO::PreviewJob::failed
, this, &ToolTipManager::previewFailed
);
149 void ToolTipManager::setPreviewPix(const KFileItem
&item
, const QPixmap
&pixmap
)
151 if (!m_toolTipRequested
|| (m_item
.url() != item
.url())) {
152 // No tooltip is requested anymore or an old preview has been received
156 if (pixmap
.isNull()) {
159 m_fileMetaDataWidget
->setPreview(pixmap
);
160 if (!m_showToolTipTimer
->isActive()) {
166 void ToolTipManager::previewFailed()
168 if (!m_toolTipRequested
) {
172 for (auto state
: {QPalette::Active
, QPalette::Inactive
, QPalette::Disabled
}) {
173 pal
.setBrush(state
, QPalette::WindowText
, pal
.toolTipText());
174 pal
.setBrush(state
, QPalette::Window
, pal
.toolTipBase());
176 iconLoader
->self
.setCustomPalette(pal
);
177 const QPixmap pixmap
= KDE::icon(m_item
.iconName(), &iconLoader
->self
).pixmap(128, 128);
178 m_fileMetaDataWidget
->setPreview(pixmap
);
179 if (!m_showToolTipTimer
->isActive()) {
184 void ToolTipManager::slotMetaDataRequestFinished()
186 if (!m_toolTipRequested
) {
190 m_metaDataRequested
= false;
192 if (!m_showToolTipTimer
->isActive()) {
197 void ToolTipManager::showToolTip()
199 Q_ASSERT(m_toolTipRequested
);
200 if (m_appliedWaitCursor
) {
201 QApplication::restoreOverrideCursor();
202 m_appliedWaitCursor
= false;
205 if (m_fileMetaDataWidget
->preview().isNull() || m_metaDataRequested
) {
206 Q_ASSERT(!m_appliedWaitCursor
);
207 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
208 m_appliedWaitCursor
= true;
212 // Adjust the size to get a proper sizeHint()
213 m_fileMetaDataWidget
->adjustSize();
214 if (!m_tooltipWidget
) {
215 m_tooltipWidget
.reset(new KToolTipWidget());
217 m_tooltipWidget
->showBelow(m_itemRect
, m_fileMetaDataWidget
, m_transientParent
);
218 // At this point KToolTipWidget adopted our parent-less metadata widget.
219 m_fileMetaDatWidgetOwnershipTransferred
= true;
221 m_toolTipRequested
= false;
224 #include "moc_tooltipmanager.cpp"