1 /*******************************************************************************
2 * Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
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. *
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. *
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 *******************************************************************************/
20 #include "tooltipmanager.h"
22 #include "dolphinfilemetadatawidget.h"
24 #include <KIO/JobUiDelegate>
25 #include <KIO/PreviewJob>
26 #include <KJobWidgets>
27 #include <KToolTipWidget>
28 #include <KIconLoader>
30 #include <QApplication>
31 #include <QDesktopWidget>
38 class IconLoaderSingleton
{
40 IconLoaderSingleton() = default;
45 Q_GLOBAL_STATIC(IconLoaderSingleton
, iconLoader
)
47 ToolTipManager::ToolTipManager(QWidget
* parent
) :
49 m_showToolTipTimer(nullptr),
50 m_contentRetrievalTimer(nullptr),
51 m_transientParent(nullptr),
52 m_fileMetaDataWidget(nullptr),
53 m_toolTipRequested(false),
54 m_metaDataRequested(false),
55 m_appliedWaitCursor(false),
61 m_margin
= qMax(m_margin
, parent
->style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth
));
64 m_showToolTipTimer
= new QTimer(this);
65 m_showToolTipTimer
->setSingleShot(true);
66 m_showToolTipTimer
->setInterval(500);
67 connect(m_showToolTipTimer
, &QTimer::timeout
, this, QOverload
<>::of(&ToolTipManager::showToolTip
));
69 m_contentRetrievalTimer
= new QTimer(this);
70 m_contentRetrievalTimer
->setSingleShot(true);
71 m_contentRetrievalTimer
->setInterval(200);
72 connect(m_contentRetrievalTimer
, &QTimer::timeout
, this, &ToolTipManager::startContentRetrieval
);
74 Q_ASSERT(m_contentRetrievalTimer
->interval() < m_showToolTipTimer
->interval());
77 ToolTipManager::~ToolTipManager()
81 void ToolTipManager::showToolTip(const KFileItem
& item
, const QRectF
& itemRect
, QWindow
*transientParent
)
85 m_itemRect
= itemRect
.toRect();
87 m_itemRect
.adjust(-m_margin
, -m_margin
, m_margin
, m_margin
);
90 m_transientParent
= transientParent
;
92 // Only start the retrieving of the content, when the mouse has been over this
93 // item for 200 milliseconds. This prevents a lot of useless preview jobs and
94 // meta data retrieval, when passing rapidly over a lot of items.
95 m_fileMetaDataWidget
.reset(new DolphinFileMetaDataWidget());
96 connect(m_fileMetaDataWidget
.data(), &DolphinFileMetaDataWidget::metaDataRequestFinished
,
97 this, &ToolTipManager::slotMetaDataRequestFinished
);
98 connect(m_fileMetaDataWidget
.data(), &DolphinFileMetaDataWidget::urlActivated
,
99 this, &ToolTipManager::urlActivated
);
101 m_contentRetrievalTimer
->start();
102 m_showToolTipTimer
->start();
103 m_toolTipRequested
= true;
104 Q_ASSERT(!m_metaDataRequested
);
107 void ToolTipManager::hideToolTip(const HideBehavior behavior
)
109 if (m_appliedWaitCursor
) {
110 QApplication::restoreOverrideCursor();
111 m_appliedWaitCursor
= false;
114 m_toolTipRequested
= false;
115 m_metaDataRequested
= false;
116 m_showToolTipTimer
->stop();
117 m_contentRetrievalTimer
->stop();
118 if (m_tooltipWidget
) {
120 case HideBehavior::Instantly
:
121 m_tooltipWidget
->hide();
123 case HideBehavior::Later
:
124 m_tooltipWidget
->hideLater();
130 void ToolTipManager::startContentRetrieval()
132 if (!m_toolTipRequested
) {
136 m_fileMetaDataWidget
->setName(m_item
.text());
138 // Request the retrieval of meta-data. The slot
139 // slotMetaDataRequestFinished() is invoked after the
140 // meta-data have been received.
141 m_metaDataRequested
= true;
142 m_fileMetaDataWidget
->setItems(KFileItemList() << m_item
);
143 m_fileMetaDataWidget
->adjustSize();
145 // Request a preview of the item
146 m_fileMetaDataWidget
->setPreview(QPixmap());
148 QStringList plugins
= KIO::PreviewJob::availablePlugins();
149 KIO::PreviewJob
* job
= new KIO::PreviewJob(KFileItemList() << m_item
,
152 job
->setIgnoreMaximumSize(m_item
.isLocalFile());
153 if (job
->uiDelegate()) {
154 KJobWidgets::setWindow(job
, qApp
->activeWindow());
157 connect(job
, &KIO::PreviewJob::gotPreview
,
158 this, &ToolTipManager::setPreviewPix
);
159 connect(job
, &KIO::PreviewJob::failed
,
160 this, &ToolTipManager::previewFailed
);
164 void ToolTipManager::setPreviewPix(const KFileItem
& item
,
165 const QPixmap
& pixmap
)
167 if (!m_toolTipRequested
|| (m_item
.url() != item
.url())) {
168 // No tooltip is requested anymore or an old preview has been received
172 if (pixmap
.isNull()) {
175 m_fileMetaDataWidget
->setPreview(pixmap
);
176 if (!m_showToolTipTimer
->isActive()) {
182 void ToolTipManager::previewFailed()
184 if (!m_toolTipRequested
) {
188 for (auto state
: { QPalette::Active
, QPalette::Inactive
, QPalette::Disabled
}) {
189 pal
.setBrush(state
, QPalette::WindowText
, pal
.toolTipText());
190 pal
.setBrush(state
, QPalette::Window
, pal
.toolTipBase());
192 iconLoader
->self
.setCustomPalette(pal
);
193 const QPixmap pixmap
= KDE::icon(m_item
.iconName(), &iconLoader
->self
).pixmap(128, 128);
194 m_fileMetaDataWidget
->setPreview(pixmap
);
195 if (!m_showToolTipTimer
->isActive()) {
200 void ToolTipManager::slotMetaDataRequestFinished()
202 if (!m_toolTipRequested
) {
206 m_metaDataRequested
= false;
208 if (!m_showToolTipTimer
->isActive()) {
213 void ToolTipManager::showToolTip()
215 Q_ASSERT(m_toolTipRequested
);
216 if (m_appliedWaitCursor
) {
217 QApplication::restoreOverrideCursor();
218 m_appliedWaitCursor
= false;
221 if (m_fileMetaDataWidget
->preview().isNull() || m_metaDataRequested
) {
222 Q_ASSERT(!m_appliedWaitCursor
);
223 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
224 m_appliedWaitCursor
= true;
228 // Adjust the size to get a proper sizeHint()
229 m_fileMetaDataWidget
->adjustSize();
230 if (!m_tooltipWidget
) {
231 m_tooltipWidget
.reset(new KToolTipWidget());
233 m_tooltipWidget
->showBelow(m_itemRect
, m_fileMetaDataWidget
.data(), m_transientParent
);
234 m_toolTipRequested
= false;