]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Provide tooltips. Per default tooltips are turned off because the information sidebar...
authorPeter Penz <peter.penz19@gmail.com>
Wed, 9 Apr 2008 20:12:43 +0000 (20:12 +0000)
committerPeter Penz <peter.penz19@gmail.com>
Wed, 9 Apr 2008 20:12:43 +0000 (20:12 +0000)
Thanks a lot to Konstantin Heil and Fredrik Höglund for the code :-)

CCMAIL: konst.heil@stud.uni-heidelberg.de
CCMAIL: fredrik@kde.org

svn path=/trunk/KDE/kdebase/apps/; revision=795324

12 files changed:
src/CMakeLists.txt
src/dolphincolumnwidget.cpp
src/dolphinview.cpp
src/kballoontipdelegate.cpp [new file with mode: 0644]
src/kballoontipdelegate.h [new file with mode: 0644]
src/kformattedballoontipdelegate.cpp [new file with mode: 0644]
src/kformattedballoontipdelegate.h [new file with mode: 0644]
src/ktooltip.cpp [new file with mode: 0644]
src/ktooltip.h [new file with mode: 0644]
src/ktooltip_p.h [new file with mode: 0644]
src/tooltipmanager.cpp [new file with mode: 0644]
src/tooltipmanager.h [new file with mode: 0644]

index 77323bb4599863a47ad9c062d64cbb497b4dd5fd..b59d6bb1d7569bc69392f9906a58c61047a552d7 100644 (file)
@@ -27,9 +27,13 @@ set(dolphinprivate_LIB_SRCS
     dolphinview.cpp
     dolphinviewactionhandler.cpp
     iconmanager.cpp
+    ktooltip.cpp
+    kballoontipdelegate.cpp
+    kformattedballoontipdelegate.cpp
     renamedialog.cpp
     selectiontoggle.cpp
     selectionmanager.cpp
+    tooltipmanager.cpp
     viewproperties.cpp
     )
 
