Guest User

Tuned tooltipmanager.cpp

a guest
Sep 10th, 2015
233
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Linking to https://www.kubuntuforums.net/showthread.php?63185-Auto-preview-audio-and-video-files-in-the-Dolphin-and-Konqueror
  2.  
  3.  
  4. /*******************************************************************************
  5. * Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
  6. * *
  7. * This program is free software; you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation; either version 2 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with this program; if not, write to the *
  19. * Free Software Foundation, Inc., *
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
  21. *******************************************************************************/
  22.  
  23. #include "tooltipmanager.h"
  24.  
  25. #include "filemetadatatooltip.h"
  26. #include <QIcon>
  27. #include <KIO/JobUiDelegate>
  28. #include <KIO/PreviewJob>
  29. #include <KJobWidgets>
  30.  
  31. #include <QApplication>
  32. #include <QDesktopWidget>
  33. #include <QLayout>
  34. #include <QStyle>
  35. #include <QTimer>
  36.  
  37. #include <QProcess>
  38.  
  39. ToolTipManager::ToolTipManager(QWidget* parent) :
  40. QObject(parent),
  41. m_showToolTipTimer(0),
  42. m_contentRetrievalTimer(0),
  43. m_fileMetaDataToolTip(0),
  44. m_toolTipRequested(false),
  45. m_metaDataRequested(false),
  46. m_appliedWaitCursor(false),
  47. m_margin(4),
  48. m_item(),
  49. m_itemRect()
  50. {
  51. if (parent) {
  52. m_margin = qMax(m_margin, parent->style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth));
  53. }
  54.  
  55. m_showToolTipTimer = new QTimer(this);
  56. m_showToolTipTimer->setSingleShot(true);
  57. m_showToolTipTimer->setInterval(500);
  58. connect(m_showToolTipTimer, &QTimer::timeout, this, static_cast<void(ToolTipManager::*)()>(&ToolTipManager::showToolTip));
  59.  
  60. m_contentRetrievalTimer = new QTimer(this);
  61. m_contentRetrievalTimer->setSingleShot(true);
  62. m_contentRetrievalTimer->setInterval(200);
  63. connect(m_contentRetrievalTimer, &QTimer::timeout, this, &ToolTipManager::startContentRetrieval);
  64.  
  65. Q_ASSERT(m_contentRetrievalTimer->interval() < m_showToolTipTimer->interval());
  66. }
  67.  
  68. ToolTipManager::~ToolTipManager()
  69. {
  70. delete m_fileMetaDataToolTip;
  71. m_fileMetaDataToolTip = 0;
  72. }
  73.  
  74. void ToolTipManager::showToolTip(const KFileItem& item, const QRectF& itemRect)
  75. {
  76. hideToolTip();
  77.  
  78. m_itemRect = itemRect.toRect();
  79.  
  80. m_itemRect.adjust(-m_margin, -m_margin, m_margin, m_margin);
  81. m_item = item;
  82.  
  83. // Only start the retrieving of the content, when the mouse has been over this
  84. // item for 200 milliseconds. This prevents a lot of useless preview jobs and
  85. // meta data retrieval, when passing rapidly over a lot of items.
  86. Q_ASSERT(!m_fileMetaDataToolTip);
  87. m_fileMetaDataToolTip = new FileMetaDataToolTip();
  88. connect(m_fileMetaDataToolTip, &FileMetaDataToolTip::metaDataRequestFinished,
  89. this, &ToolTipManager::slotMetaDataRequestFinished);
  90.  
  91. m_contentRetrievalTimer->start();
  92. m_showToolTipTimer->start();
  93. m_toolTipRequested = true;
  94. Q_ASSERT(!m_metaDataRequested);
  95. }
  96.  
  97. void ToolTipManager::hideToolTip()
  98. {
  99. if (m_appliedWaitCursor) {
  100. QApplication::restoreOverrideCursor();
  101. m_appliedWaitCursor = false;
  102. }
  103.  
  104. m_toolTipRequested = false;
  105. m_metaDataRequested = false;
  106. m_showToolTipTimer->stop();
  107. m_contentRetrievalTimer->stop();
  108.  
  109. if (m_fileMetaDataToolTip) {
  110. m_fileMetaDataToolTip->hide();
  111. // Do not delete the tool tip immediately to prevent crashes when
  112. // QCoreApplication tries to deliver an 'Enter' event to it, see bug 310579.
  113. m_fileMetaDataToolTip->deleteLater();
  114. m_fileMetaDataToolTip = 0;
  115.  
  116. // Kill mouse over action
  117. QObject *parent;
  118. QString program = "/usr/bin/pkill";
  119. QStringList arguments;
  120. arguments << "-f" << "/usr/local/bin/MouseOverAction.sh";
  121. QProcess *killAction = new QProcess(parent);
  122. killAction->start(program, arguments);
  123. }
  124. }
  125.  
  126. void ToolTipManager::startContentRetrieval()
  127. {
  128. if (!m_toolTipRequested) {
  129. return;
  130. }
  131.  
  132. m_fileMetaDataToolTip->setName(m_item.text());
  133.  
  134. // Request the retrieval of meta-data. The slot
  135. // slotMetaDataRequestFinished() is invoked after the
  136. // meta-data have been received.
  137. m_metaDataRequested = true;
  138. m_fileMetaDataToolTip->setItems(KFileItemList() << m_item);
  139. m_fileMetaDataToolTip->adjustSize();
  140.  
  141. // Request a preview of the item
  142. m_fileMetaDataToolTip->setPreview(QPixmap());
  143.  
  144. KIO::PreviewJob* job = new KIO::PreviewJob(KFileItemList() << m_item, QSize(256, 256));
  145. job->setIgnoreMaximumSize(m_item.isLocalFile());
  146. if (job->ui()) {
  147. KJobWidgets::setWindow(job, qApp->activeWindow());
  148. }
  149.  
  150. connect(job, &KIO::PreviewJob::gotPreview,
  151. this, &ToolTipManager::setPreviewPix);
  152. connect(job, &KIO::PreviewJob::failed,
  153. this, &ToolTipManager::previewFailed);
  154. }
  155.  
  156.  
  157. void ToolTipManager::setPreviewPix(const KFileItem& item,
  158. const QPixmap& pixmap)
  159. {
  160. if (!m_toolTipRequested || (m_item.url() != item.url())) {
  161. // No tooltip is requested anymore or an old preview has been received
  162. return;
  163. }
  164.  
  165. if (pixmap.isNull()) {
  166. previewFailed();
  167. } else {
  168. m_fileMetaDataToolTip->setPreview(pixmap);
  169. if (!m_showToolTipTimer->isActive()) {
  170. showToolTip();
  171. }
  172. }
  173. }
  174.  
  175. void ToolTipManager::previewFailed()
  176. {
  177. if (!m_toolTipRequested) {
  178. return;
  179. }
  180.  
  181. const QPixmap pixmap = QIcon::fromTheme(m_item.iconName()).pixmap(128, 128);
  182. m_fileMetaDataToolTip->setPreview(pixmap);
  183. if (!m_showToolTipTimer->isActive()) {
  184. showToolTip();
  185. }
  186. }
  187.  
  188. void ToolTipManager::slotMetaDataRequestFinished()
  189. {
  190. if (!m_toolTipRequested) {
  191. return;
  192. }
  193.  
  194. m_metaDataRequested = false;
  195.  
  196. if (!m_showToolTipTimer->isActive()) {
  197. showToolTip();
  198. }
  199. }
  200.  
  201. void ToolTipManager::showToolTip()
  202. {
  203. Q_ASSERT(m_toolTipRequested);
  204. if (m_appliedWaitCursor) {
  205. QApplication::restoreOverrideCursor();
  206. m_appliedWaitCursor = false;
  207. }
  208.  
  209. if (m_fileMetaDataToolTip->preview().isNull() || m_metaDataRequested) {
  210. Q_ASSERT(!m_appliedWaitCursor);
  211. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
  212. m_appliedWaitCursor = true;
  213. return;
  214. }
  215.  
  216. const QRect screen = QApplication::desktop()->screenGeometry(QCursor::pos());
  217.  
  218. // Restrict tooltip size to current screen size when needed.
  219. // Because layout controlling widget doesn't respect widget's maximumSize property
  220. // (correct me if I'm wrong), we need to let layout do its work, then manually change
  221. // geometry if resulting widget doesn't fit the screen.
  222.  
  223. // Step #1 - make sizeHint return calculated tooltip size
  224. m_fileMetaDataToolTip->layout()->setSizeConstraint(QLayout::SetFixedSize);
  225. m_fileMetaDataToolTip->adjustSize();
  226. QSize size = m_fileMetaDataToolTip->sizeHint();
  227.  
  228. // Step #2 - correct tooltip size when needed
  229. if (size.width() > screen.width()) {
  230. size.setWidth(screen.width());
  231. }
  232. if (size.height() > screen.height()) {
  233. size.setHeight(screen.height());
  234. }
  235.  
  236. // m_itemRect defines the area of the item, where the tooltip should be
  237. // shown. Per default the tooltip is shown centered at the bottom.
  238. // It must be assured that:
  239. // - the content is fully visible
  240. // - the content is not drawn inside m_itemRect
  241. const bool hasRoomToLeft = (m_itemRect.left() - size.width() - m_margin >= screen.left());
  242. const bool hasRoomToRight = (m_itemRect.right() + size.width() + m_margin <= screen.right());
  243. const bool hasRoomAbove = (m_itemRect.top() - size.height() - m_margin >= screen.top());
  244. const bool hasRoomBelow = (m_itemRect.bottom() + size.height() + m_margin <= screen.bottom());
  245. if (!hasRoomAbove && !hasRoomBelow && !hasRoomToLeft && !hasRoomToRight) {
  246. return;
  247. }
  248.  
  249. int x, y;
  250. if (hasRoomBelow || hasRoomAbove) {
  251. x = qMax(screen.left(), m_itemRect.center().x() - size.width() / 2);
  252. if (x + size.width() >= screen.right()) {
  253. x = screen.right() - size.width() + 1;
  254. }
  255. if (hasRoomBelow) {
  256. y = m_itemRect.bottom() + m_margin;
  257. } else {
  258. y = m_itemRect.top() - size.height() - m_margin;
  259. }
  260. } else {
  261. Q_ASSERT(hasRoomToLeft || hasRoomToRight);
  262. if (hasRoomToRight) {
  263. x = m_itemRect.right() + m_margin;
  264. } else {
  265. x = m_itemRect.left() - size.width() - m_margin;
  266. }
  267. // Put the tooltip at the bottom of the screen. The x-coordinate has already
  268. // been adjusted, so that no overlapping with m_itemRect occurs.
  269. y = screen.bottom() - size.height() + 1;
  270. }
  271.  
  272. // Step #3 - Alter tooltip geometry
  273. m_fileMetaDataToolTip->setFixedSize(size);
  274. m_fileMetaDataToolTip->layout()->setSizeConstraint(QLayout::SetNoConstraint);
  275. m_fileMetaDataToolTip->move(QPoint(x, y));
  276. m_fileMetaDataToolTip->show();
  277.  
  278. m_toolTipRequested = false;
  279.  
  280. // Start mouse over action
  281. // http://api.kde.org/frameworks-api/frameworks5-apidocs/kio/html/index.html ?
  282. // mimetype() and localPath()
  283. QObject *parent;
  284. QString program = "/usr/local/bin/MouseOverAction.sh";
  285. QStringList arguments;
  286. arguments << m_item.mimetype() << m_item.localPath();
  287. QProcess *startAction = new QProcess(parent);
  288. startAction->start(program, arguments);
  289. }
RAW Paste Data