]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/tooltips/ktooltip.cpp
Restore the "Edit->Selection" menu from Konqueror 3 for file
[dolphin.git] / src / tooltips / ktooltip.cpp
index d5aa0f7b77202ddece8ed16944197a1eb65375a8..d0da7983b56c833762b45cdcbd094bbe1a86f009 100644 (file)
  ***************************************************************************/
 
 #include "ktooltip.h"
-
-#include <QApplication>
-#include <QMap>
-#include <QPixmap>
-#include <QPainter>
-#include <QVariant>
-#include <QIcon>
+#include "ktooltipwindow_p.h"
+#include <QLabel>
+#include <QPoint>
 #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
+class KToolTipManager
 {
 public:
-    KAbstractToolTipLabel() {}
-    virtual ~KAbstractToolTipLabel() {}
+    ~KToolTipManager();
 
-    virtual void showTip(const QPoint &pos, const KToolTipItem *item) = 0;
-    virtual void moveTip(const QPoint &pos) = 0;
-    virtual void hideTip() = 0;
+    static KToolTipManager* instance();
 
-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();
-    void showTip(const QPoint &pos, const KToolTipItem *item);
-    void moveTip(const QPoint &pos);
+    void showTip(const QPoint& pos, QWidget* content);
     void hideTip();
 
 private:
-    void paintEvent(QPaintEvent*);
-    QSize sizeHint() const;
+    KToolTipManager();
 
-private:
-    const KToolTipItem *currentItem;
+    KToolTipWindow* m_window;
+    static KToolTipManager *s_instance;
 };
 
-QWidgetLabel::QWidgetLabel() : QWidget(0, Qt::ToolTip)
-{
-    if (KToolTipManager::instance()->haveAlphaChannel()) {
-        setAttribute(Qt::WA_TranslucentBackground);
-    }
-}
-
-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;
-}
+KToolTipManager *KToolTipManager::s_instance = 0;
 
-void ArgbLabel::moveTip(const QPoint &pos)
+KToolTipManager::KToolTipManager() :
+    m_window(0)
 {
-    if (mapped)
-        XMoveWindow(QX11Info::display(), window, pos.x(), pos.y());
 }
 
-void ArgbLabel::hideTip()
+KToolTipManager::~KToolTipManager()
 {
-    if (mapped) {
-        Display *dpy = QX11Info::display();
-        XUnmapWindow(dpy, window);
-       mapped = false;
-    }
+    delete m_window;
+    m_window = 0;
 }
 
-#endif // Q_WS_X11
-
-
-
-
-// ----------------------------------------------------------------------------
-
-
-
-
-KToolTipManager *KToolTipManager::s_instance = 0;
-
-KToolTipManager::KToolTipManager()
-       : label(0), currentItem(0), m_delegate(0)
+KToolTipManager* KToolTipManager::instance()
 {
-#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 (s_instance == 0) {
+        s_instance = new KToolTipManager();
     }
 
-    if (haveArgbVisual)
-        label = new ArgbLabel(visual, depth);
-    else
-#endif
-        label = new QWidgetLabel();
+    return s_instance;
 }
 
-KToolTipManager::~KToolTipManager()
-{
-    delete label;
-    delete currentItem;
-}
-
-void KToolTipManager::showTip(const QPoint &pos, KToolTipItem *item)
+void KToolTipManager::showTip(const QPoint& pos, QWidget* content)
 {
     hideTip();
-    label->showTip(pos, item);
-    currentItem = item;
-    m_tooltipPos = pos;
+    Q_ASSERT(m_window == 0);
+    m_window = new KToolTipWindow(content);
+    m_window->move(pos);
+    m_window->show();
 }
 
 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;
+    if (m_window != 0) {
+        m_window->hide();
+        delete m_window;
+        m_window = 0;
+    }
 }
 
-
-
-// ----------------------------------------------------------------------------
-
-
-
 namespace KToolTip
 {
-    void showText(const QPoint &pos, const QString &text, QWidget *widget, const QRect &rect)
+    void showText(const QPoint& pos, const QString& text)
     {
-        Q_UNUSED(widget)
-        Q_UNUSED(rect)
-        KToolTipItem *item = new KToolTipItem(text);
-        KToolTipManager::instance()->showTip(pos, item);
+        QLabel* label = new QLabel(text);
+        label->setForegroundRole(QPalette::ToolTipText);
+        showTip(pos, label);
     }
 
-    void showText(const QPoint &pos, const QString &text, QWidget *widget)
+    void showTip(const QPoint& pos, QWidget* content)
     {
-        showText(pos, text, widget, QRect());
-    }
-
-    void showTip(const QPoint &pos, KToolTipItem *item)
-    {
-        KToolTipManager::instance()->showTip(pos, item);
+        KToolTipManager::instance()->showTip(pos, content);
     }
 
     void hideTip()
     {
         KToolTipManager::instance()->hideTip();
     }
-
-    void setToolTipDelegate(KToolTipDelegate *delegate)
-    {
-        KToolTipManager::instance()->setDelegate(delegate);
-    }
 }