┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/tooltips
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2009-01-14 19:26:23 +0000
committerPeter Penz <[email protected]>2009-01-14 19:26:23 +0000
commit307285e9635a4bf584d6e5d7478876b90ef870f0 (patch)
treedb36cbbdc7996ab86c38be8f96fe83597d350dfb /src/tooltips
parent86d9c40ab71df5b8bd5063251337d5ca0c22380a (diff)
Group classes into folders, Dolphin is too big in the meantime for having a flat directory hierarchy. dolphin/src/CMakeLists.txt will be cleaned up later.
svn path=/trunk/KDE/kdebase/apps/; revision=911065
Diffstat (limited to 'src/tooltips')
-rw-r--r--src/tooltips/dolphintooltip.cpp50
-rw-r--r--src/tooltips/dolphintooltip.h47
-rw-r--r--src/tooltips/kformattedballoontipdelegate.cpp129
-rw-r--r--src/tooltips/kformattedballoontipdelegate.h45
-rw-r--r--src/tooltips/ktooltip.cpp558
-rw-r--r--src/tooltips/ktooltip.h198
-rw-r--r--src/tooltips/ktooltip_p.h67
-rw-r--r--src/tooltips/tooltipmanager.cpp307
-rw-r--r--src/tooltips/tooltipmanager.h91
9 files changed, 1492 insertions, 0 deletions
diff --git a/src/tooltips/dolphintooltip.cpp b/src/tooltips/dolphintooltip.cpp
new file mode 100644
index 000000000..bc3be33aa
--- /dev/null
+++ b/src/tooltips/dolphintooltip.cpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Simon St James <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "dolphintooltip.h"
+
+#include <kicon.h>
+#include <kio/previewjob.h>
+#include <kfileitem.h>
+
+#include <QtGui/QPixmap>
+
+DolphinBalloonTooltipDelegate::DolphinBalloonTooltipDelegate()
+{
+}
+
+DolphinBalloonTooltipDelegate::~DolphinBalloonTooltipDelegate()
+{
+}
+
+// Delegate everything to the base class, after re-setting the decorationSize
+// to the preview size.
+QSize DolphinBalloonTooltipDelegate::sizeHint(const KStyleOptionToolTip* option, const KToolTipItem* item) const
+{
+ KStyleOptionToolTip updatedStyleOption = *option;
+ updatedStyleOption.decorationSize = QSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ return KFormattedBalloonTipDelegate::sizeHint(&updatedStyleOption, item);
+}
+
+void DolphinBalloonTooltipDelegate::paint(QPainter* painter, const KStyleOptionToolTip* option, const KToolTipItem* item) const
+{
+ KStyleOptionToolTip updatedStyleOption = *option;
+ updatedStyleOption.decorationSize = QSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ return KFormattedBalloonTipDelegate::paint(painter, &updatedStyleOption, item);
+}
diff --git a/src/tooltips/dolphintooltip.h b/src/tooltips/dolphintooltip.h
new file mode 100644
index 000000000..5c0682171
--- /dev/null
+++ b/src/tooltips/dolphintooltip.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Simon St James <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+// NOTE: proper documentation will be added once the code is better developed.
+
+#ifndef DOLPHINTOOLTIP_H
+#define DOLPHINTOOLTIP_H
+
+#include <tooltips/ktooltip.h>
+#include <tooltips/kformattedballoontipdelegate.h>
+
+#include <kio/previewjob.h>
+#include <QtCore/QObject>
+
+class KFileItem;
+class QPixmap;
+
+const int PREVIEW_WIDTH = 256;
+const int PREVIEW_HEIGHT = 256;
+
+
+class DolphinBalloonTooltipDelegate : public KFormattedBalloonTipDelegate
+{
+public:
+ DolphinBalloonTooltipDelegate();
+ virtual ~DolphinBalloonTooltipDelegate();
+
+ virtual QSize sizeHint(const KStyleOptionToolTip* option, const KToolTipItem* item) const;
+ virtual void paint(QPainter* painter, const KStyleOptionToolTip* option, const KToolTipItem* item) const;
+};
+#endif
diff --git a/src/tooltips/kformattedballoontipdelegate.cpp b/src/tooltips/kformattedballoontipdelegate.cpp
new file mode 100644
index 000000000..140c90ef4
--- /dev/null
+++ b/src/tooltips/kformattedballoontipdelegate.cpp
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (C) 2008 by Fredrik Höglund <[email protected]> *
+ * Copyright (C) 2008 by Konstantin Heil <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ *******************************************************************************/
+
+#include "kformattedballoontipdelegate.h"
+#include <QBitmap>
+#include <QLinearGradient>
+#include <QTextDocument>
+#include <kcolorscheme.h>
+
+KFormattedBalloonTipDelegate::KFormattedBalloonTipDelegate()
+{
+}
+
+KFormattedBalloonTipDelegate::~KFormattedBalloonTipDelegate()
+{
+}
+
+QSize KFormattedBalloonTipDelegate::sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const
+{
+ QTextDocument doc;
+ doc.setHtml(item->text());
+ const QIcon icon = item->icon();
+
+ const QSize iconSize = icon.isNull() ? QSize(0, 0) : icon.actualSize(option->decorationSize);
+ const QSize docSize = doc.size().toSize();
+ QSize contentSize = iconSize + docSize;
+
+ // assure that the content height is large enough for the icon and the document
+ contentSize.setHeight(iconSize.height() > doc.size().height() ? iconSize.height() : doc.size().height());
+ return contentSize + QSize(Border * 3, Border * 2);
+}
+
+void KFormattedBalloonTipDelegate::paint(QPainter *painter,
+ const KStyleOptionToolTip *option,
+ const KToolTipItem *item) const
+{
+ QPainterPath path = createPath(*option);
+ if (haveAlphaChannel()) {
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->translate(.5, .5);
+ }
+
+ const QColor toColor = option->palette.brush(QPalette::ToolTipBase).color();
+ const QColor fromColor = KColorScheme::shade(toColor, KColorScheme::LightShade, 0.2);
+
+ QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft());
+ gradient.setColorAt(0.0, fromColor);
+ gradient.setColorAt(1.0, toColor);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(gradient);
+
+ painter->drawPath(path);
+
+ const QIcon icon = item->icon();
+ int x = Border;
+ const int y = Border;
+ if (!icon.isNull()) {
+ const QSize iconSize = icon.actualSize(option->decorationSize);
+ const QPoint pos(x + option->rect.x(), y + option->rect.y());
+ painter->drawPixmap(pos, icon.pixmap(iconSize));
+ x += iconSize.width() + Border;
+ }
+
+ QTextDocument doc;
+ doc.setHtml(item->text());
+ QPixmap bitmap(doc.size().toSize());
+ bitmap.fill(Qt::transparent);
+ QPainter p(&bitmap);
+ doc.drawContents(&p);
+
+ const QRect docRect(QPoint(x, y), doc.size().toSize());
+ painter->drawPixmap(docRect, bitmap);
+}
+
+QRegion KFormattedBalloonTipDelegate::inputShape(const KStyleOptionToolTip *option) const
+{
+ QBitmap bitmap(option->rect.size());
+ bitmap.fill(Qt::color0);
+
+ QPainter p(&bitmap);
+ p.setPen(QPen(Qt::color1, 1));
+ p.setBrush(Qt::color1);
+ p.drawPath(createPath(*option));
+
+ return QRegion(bitmap);
+}
+
+QRegion KFormattedBalloonTipDelegate::shapeMask(const KStyleOptionToolTip *option) const
+{
+ return inputShape(option);
+}
+
+static inline void arc(QPainterPath &path, qreal cx, qreal cy, qreal radius, qreal angle, qreal sweeplength)
+{
+ path.arcTo(cx-radius, cy-radius, radius * 2, radius * 2, angle, sweeplength);
+}
+
+QPainterPath KFormattedBalloonTipDelegate::createPath(const KStyleOptionToolTip& option) const
+{
+ const QRect rect = option.rect;
+ const qreal radius = 5;
+
+ QPainterPath path;
+ path.moveTo(rect.left(), rect.top() + radius);
+ arc(path, rect.left() + radius, rect.top() + radius, radius, 180, -90);
+ arc(path, rect.right() - radius, rect.top() + radius, radius, 90, -90);
+ arc(path, rect.right() - radius, rect.bottom() - radius, radius, 0, -90);
+ arc(path, rect.left() + radius, rect.bottom() - radius, radius, 270, -90);
+ path.closeSubpath();
+
+ return path;
+}
diff --git a/src/tooltips/kformattedballoontipdelegate.h b/src/tooltips/kformattedballoontipdelegate.h
new file mode 100644
index 000000000..117d6eec7
--- /dev/null
+++ b/src/tooltips/kformattedballoontipdelegate.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2008 by Fredrik Höglund <[email protected]> *
+ * Copyright (C) 2008 by Konstantin Heil <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ *******************************************************************************/
+
+#ifndef KFORMATTEDBALLOONTIPDELEGATE_H
+#define KFORMATTEDBALLOONTIPDELEGATE_H
+
+#include <tooltips/ktooltip.h>
+#include <QPainter>
+
+class KFormattedBalloonTipDelegate : public KToolTipDelegate
+{
+public:
+ KFormattedBalloonTipDelegate();
+ virtual ~KFormattedBalloonTipDelegate();
+
+ virtual QSize sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+ virtual void paint(QPainter *painter, const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+ virtual QRegion inputShape(const KStyleOptionToolTip *option) const;
+ virtual QRegion shapeMask(const KStyleOptionToolTip *option) const;
+
+private:
+ QPainterPath createPath(const KStyleOptionToolTip& option) const;
+
+private:
+ enum { Border = 8 };
+};
+
+#endif
diff --git a/src/tooltips/ktooltip.cpp b/src/tooltips/ktooltip.cpp
new file mode 100644
index 000000000..a0126fbff
--- /dev/null
+++ b/src/tooltips/ktooltip.cpp
@@ -0,0 +1,558 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Fredrik Höglund <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "ktooltip.h"
+
+#include <QApplication>
+#include <QMap>
+#include <QPixmap>
+#include <QPainter>
+#include <QVariant>
+#include <QIcon>
+#include <QWidget>
+#include <QToolTip>
+#include <QDebug>
+
+#ifdef Q_WS_X11
+# include <QX11Info>
+# include <X11/Xlib.h>
+# include <X11/extensions/Xrender.h>
+# include <X11/extensions/shape.h>
+#endif
+
+#include "ktooltip_p.h"
+
+
+// compile with XShape older than 1.0
+#ifndef ShapeInput
+const int ShapeInput = 2;
+#endif
+
+
+class KToolTipItemPrivate
+{
+public:
+ QMap<int, QVariant> map;
+ int type;
+};
+
+KToolTipItem::KToolTipItem(const QString &text, int type)
+ : d(new KToolTipItemPrivate)
+{
+ d->map[Qt::DisplayRole] = text;
+ d->type = type;
+}
+
+KToolTipItem::KToolTipItem(const QIcon &icon, const QString &text, int type)
+ : d(new KToolTipItemPrivate)
+{
+ d->map[Qt::DecorationRole] = icon;
+ d->map[Qt::DisplayRole] = text;
+ d->type = type;
+}
+
+KToolTipItem::~KToolTipItem()
+{
+ delete d;
+}
+
+int KToolTipItem::type() const
+{
+ return d->type;
+}
+
+QString KToolTipItem::text() const
+{
+ return data(Qt::DisplayRole).toString();
+}
+
+QIcon KToolTipItem::icon() const
+{
+ return qvariant_cast<QIcon>(data(Qt::DecorationRole));
+}
+
+QVariant KToolTipItem::data(int role) const
+{
+ return d->map.value(role);
+}
+
+void KToolTipItem::setData(int role, const QVariant &data)
+{
+ d->map[role] = data;
+ KToolTipManager::instance()->update();
+}
+
+
+
+// ----------------------------------------------------------------------------
+
+
+KStyleOptionToolTip::KStyleOptionToolTip()
+ : fontMetrics(QApplication::font())
+{
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+
+KToolTipDelegate::KToolTipDelegate() : QObject()
+{
+}
+
+KToolTipDelegate::~KToolTipDelegate()
+{
+}
+
+QSize KToolTipDelegate::sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const
+{
+ QSize size;
+ size.rwidth() = option->fontMetrics.width(item->text());
+ size.rheight() = option->fontMetrics.lineSpacing();
+
+ QIcon icon = item->icon();
+ if (!icon.isNull()) {
+ const QSize iconSize = icon.actualSize(option->decorationSize);
+ size.rwidth() += iconSize.width() + 4;
+ size.rheight() = qMax(size.height(), iconSize.height());
+ }
+
+ return size + QSize(20, 20);
+
+}
+
+void KToolTipDelegate::paint(QPainter *painter, const KStyleOptionToolTip *option,
+ const KToolTipItem *item) const
+{
+ bool haveAlpha = haveAlphaChannel();
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ QPainterPath path;
+ if (haveAlpha)
+ path.addRoundRect(option->rect.adjusted(0, 0, -1, -1), 25);
+ else
+ path.addRect(option->rect.adjusted(0, 0, -1, -1));
+
+ QColor color = option->palette.color(QPalette::ToolTipBase);
+ QColor from = color.lighter(105);
+ QColor to = color.darker(120);
+
+ QLinearGradient gradient(0, 0, 0, 1);
+ gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ gradient.setColorAt(0, from);
+ gradient.setColorAt(1, to);
+
+ painter->translate(.5, .5);
+ painter->setPen(QPen(Qt::black, 1));
+ painter->setBrush(gradient);
+ painter->drawPath(path);
+ painter->translate(-.5, -.5);
+
+ if (haveAlpha) {
+ QLinearGradient mask(0, 0, 0, 1);
+ gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ gradient.setColorAt(0, QColor(0, 0, 0, 192));
+ gradient.setColorAt(1, QColor(0, 0, 0, 72));
+ painter->setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ painter->fillRect(option->rect, gradient);
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ }
+
+ QRect textRect = option->rect.adjusted(10, 10, -10, -10);
+
+ QIcon icon = item->icon();
+ if (!icon.isNull()) {
+ const QSize iconSize = icon.actualSize(option->decorationSize);
+ painter->drawPixmap(textRect.topLeft(), icon.pixmap(iconSize));
+ textRect.adjust(iconSize.width() + 4, 0, 0, 0);
+ }
+ painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, item->text());
+}
+
+QRegion KToolTipDelegate::inputShape(const KStyleOptionToolTip *option) const
+{
+ return QRegion(option->rect);
+}
+
+QRegion KToolTipDelegate::shapeMask(const KStyleOptionToolTip *option) const
+{
+ return QRegion(option->rect);
+}
+
+bool KToolTipDelegate::haveAlphaChannel() const
+{
+ return KToolTipManager::instance()->haveAlphaChannel();
+}
+
+
+
+// ----------------------------------------------------------------------------
+
+
+
+class KAbstractToolTipLabel
+{
+public:
+ KAbstractToolTipLabel() {}
+ virtual ~KAbstractToolTipLabel() {}
+
+ virtual void showTip(const QPoint &pos, const KToolTipItem *item) = 0;
+ virtual void moveTip(const QPoint &pos) = 0;
+ virtual void hideTip() = 0;
+
+protected:
+ KStyleOptionToolTip styleOption() const;
+ KToolTipDelegate *delegate() const;
+};
+
+KStyleOptionToolTip KAbstractToolTipLabel::styleOption() const
+{
+ KStyleOptionToolTip option;
+ KToolTipManager::instance()->initStyleOption(&option);
+ return option;
+}
+
+KToolTipDelegate *KAbstractToolTipLabel::delegate() const
+{
+ return KToolTipManager::instance()->delegate();
+}
+
+
+// ----------------------------------------------------------------------------
+
+
+
+class QWidgetLabel : public QWidget, public KAbstractToolTipLabel
+{
+public:
+ QWidgetLabel() : QWidget(0, Qt::ToolTip) {}
+ void showTip(const QPoint &pos, const KToolTipItem *item);
+ void moveTip(const QPoint &pos);
+ void hideTip();
+
+private:
+ void paintEvent(QPaintEvent*);
+ QSize sizeHint() const;
+
+private:
+ const KToolTipItem *currentItem;
+};
+
+void QWidgetLabel::showTip(const QPoint &pos, const KToolTipItem *item)
+{
+ currentItem = item;
+ move(pos);
+ show();
+}
+
+void QWidgetLabel::hideTip()
+{
+ hide();
+ currentItem = 0;
+}
+
+void QWidgetLabel::moveTip(const QPoint &pos)
+{
+ move(pos);
+}
+
+void QWidgetLabel::paintEvent(QPaintEvent*)
+{
+ KStyleOptionToolTip option = styleOption();
+ option.rect = rect();
+
+ setMask(delegate()->shapeMask(&option));
+
+ QPainter p(this);
+ p.setFont(option.font);
+ p.setPen(QPen(option.palette.brush(QPalette::Text), 0));
+ delegate()->paint(&p, &option, currentItem);
+}
+
+QSize QWidgetLabel::sizeHint() const
+{
+ if (!currentItem)
+ return QSize();
+
+ KStyleOptionToolTip option = styleOption();
+ return delegate()->sizeHint(&option, currentItem);
+}
+
+
+
+// ----------------------------------------------------------------------------
+
+
+
+#ifdef Q_WS_X11
+
+// X11 specific label that displays the tip in an ARGB window.
+class ArgbLabel : public KAbstractToolTipLabel
+{
+public:
+ ArgbLabel(Visual *visual, int depth);
+ ~ArgbLabel();
+
+ void showTip(const QPoint &pos, const KToolTipItem *item);
+ void moveTip(const QPoint &pos);
+ void hideTip();
+
+private:
+ Window window;
+ Colormap colormap;
+ Picture picture;
+ bool mapped;
+};
+
+ArgbLabel::ArgbLabel(Visual *visual, int depth)
+{
+ Display *dpy = QX11Info::display();
+ Window root = QX11Info::appRootWindow();
+ colormap = XCreateColormap(dpy, QX11Info::appRootWindow(), visual, AllocNone);
+
+ XSetWindowAttributes attr;
+ attr.border_pixel = 0;
+ attr.background_pixel = 0;
+ attr.colormap = colormap;
+ attr.override_redirect = True;
+
+ window = XCreateWindow(dpy, root, 0, 0, 1, 1, 0, depth, InputOutput, visual,
+ CWBorderPixel | CWBackPixel | CWColormap |
+ CWOverrideRedirect, &attr);
+
+ // ### TODO: Set the WM hints so KWin can identify this window as a
+ // tooltip.
+
+ XRenderPictFormat *format = XRenderFindVisualFormat(dpy, visual);
+ picture = XRenderCreatePicture(dpy, window, format, 0, 0);
+
+ mapped = false;
+}
+
+ArgbLabel::~ArgbLabel()
+{
+ Display *dpy = QX11Info::display();
+ XRenderFreePicture(dpy, picture);
+ XDestroyWindow(dpy, window);
+ XFreeColormap(dpy, colormap);
+}
+
+void ArgbLabel::showTip(const QPoint &pos, const KToolTipItem *item)
+{
+ Display *dpy = QX11Info::display();
+ KStyleOptionToolTip option = styleOption();
+ const QSize size = delegate()->sizeHint(&option, item);
+ option.rect = QRect(QPoint(), size);
+
+ QPixmap pixmap(size);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setFont(option.font);
+ p.setPen(QPen(option.palette.brush(QPalette::Text), 0));
+ delegate()->paint(&p, &option, item);
+
+ // Resize, position and show the window.
+ XMoveResizeWindow(dpy, window, pos.x(), pos.y(), size.width(), size.height());
+
+ if (KToolTipManager::instance()->haveAlphaChannel()) {
+ const QRegion region = delegate()->inputShape(&option);
+ XShapeCombineRegion(dpy, window, ShapeInput, 0, 0, region.handle(), ShapeSet);
+ } else {
+ const QRegion region = delegate()->shapeMask(&option);
+ XShapeCombineRegion(dpy, window, ShapeBounding, 0, 0, region.handle(), ShapeSet);
+ }
+
+ XMapWindow(dpy, window);
+
+ // Blit the pixmap with the tip contents to the window.
+ // Since the window is override-redirect and an ARGB32 window,
+ // which always has an offscreen pixmap, there's no need to
+ // wait for an Expose event, or to process those.
+ XRenderComposite(dpy, PictOpSrc, pixmap.x11PictureHandle(), None,
+ picture, 0, 0, 0, 0, 0, 0, size.width(), size.height());
+
+ mapped = true;
+}
+
+void ArgbLabel::moveTip(const QPoint &pos)
+{
+ if (mapped)
+ XMoveWindow(QX11Info::display(), window, pos.x(), pos.y());
+}
+
+void ArgbLabel::hideTip()
+{
+ if (mapped) {
+ Display *dpy = QX11Info::display();
+ XUnmapWindow(dpy, window);
+ mapped = false;
+ }
+}
+
+#endif // Q_WS_X11
+
+
+
+
+// ----------------------------------------------------------------------------
+
+
+
+
+KToolTipManager *KToolTipManager::s_instance = 0;
+
+KToolTipManager::KToolTipManager()
+ : label(0), currentItem(0), m_delegate(0)
+{
+#ifdef Q_WS_X11
+ Display *dpy = QX11Info::display();
+ int screen = DefaultScreen(dpy);
+ int depth = DefaultDepth(dpy, screen);
+ Visual *visual = DefaultVisual(dpy, screen);
+ net_wm_cm_s0 = XInternAtom(dpy, "_NET_WM_CM_S0", False);
+ haveArgbVisual = false;
+
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = screen;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask |
+ VisualClassMask, &templ, &nvi);
+
+ for (int i = 0; i < nvi; ++i)
+ {
+ XRenderPictFormat *format = XRenderFindVisualFormat(dpy, xvi[i].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask)
+ {
+ visual = xvi[i].visual;
+ depth = xvi[i].depth;
+ haveArgbVisual = true;
+ break;
+ }
+ }
+
+ if (haveArgbVisual)
+ label = new ArgbLabel(visual, depth);
+ else
+#endif
+ label = new QWidgetLabel();
+}
+
+KToolTipManager::~KToolTipManager()
+{
+ delete label;
+ delete currentItem;
+}
+
+void KToolTipManager::showTip(const QPoint &pos, KToolTipItem *item)
+{
+ hideTip();
+ label->showTip(pos, item);
+ currentItem = item;
+ m_tooltipPos = pos;
+}
+
+void KToolTipManager::hideTip()
+{
+ label->hideTip();
+ delete currentItem;
+ currentItem = 0;
+}
+
+void KToolTipManager::initStyleOption(KStyleOptionToolTip *option) const
+{
+ option->direction = QApplication::layoutDirection();
+ option->fontMetrics = QFontMetrics(QToolTip::font());
+ option->activeCorner = KStyleOptionToolTip::TopLeftCorner;
+ option->palette = QToolTip::palette();
+ option->font = QToolTip::font();
+ option->rect = QRect();
+ option->state = QStyle::State_None;
+ option->decorationSize = QSize(32, 32);
+}
+
+bool KToolTipManager::haveAlphaChannel() const
+{
+#ifdef Q_WS_X11
+ // ### This is a synchronous call - ideally we'd use a selection
+ // watcher to avoid it.
+ return haveArgbVisual &&
+ XGetSelectionOwner(QX11Info::display(), net_wm_cm_s0) != None;
+#else
+ return false;
+#endif
+}
+
+void KToolTipManager::setDelegate(KToolTipDelegate *delegate)
+{
+ m_delegate = delegate;
+}
+
+void KToolTipManager::update()
+{
+ if (currentItem == 0)
+ return;
+ label->showTip(m_tooltipPos, currentItem);
+}
+
+KToolTipDelegate *KToolTipManager::delegate() const
+{
+ return m_delegate;
+}
+
+
+
+// ----------------------------------------------------------------------------
+
+
+
+namespace KToolTip
+{
+ void showText(const QPoint &pos, const QString &text, QWidget *widget, const QRect &rect)
+ {
+ Q_UNUSED(widget)
+ Q_UNUSED(rect)
+ KToolTipItem *item = new KToolTipItem(text);
+ KToolTipManager::instance()->showTip(pos, item);
+ }
+
+ void showText(const QPoint &pos, const QString &text, QWidget *widget)
+ {
+ showText(pos, text, widget, QRect());
+ }
+
+ void showTip(const QPoint &pos, KToolTipItem *item)
+ {
+ KToolTipManager::instance()->showTip(pos, item);
+ }
+
+ void hideTip()
+ {
+ KToolTipManager::instance()->hideTip();
+ }
+
+ void setToolTipDelegate(KToolTipDelegate *delegate)
+ {
+ KToolTipManager::instance()->setDelegate(delegate);
+ }
+}
+
diff --git a/src/tooltips/ktooltip.h b/src/tooltips/ktooltip.h
new file mode 100644
index 000000000..d59f1bf17
--- /dev/null
+++ b/src/tooltips/ktooltip.h
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Fredrik Höglund <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef KTOOLTIP_H
+#define KTOOLTIP_H
+
+#include <QObject>
+#include <QPalette>
+#include <QFont>
+#include <QRect>
+#include <QStyle>
+#include <QFontMetrics>
+
+class QString;
+class QIcon;
+class QSize;
+class QPainter;
+class QRegion;
+
+class KToolTipItemPrivate;
+
+/**
+ * KToolTipItem contains the data to be displayed in a tooltip.
+ *
+ * Custom data can be stored as QVariants in the object by calling
+ * setData() with a custom item role, and retrieved and displayed
+ * by a tooltip delegate by calling data().
+ *
+ * The default tooltip delegate uses Qt::DecorationRole and
+ * Qt::DisplayRole.
+ *
+ * To display the tooltip, call KToolTip::showTip() with a pointer
+ * to the KToolTipItem.
+ *
+ * You can reimplement the setData() and/or data() methods in this
+ * class to implement on-demand loading of data.
+ */
+class KToolTipItem
+{
+public:
+ enum ItemType { DefaultType, UserType = 1000 };
+
+ /**
+ * Creates a KToolTipItem with @p text and no icon.
+ */
+ explicit KToolTipItem(const QString &text, int type = DefaultType);
+
+ /**
+ * Creates a KToolTipItem with an @p icon and @p text.
+ */
+ KToolTipItem(const QIcon &icon, const QString &text, int type = DefaultType);
+
+ /**
+ * Destroys the KToolTipItem.
+ */
+ virtual ~KToolTipItem();
+
+ /**
+ * Returns the item type.
+ */
+ int type() const;
+
+ QString text() const;
+ QIcon icon() const;
+
+ virtual QVariant data(int role) const;
+ virtual void setData(int role, const QVariant &data);
+
+private:
+ KToolTipItemPrivate * const d;
+};
+
+
+class KStyleOptionToolTip
+{
+public:
+ KStyleOptionToolTip();
+ enum Corner { TopLeftCorner, TopRightCorner, BottomLeftCorner, BottomRightCorner, NoCorner };
+
+ Qt::LayoutDirection direction;
+ QFontMetrics fontMetrics;
+ QPalette palette;
+ QRect rect;
+ QStyle::State state;
+ QFont font;
+ QSize decorationSize;
+ Corner activeCorner;
+};
+
+/**
+ * KToolTipDelegate is responsible for providing the size hint and
+ * painting the tooltips.
+ */
+class KToolTipDelegate : public QObject
+{
+ Q_OBJECT
+public:
+ KToolTipDelegate();
+ virtual ~KToolTipDelegate();
+
+ virtual QSize sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+
+ /**
+ * If haveAlphaChannel() returns true, the paint device will be filled with
+ * Qt::transparent when this function is called, otherwise the content is
+ * undefined.
+ */
+ virtual void paint(QPainter *painter, const KStyleOptionToolTip *option,
+ const KToolTipItem *item) const;
+
+ /**
+ * Reimplement this function to specify the region of the tooltip
+ * that accepts input. Any mouse events that occur outside this
+ * region will be sent to the widget below the tooltip.
+ *
+ * The default implementation returns a region containing the
+ * bounding rect of the tooltip.
+ *
+ * This function will only be called if haveAlphaChannel()
+ * returns true.
+ */
+ virtual QRegion inputShape(const KStyleOptionToolTip *option) const;
+
+ /**
+ * Reimplement this function to specify a shape mask for the tooltip.
+ *
+ * The default implementation returns a region containing the
+ * bounding rect of the tooltip.
+ *
+ * This function will only be called if haveAlphaChannel()
+ * returns false.
+ */
+ virtual QRegion shapeMask(const KStyleOptionToolTip *option) const;
+
+protected:
+ /**
+ * Returns true if the tooltip has an alpha channel, and false
+ * otherwise.
+ *
+ * Implementors should assume that this condition may change at
+ * any time during the runtime of the application, as compositing
+ * can be enabled or disabled in the window manager.
+ */
+ bool haveAlphaChannel() const;
+
+#if 0
+private Q_SLOTS:
+ /**
+ * Schedules a repaint of the tooltip item.
+ * This slot can be connected to a timer to animate the tooltip.
+ */
+ void update(const KToolTipItem *item);
+#endif
+};
+
+
+/**
+ * KToolTip provides customizable tooltips that can have animations as well as an alpha
+ * channel, allowing for dynamic transparency effects.
+ *
+ * ARGB tooltips work on X11 even when the application isn't using the ARGB visual.
+ */
+namespace KToolTip
+{
+ void showText(const QPoint &pos, const QString &text, QWidget *widget, const QRect &rect);
+ void showText(const QPoint &pos, const QString &text, QWidget *widget = 0);
+
+ /**
+ * Shows the tip @p item at the global position indicated by @p pos.
+ *
+ * Ownership of the item is transferred to KToolTip. The item will be deleted
+ * automatically when it is hidden.
+ *
+ * The tip is shown immediately when this function is called.
+ */
+ void showTip(const QPoint &pos, KToolTipItem *item);
+ void hideTip();
+
+ void setToolTipDelegate(KToolTipDelegate *delegate);
+}
+
+#endif
diff --git a/src/tooltips/ktooltip_p.h b/src/tooltips/ktooltip_p.h
new file mode 100644
index 000000000..332df4854
--- /dev/null
+++ b/src/tooltips/ktooltip_p.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Fredrik Höglund <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef KTOOLTIP_P_H
+#define KTOOLTIP_P_H
+
+class KAbstractToolTipLabel;
+class KStyleOptionToolTip;
+class KToolTipDelegate;
+
+class KToolTipManager
+{
+public:
+ ~KToolTipManager();
+
+ static KToolTipManager *instance() {
+ if (!s_instance)
+ s_instance = new KToolTipManager();
+
+ return s_instance;
+ }
+
+ void showTip(const QPoint &pos, KToolTipItem *item);
+ void hideTip();
+
+ void initStyleOption(KStyleOptionToolTip *option) const;
+ bool haveAlphaChannel() const;
+
+ void setDelegate(KToolTipDelegate *delegate);
+ KToolTipDelegate *delegate() const;
+
+ void update();
+
+private:
+ KToolTipManager();
+
+ KAbstractToolTipLabel *label;
+ KToolTipItem *currentItem;
+ KToolTipDelegate *m_delegate;
+
+ QPoint m_tooltipPos;
+
+#ifdef Q_WS_X11
+ bool haveArgbVisual;
+ Atom net_wm_cm_s0;
+#endif
+
+ static KToolTipManager *s_instance;
+};
+
+#endif
diff --git a/src/tooltips/tooltipmanager.cpp b/src/tooltips/tooltipmanager.cpp
new file mode 100644
index 000000000..36a008f33
--- /dev/null
+++ b/src/tooltips/tooltipmanager.cpp
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (C) 2008 by Konstantin Heil <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ *******************************************************************************/
+
+#include "tooltipmanager.h"
+
+#include "dolphintooltip.h"
+#include "dolphinmodel.h"
+#include "dolphinsortfilterproxymodel.h"
+
+#include <kicon.h>
+#include <tooltips/ktooltip.h>
+#include <kio/previewjob.h>
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QScrollBar>
+#include <QTimer>
+#include <QToolTip>
+
+const int ICON_WIDTH = 128;
+const int ICON_HEIGHT = 128;
+const int PREVIEW_DELAY = 250;
+
+K_GLOBAL_STATIC(DolphinBalloonTooltipDelegate, g_delegate)
+
+ToolTipManager::ToolTipManager(QAbstractItemView* parent,
+ DolphinSortFilterProxyModel* model) :
+ QObject(parent),
+ m_view(parent),
+ m_dolphinModel(0),
+ m_proxyModel(model),
+ m_timer(0),
+ m_previewTimer(0),
+ m_waitOnPreviewTimer(0),
+ m_item(),
+ m_itemRect(),
+ m_preview(false),
+ m_generatingPreview(false),
+ m_previewIsLate(false),
+ m_previewPass(0),
+ m_emptyRenderedKToolTipItem(0),
+ m_pix()
+{
+ KToolTip::setToolTipDelegate(g_delegate);
+
+ m_dolphinModel = static_cast<DolphinModel*>(m_proxyModel->sourceModel());
+ connect(parent, SIGNAL(entered(const QModelIndex&)),
+ this, SLOT(requestToolTip(const QModelIndex&)));
+ connect(parent, SIGNAL(viewportEntered()),
+ this, SLOT(hideToolTip()));
+
+ m_timer = new QTimer(this);
+ m_timer->setSingleShot(true);
+ connect(m_timer, SIGNAL(timeout()),
+ this, SLOT(prepareToolTip()));
+
+ m_previewTimer = new QTimer(this);
+ m_previewTimer->setSingleShot(true);
+ connect(m_previewTimer, SIGNAL(timeout()),
+ this, SLOT(startPreviewJob()));
+
+ m_waitOnPreviewTimer = new QTimer(this);
+ m_waitOnPreviewTimer->setSingleShot(true);
+ connect(m_waitOnPreviewTimer, SIGNAL(timeout()),
+ this, SLOT(prepareToolTip()));
+
+ // When the mousewheel is used, the items don't get a hovered indication
+ // (Qt-issue #200665). To assure that the tooltip still gets hidden,
+ // the scrollbars are observed.
+ connect(parent->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(hideTip()));
+ connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ this, SLOT(hideTip()));
+
+ m_view->viewport()->installEventFilter(this);
+}
+
+ToolTipManager::~ToolTipManager()
+{
+}
+
+void ToolTipManager::hideTip()
+{
+ hideToolTip();
+}
+
+bool ToolTipManager::eventFilter(QObject* watched, QEvent* event)
+{
+ if ((watched == m_view->viewport()) && (event->type() == QEvent::Leave)) {
+ hideToolTip();
+ }
+
+ return QObject::eventFilter(watched, event);
+}
+
+void ToolTipManager::requestToolTip(const QModelIndex& index)
+{
+ // only request a tooltip for the name column and when no selection or
+ // drag & drop operation is done (indicated by the left mouse button)
+ if ((index.column() == DolphinModel::Name) && !(QApplication::mouseButtons() & Qt::LeftButton)) {
+ m_waitOnPreviewTimer->stop();
+ KToolTip::hideTip();
+
+ m_itemRect = m_view->visualRect(index);
+ const QPoint pos = m_view->viewport()->mapToGlobal(m_itemRect.topLeft());
+ m_itemRect.moveTo(pos);
+
+ const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
+ m_item = m_dolphinModel->itemForIndex(dirIndex);
+
+ // only start the previewJob when the mouse has been over this item for 200 milliseconds,
+ // this prevents a lot of useless preview jobs when passing rapidly over a lot of items
+ m_previewTimer->start(200);
+ m_preview = false;
+ m_previewIsLate = false;
+ m_previewPass = 0;
+
+ m_timer->start(500);
+ } else {
+ hideToolTip();
+ }
+}
+
+void ToolTipManager::hideToolTip()
+{
+ m_timer->stop();
+ m_previewTimer->stop();
+ m_waitOnPreviewTimer->stop();
+ m_previewIsLate = false;
+ KToolTip::hideTip();
+}
+
+void ToolTipManager::prepareToolTip()
+{
+ if (m_generatingPreview) {
+ if (m_previewPass == 1) {
+ // We waited 250msec and the preview is still not finished,
+ // so show the toolTip with a transparent image of maximal width.
+ // When the preview finishes, m_previewIsLate will cause
+ // a direct update of the tooltip, via m_emptyRenderedKToolTipItem.
+ QPixmap paddedImage(QSize(PREVIEW_WIDTH, 32));
+ m_previewIsLate = true;
+ paddedImage.fill(Qt::transparent);
+ KToolTipItem* toolTip = new KToolTipItem(paddedImage, m_item.getToolTipText());
+ m_emptyRenderedKToolTipItem = toolTip; // make toolTip accessible everywhere
+ showToolTip(toolTip);
+ }
+
+ ++m_previewPass;
+ m_waitOnPreviewTimer->start(250);
+ } else {
+ // The preview generation has finished, find out under which circumstances.
+ if (m_preview && m_previewIsLate) {
+ // We got a preview, but it is late, the tooltip has already been shown.
+ // So update the tooltip directly.
+ if (m_emptyRenderedKToolTipItem != 0) {
+ m_emptyRenderedKToolTipItem->setData(Qt::DecorationRole, KIcon(m_pix));
+ }
+ return;
+ }
+
+ KIcon icon;
+ if (m_preview) {
+ // We got a preview.
+ icon = KIcon(m_pix);
+ } else {
+ // No preview, so use an icon.
+ // Force a 128x128 icon, a 256x256 one is far too big.
+ icon = KIcon(KIcon(m_item.iconName()).pixmap(ICON_WIDTH, ICON_HEIGHT));
+ }
+
+ KToolTipItem* toolTip = new KToolTipItem(icon, m_item.getToolTipText());
+ showToolTip(toolTip);
+ }
+}
+
+void ToolTipManager::showToolTip(KToolTipItem* tip)
+{
+ if (QApplication::mouseButtons() & Qt::LeftButton) {
+ delete tip;
+ tip = 0;
+ // m_emptyRenderedKToolTipItem is an alias for tip.
+ m_emptyRenderedKToolTipItem = 0;
+ return;
+ }
+
+ KStyleOptionToolTip option;
+ // TODO: get option content from KToolTip or add KToolTip::sizeHint() method
+ option.direction = QApplication::layoutDirection();
+ option.fontMetrics = QFontMetrics(QToolTip::font());
+ option.activeCorner = KStyleOptionToolTip::TopLeftCorner;
+ option.palette = QToolTip::palette();
+ option.font = QToolTip::font();
+ option.rect = QRect();
+ option.state = QStyle::State_None;
+ option.decorationSize = QSize(32, 32);
+
+ QSize size;
+ if (m_previewIsLate) {
+ QPixmap paddedImage(QSize(PREVIEW_WIDTH, PREVIEW_HEIGHT));
+ KToolTipItem* maxiTip = new KToolTipItem(paddedImage, m_item.getToolTipText());
+ size = g_delegate->sizeHint(&option, maxiTip);
+ delete maxiTip;
+ maxiTip = 0;
+ }
+ else {
+ size = g_delegate->sizeHint(&option, tip);
+ }
+ const QRect desktop = QApplication::desktop()->screenGeometry(m_itemRect.bottomRight());
+
+ // m_itemRect defines the area of the item, where the tooltip should be
+ // shown. Per default the tooltip is shown in the bottom right corner.
+ // If the tooltip content exceeds the desktop borders, it must be assured that:
+ // - the content is fully visible
+ // - the content is not drawn inside m_itemRect
+ const bool hasRoomToLeft = (m_itemRect.left() - size.width() >= desktop.left());
+ const bool hasRoomToRight = (m_itemRect.right() + size.width() <= desktop.right());
+ const bool hasRoomAbove = (m_itemRect.top() - size.height() >= desktop.top());
+ const bool hasRoomBelow = (m_itemRect.bottom() + size.height() <= desktop.bottom());
+ if (!hasRoomAbove && !hasRoomBelow && !hasRoomToLeft && !hasRoomToRight) {
+ delete tip;
+ tip = 0;
+ return;
+ }
+
+ int x = 0;
+ int y = 0;
+ if (hasRoomBelow || hasRoomAbove) {
+ x = QCursor::pos().x() + 16; // TODO: use mouse pointer width instead of the magic value of 16
+ if (x + size.width() >= desktop.right()) {
+ x = desktop.right() - size.width();
+ }
+ y = hasRoomBelow ? m_itemRect.bottom() : m_itemRect.top() - size.height();
+ } else {
+ Q_ASSERT(hasRoomToLeft || hasRoomToRight);
+ x = hasRoomToRight ? m_itemRect.right() : m_itemRect.left() - size.width();
+
+ // Put the tooltip at the bottom of the screen. The x-coordinate has already
+ // been adjusted, so that no overlapping with m_itemRect occurs.
+ y = desktop.bottom() - size.height();
+ }
+
+ KToolTip::showTip(QPoint(x, y), tip);
+}
+
+
+
+void ToolTipManager::startPreviewJob()
+{
+ m_generatingPreview = true;
+ KIO::PreviewJob* job = KIO::filePreview(KFileItemList() << m_item,
+ PREVIEW_WIDTH,
+ PREVIEW_HEIGHT);
+ job->setIgnoreMaximumSize(true);
+
+ connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
+ this, SLOT(setPreviewPix(const KFileItem&, const QPixmap&)));
+ connect(job, SIGNAL(failed(const KFileItem&)),
+ this, SLOT(previewFailed(const KFileItem&)));
+}
+
+
+void ToolTipManager::setPreviewPix(const KFileItem& item,
+ const QPixmap& pixmap)
+{
+ if (m_item.url() != item.url()) {
+ m_generatingPreview = false;
+ return;
+ }
+
+ if (m_previewIsLate) {
+ // always use the maximal width
+ QPixmap paddedImage(QSize(PREVIEW_WIDTH, pixmap.height()));
+ paddedImage.fill(Qt::transparent);
+ QPainter painter(&paddedImage);
+ painter.drawPixmap((PREVIEW_WIDTH - pixmap.width()) / 2, 0, pixmap);
+ m_pix = paddedImage;
+ } else {
+ m_pix = pixmap;
+ }
+ m_preview = true;
+ m_generatingPreview = false;
+}
+
+void ToolTipManager::previewFailed(const KFileItem& item)
+{
+ Q_UNUSED(item);
+ m_generatingPreview = false;
+}
+
+#include "tooltipmanager.moc"
diff --git a/src/tooltips/tooltipmanager.h b/src/tooltips/tooltipmanager.h
new file mode 100644
index 000000000..96df4819e
--- /dev/null
+++ b/src/tooltips/tooltipmanager.h
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (C) 2008 by Konstantin Heil <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ *******************************************************************************/
+
+#ifndef TOOLTIPMANAGER_H
+#define TOOLTIPMANAGER_H
+
+#include <QObject>
+#include <QRect>
+
+#include <kfileitem.h>
+
+class DolphinModel;
+class DolphinSortFilterProxyModel;
+class QAbstractItemView;
+class QModelIndex;
+class QTimer;
+class KToolTipItem;
+
+/**
+ * @brief Manages the tooltips for an item view.
+ *
+ * When hovering an item, a tooltip is shown after
+ * a short timeout. The tooltip is hidden again when the
+ * viewport is hovered or the item view has been left.
+ */
+class ToolTipManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ToolTipManager(QAbstractItemView* parent,
+ DolphinSortFilterProxyModel* model);
+ virtual ~ToolTipManager();
+
+public slots:
+ /**
+ * Hides the currently shown tooltip. Invoking this method is
+ * only needed when the tooltip should be hidden although
+ * an item is hovered.
+ */
+ void hideTip();
+
+protected:
+ virtual bool eventFilter(QObject* watched, QEvent* event);
+
+private slots:
+ void requestToolTip(const QModelIndex& index);
+ void hideToolTip();
+ void prepareToolTip();
+ void startPreviewJob();
+ void setPreviewPix(const KFileItem& item, const QPixmap& pix);
+ void previewFailed(const KFileItem& item);
+
+private:
+ void showToolTip(KToolTipItem* tip);
+
+ QAbstractItemView* m_view;
+ DolphinModel* m_dolphinModel;
+ DolphinSortFilterProxyModel* m_proxyModel;
+
+ QTimer* m_timer;
+ QTimer* m_previewTimer;
+ QTimer* m_waitOnPreviewTimer;
+ KFileItem m_item;
+ QRect m_itemRect;
+ bool m_preview;
+ bool m_generatingPreview;
+ bool m_previewIsLate;
+ int m_previewPass;
+ KToolTipItem* m_emptyRenderedKToolTipItem;
+ QPixmap m_pix;
+
+};
+
+#endif