@@ -193,4 +197,4 @@ install(TARGETS kcm_dolphin DESTINATION ${PLUGIN_INSTALL_DIR} )
 install( FILES  dolphin.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
 install( FILES  dolphin_directoryviewpropertysettings.kcfg dolphin_generalsettings.kcfg dolphin_columnmodesettings.kcfg dolphin_iconsmodesettings.kcfg dolphin_detailsmodesettings.kcfg DESTINATION ${KCFG_INSTALL_DIR} )
 install( FILES  dolphinui.rc DESTINATION ${DATA_INSTALL_DIR}/dolphin )
-install( FILES kcmdolphin.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
\ No newline at end of file
+install( FILES kcmdolphin.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
index 972098babc27abf77e367e6120bd1ad96fd55c9b..e7993b975f08046f2aeccc1ebfd68375cfacc1a3 100644 (file)
@@ -29,6 +29,7 @@
 #include "dolphin_generalsettings.h"
 #include "draganddrophelper.h"
 #include "selectionmanager.h"
+#include "tooltipmanager.h"
 
 #include <kcolorscheme.h>
 #include <kdirlister.h>
@@ -135,6 +136,10 @@ DolphinColumnWidget::DolphinColumnWidget(QWidget* parent,
     m_iconManager = new IconManager(this, m_proxyModel);
     m_iconManager->setShowPreview(m_view->m_controller->dolphinView()->showPreview());
 
+    if (DolphinSettings::instance().generalSettings()->showToolTips()) {
+        new ToolTipManager(this, m_proxyModel);
+    }
+
     m_dirLister->openUrl(url, KDirLister::NoFlags);
 
     connect(KGlobalSettings::self(), SIGNAL(kdisplayFontChanged()),
index 7b0ac8947b801e58f0d0b60750912604602b0c57..12d6be0d2744dadfe31576cd3974db4ab808e38c 100644 (file)
@@ -57,6 +57,7 @@
 #include "dolphin_generalsettings.h"
 #include "iconmanager.h"
 #include "renamedialog.h"
+#include "tooltipmanager.h"
 #include "viewproperties.h"
 
 DolphinView::DolphinView(QWidget* parent,
@@ -121,10 +122,6 @@ DolphinView::DolphinView(QWidget* parent,
 
     applyViewProperties(url);
     m_topLayout->addWidget(itemView());
-
-    if (DolphinSettings::instance().generalSettings()->showToolTips()) {
-        // TODO: instantiate ToolTipManager here...
-    }
 }
 
 DolphinView::~DolphinView()
@@ -1088,6 +1085,10 @@ void DolphinView::createView()
     m_iconManager = new IconManager(view, m_proxyModel);
     m_iconManager->setShowPreview(m_showPreview);
 
+    if (DolphinSettings::instance().generalSettings()->showToolTips()) {
+        new ToolTipManager(view, m_proxyModel);
+    }
+
     m_topLayout->insertWidget(1, view);
 
     connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
diff --git a/src/kballoontipdelegate.cpp b/src/kballoontipdelegate.cpp
new file mode 100644 (file)
index 0000000..84e0a63
--- /dev/null
@@ -0,0 +1,164 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>               *
+ *                                                                         *
+ *   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 "kballoontipdelegate.h"
+#include <QPainterPath>
+#include <QPainter>
+#include <QBitmap>
+
+QSize KBalloonTipDelegate::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());
+    }
+
+    int margin = 2 * 10 + (option->activeCorner != KStyleOptionToolTip::NoCorner ? 10 : 0);
+    return size + QSize(margin, margin);
+}
+
+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 KBalloonTipDelegate::createPath(const KStyleOptionToolTip *option, QRect *contents) const
+{
+    QPainterPath path;
+    QRect rect = option->rect.adjusted(0, 0, -1, -1);
+    qreal radius = 10;
+
+    switch (option->activeCorner)
+    {
+    case KStyleOptionToolTip::TopLeftCorner:
+        rect.adjust(10, 10, 0, 0);
+        path.moveTo(option->rect.topLeft());
+        path.lineTo(rect.left() + radius, rect.top());
+        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.lineTo(rect.left(), rect.top() + radius);
+        path.closeSubpath();
+        break;
+
+    case KStyleOptionToolTip::TopRightCorner:
+        rect.adjust(0, 10, -10, 0);
+        path.moveTo(option->rect.topRight());
+        path.lineTo(rect.right(), rect.top() + radius);
+        arc(path, rect.right() - radius, rect.bottom() - radius, radius, 0, -90);
+        arc(path, rect.left() + radius, rect.bottom() - radius, radius, 270, -90);
+        arc(path, rect.left() + radius, rect.top() + radius, radius, 180, -90);
+        path.lineTo(rect.right() - radius, rect.top());
+        path.closeSubpath();
+        break;
+
+    case KStyleOptionToolTip::BottomLeftCorner:
+        rect.adjust(10, 0, 0, -10);
+        path.moveTo(option->rect.bottomLeft());
+        path.lineTo(rect.left(), rect.bottom() - 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);
+        path.lineTo(rect.left() + radius, rect.bottom());
+        path.closeSubpath();
+        break;
+
+    case KStyleOptionToolTip::BottomRightCorner:
+        rect.adjust(0, 0, -10, -10);
+        path.moveTo(option->rect.bottomRight());
+        path.lineTo(rect.right() - radius, rect.bottom());
+        arc(path, rect.left() + radius, rect.bottom() - radius, radius, 270, -90);
+        arc(path, rect.left() + radius, rect.top() + radius, radius, 180, -90);
+        arc(path, rect.right() - radius, rect.top() + radius, radius, 90, -90);
+        path.lineTo(rect.right(), rect.bottom() - radius);
+        path.closeSubpath();
+        break;
+
+    default:
+        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();
+        break;
+    }
+
+    if (contents)
+        *contents = rect.adjusted(10, 10, -10, -10);
+
+    return path;
+}
+
+void KBalloonTipDelegate::paint(QPainter *painter, const KStyleOptionToolTip *option, const KToolTipItem *item) const
+{
+    QRect contents;
+    QPainterPath path = createPath(option, &contents);
+    bool alpha = haveAlphaChannel();
+
+    if (alpha) {
+        painter->setRenderHint(QPainter::Antialiasing);
+        painter->translate(.5, .5);
+    }
+
+#if QT_VERSION >= 0x040400
+    painter->setBrush(option->palette.brush(QPalette::ToolTipBase));
+#else
+    painter->setBrush(option->palette.brush(QPalette::Base));
+#endif
+    painter->drawPath(path);
+
+    if (alpha)
+        painter->translate(-.5, -.5);
+
+    QIcon icon = item->icon();
+    if (!icon.isNull()) {
+        const QSize iconSize = icon.actualSize(option->decorationSize);
+        painter->drawPixmap(contents.topLeft(), icon.pixmap(iconSize));
+        contents.adjust(iconSize.width() + 4, 0, 0, 0);
+    }
+
+    painter->drawText(contents, Qt::AlignLeft | Qt::AlignVCenter, item->text());
+}
+
+
+QRegion KBalloonTipDelegate::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 KBalloonTipDelegate::shapeMask(const KStyleOptionToolTip *option) const
+{
+    return inputShape(option);
+}
+
diff --git a/src/kballoontipdelegate.h b/src/kballoontipdelegate.h
new file mode 100644 (file)
index 0000000..0baec17
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>               *
+ *                                                                         *
+ *   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 KBALLOONTIPDELEGATE_H
+#define KBALLOONTIPDELEGATE_H
+
+#include "ktooltip.h"
+
+class KBalloonTipDelegate : public KToolTipDelegate
+{
+public:
+    KBalloonTipDelegate() {}
+    ~KBalloonTipDelegate() {}
+
+    QSize sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+    void paint(QPainter *painter, const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+    QRegion inputShape(const KStyleOptionToolTip *option) const;
+    QRegion shapeMask(const KStyleOptionToolTip *option) const;
+
+private:
+    QPainterPath createPath(const KStyleOptionToolTip *option, QRect *contentRect = 0) const;
+};
+
+#endif
diff --git a/src/kformattedballoontipdelegate.cpp b/src/kformattedballoontipdelegate.cpp
new file mode 100644 (file)
index 0000000..bb3f658
--- /dev/null
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>                   *
+ *   Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
+ *                                                                             *
+ *   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 <QTextDocument>
+
+QSize KFormattedBalloonTipDelegate::sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const
+{
+    QTextDocument doc;
+    doc.setHtml(item->text());
+    QIcon icon = item->icon();
+    QSize is = (icon.isNull()) ? QSize(0,0) : QSize(icon.actualSize(option->decorationSize).width(),0);
+    return doc.size().toSize()+is+QSize(20,20);
+}
+
+void KFormattedBalloonTipDelegate::paint(QPainter *painter, const KStyleOptionToolTip *option, const KToolTipItem *item) const
+{
+    QRect contents;
+    QPainterPath path = createPath(option, &contents);
+    bool alpha = haveAlphaChannel();
+
+    if (alpha) {
+        painter->setRenderHint(QPainter::Antialiasing);
+        painter->translate(.5, .5);
+    }
+
+#if QT_VERSION >= 0x040400
+    painter->setBrush(option->palette.brush(QPalette::ToolTipBase));
+#else
+    painter->setBrush(option->palette.brush(QPalette::Base));
+#endif
+    painter->drawPath(path);
+
+    QIcon icon = item->icon();
+    if (!icon.isNull()) {
+        const QSize iconSize = icon.actualSize(option->decorationSize);
+        painter->drawPixmap(contents.topLeft(), icon.pixmap(iconSize));
+        contents.adjust(iconSize.width() + 4, 0, 0, 0);
+    }
+
+    QTextDocument doc;
+    doc.setHtml(item->text());
+    QBitmap bitmap(doc.size().toSize());
+    bitmap.fill(Qt::color0);
+    QPainter p(&bitmap);
+    doc.drawContents(&p);
+
+    painter->drawPixmap(contents, bitmap, QRect(QPoint(0,0), bitmap.size()));
+}
+
+QRegion KFormattedBalloonTipDelegate::inputShape(const KStyleOptionToolTip *option) const
+{
+    QBitmap bitmap(option->rect.size()+QSize(20,20));
+    bitmap.fill(Qt::color0);
+
+    QPainter p(&bitmap);
+    p.setPen(QPen(Qt::color1, 1));
+    p.setBrush(Qt::color1);
+    p.drawPath(createPath(option, &QRect()));
+
+    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, QRect *contents) const
+{
+    QPainterPath path;
+    QRect rect = option->rect.adjusted(0, 0, -1, -1);
+    qreal radius = 10;
+
+    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();
+
+    if (contents)
+        *contents = rect.adjusted(10, 10, -10, -10);
+
+    return path;
+}
diff --git a/src/kformattedballoontipdelegate.h b/src/kformattedballoontipdelegate.h
new file mode 100644 (file)
index 0000000..c4448b8
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>                   *
+ *   Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
+ *                                                                             *
+ *   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 "ktooltip.h"
+#include <QPainter>
+
+class KFormattedBalloonTipDelegate : public KToolTipDelegate
+{
+public:
+    KFormattedBalloonTipDelegate() {}
+    ~KFormattedBalloonTipDelegate() {}
+
+    QSize sizeHint(const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+    void paint(QPainter *painter, const KStyleOptionToolTip *option, const KToolTipItem *item) const;
+    QRegion inputShape(const KStyleOptionToolTip *option) const;
+    QRegion shapeMask(const KStyleOptionToolTip *option) const;
+
+    QPainterPath createPath(const KStyleOptionToolTip *option, QRect *contents) const;
+};
+
+#endif
diff --git a/src/ktooltip.cpp b/src/ktooltip.cpp
new file mode 100644 (file)
index 0000000..bf607d0
--- /dev/null
@@ -0,0 +1,547 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>               *
+ *                                                                         *
+ *   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"
+
+
+
+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()
+{
+}
+
+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;
+}
+
+
+
+// ----------------------------------------------------------------------------
+
+
+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));
+
+#if QT_VERSION >= 0x040400
+    QColor color = option->palette.color(QPalette::ToolTipBase);
+#else
+    QColor color = option->palette.color(QPalette::Base);
+#endif
+    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)
+{
+#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;
+}
+
+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;
+}
+
+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/ktooltip.h b/src/ktooltip.h
new file mode 100644 (file)
index 0000000..bb8389d
--- /dev/null
@@ -0,0 +1,197 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>               *
+ *                                                                         *
+ *   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.
+      */
+     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
+{
+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 implemenation 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 implemenation 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/ktooltip_p.h b/src/ktooltip_p.h
new file mode 100644 (file)
index 0000000..16ca852
--- /dev/null
@@ -0,0 +1,63 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Fredrik Höglund <fredrik@kde.org>               *
+ *                                                                         *
+ *   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;
+
+private:
+    KToolTipManager();
+
+    KAbstractToolTipLabel *label;
+    KToolTipItem *currentItem;
+    KToolTipDelegate *m_delegate;
+
+#ifdef Q_WS_X11
+    bool haveArgbVisual;
+    Atom net_wm_cm_s0;
+#endif
+
+    static KToolTipManager *s_instance;
+};
+
+#endif
diff --git a/src/tooltipmanager.cpp b/src/tooltipmanager.cpp
new file mode 100644 (file)
index 0000000..6af3bb8
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ *   Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
+ *                                                                             *
+ *   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 "dolphinmodel.h"
+#include "dolphinsortfilterproxymodel.h"
+#include "ktooltip.h"
+#include "kicon.h"
+
+#include <QTimer>
+
+ToolTipManager::ToolTipManager(QAbstractItemView* parent,
+                               DolphinSortFilterProxyModel* model) :
+    QObject(parent),
+    m_view(parent),
+    m_dolphinModel(0),
+    m_proxyModel(model),
+    m_timer(0),
+    m_item(),
+    m_pos(),
+    m_delegate()
+{
+    KToolTip::setToolTipDelegate(&m_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(showToolTip()));
+
+    m_view->viewport()->installEventFilter(this);
+}
+
+ToolTipManager::~ToolTipManager()
+{
+}
+
+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)
+{
+    KToolTip::hideTip();
+
+    const QRect rect = m_view->visualRect(index);
+    m_pos = m_view->viewport()->mapToGlobal(rect.bottomRight());
+
+    const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
+    m_item = m_dolphinModel->itemForIndex(dirIndex);
+
+    m_timer->start(500);
+}
+
+void ToolTipManager::hideToolTip()
+{
+    m_timer->stop();
+    KToolTip::hideTip();
+}
+
+void ToolTipManager::showToolTip()
+{
+    KToolTipItem* tip = new KToolTipItem(KIcon(m_item.iconName()), m_item.getToolTipText());
+    KToolTip::showTip(m_pos, tip);
+}
+
+#include "tooltipmanager.moc"
diff --git a/src/tooltipmanager.h b/src/tooltipmanager.h
new file mode 100644 (file)
index 0000000..8223b5b
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ *   Copyright (C) 2008 by Konstantin Heil <konst.heil@stud.uni-heidelberg.de> *
+ *                                                                             *
+ *   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 <QPoint>
+
+#include <kfileitem.h>
+#include <kformattedballoontipdelegate.h>
+
+class DolphinModel;
+class DolphinSortFilterProxyModel;
+class QAbstractItemView;
+class QModelIndex;
+class QTimer;
+
+/**
+ * @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();
+
+protected:
+    virtual bool eventFilter(QObject* watched, QEvent* event);
+
+private slots:
+    void requestToolTip(const QModelIndex& index);
+    void hideToolTip();
+    void showToolTip();
+
+private:
+    QAbstractItemView* m_view;
+    DolphinModel* m_dolphinModel;
+    DolphinSortFilterProxyModel* m_proxyModel;
+
+    QTimer* m_timer;
+    KFileItem m_item;
+    QPoint m_pos;
+    KFormattedBalloonTipDelegate m_delegate;
+};
+
+#endif