From 357656f660fb17e04398367205942558f2ebaf14 Mon Sep 17 00:00:00 2001 From: Dan Meltzer Date: Fri, 21 Dec 2007 05:33:17 +0000 Subject: [PATCH] Add a generic tooltip widget to Plasma::Widget and implement it in the tasks applet. Applets wishing to use this tooltip should Create a Plasma::ToolTipData struct (defined in widget.h) and pass it to Widget::setToolTip(). Showing and hiding the tooltip is all handled automatically. While the basic idea is found in this patch, the look still definatly needs some work. Still a definate work in progress. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=751113 --- CMakeLists.txt | 1 + widgets/checkbox.cpp | 2 + widgets/radiobutton.cpp | 2 + widgets/tooltip.cpp | 133 ++++++++++++++++++++++++++++++++++++++++ widgets/tooltip_p.h | 64 +++++++++++++++++++ widgets/widget.cpp | 37 +++++++++++ widgets/widget.h | 24 ++++++++ 7 files changed, 263 insertions(+) create mode 100644 widgets/tooltip.cpp create mode 100644 widgets/tooltip_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d4554b24..c3f977e53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ set(plasma_LIB_SRCS widgets/widget.cpp widgets/signalplotter.cpp widgets/meter.cpp + widgets/tooltip.cpp ) kde4_add_ui_files ( diff --git a/widgets/checkbox.cpp b/widgets/checkbox.cpp index af606e3d9..4b4acec8e 100644 --- a/widgets/checkbox.cpp +++ b/widgets/checkbox.cpp @@ -214,6 +214,7 @@ void CheckBox::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) event->accept(); d->hasMouse= false; update(); + Widget::hoverEnterEvent(event); } void CheckBox::hoverEnterEvent ( QGraphicsSceneHoverEvent * event) @@ -221,6 +222,7 @@ void CheckBox::hoverEnterEvent ( QGraphicsSceneHoverEvent * event) event->accept(); d->hasMouse = true; update(); + Widget::hoverLeaveEvent(event); } /* diff --git a/widgets/radiobutton.cpp b/widgets/radiobutton.cpp index 8063ec727..1eeb84ed7 100644 --- a/widgets/radiobutton.cpp +++ b/widgets/radiobutton.cpp @@ -201,6 +201,7 @@ void RadioButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) event->accept(); d->mouseOver = false; update(); + Widget::hoverLeaveEvent(event); } void RadioButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event) @@ -208,6 +209,7 @@ void RadioButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event) event->accept(); d->mouseOver = true; update(); + Widget::hoverEnterEvent(event); } diff --git a/widgets/tooltip.cpp b/widgets/tooltip.cpp new file mode 100644 index 000000000..d6a681296 --- /dev/null +++ b/widgets/tooltip.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2007 by Dan Meltzer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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 "tooltip_p.h" + +#include +#include +#include +#include + +#include + +namespace Plasma { + +class ToolTip::Private +{ + public: + Private() + : label(0) + , imageLabel(0) + , isShown(false) + , showTimer(0) + , hideTimer(0) + { } + + QLabel *label; + QLabel *imageLabel; + bool isShown; + QTimer *showTimer; + QTimer *hideTimer; +}; + +class ToolTipSingleton +{ + public: + ToolTip self; +}; +K_GLOBAL_STATIC( ToolTipSingleton, privateInstance ) + +ToolTip *ToolTip::instance() +{ + return &privateInstance->self; +} + +void ToolTip::show(const QPoint &location, const Plasma::ToolTipData &data) +{ + setData(data); + move(location.x(), location.y() - sizeHint().height()); + if (d->isShown) { + setVisible(true); // Don't delay if the tooltip is already shown(i.e. moving from one task to another) + } + else { + d->showTimer->start(1000); //Shown after a one second delay. + } +} + +void ToolTip::hide() +{ + d->showTimer->stop(); //Mouse out, stop the timer to show the tooltip + if (!isVisible()) { + d->isShown = false; + } + setVisible(false); + d->hideTimer->start(500); //500 ms delay before we are officially "gone" to allow for the time to move between widgets +} + +//PRIVATE FUNCTIONS +void ToolTip::slotShowToolTip() +{ + d->isShown = true; //ToolTip is visible + setVisible(true); +} + +void ToolTip::slotResetTimer() +{ + if (!isVisible()) { //One might have moused out and back in again + d->isShown = false; + } +} + +ToolTip::ToolTip() + : QWidget(0) + , d( new Private ) +{ + setWindowFlags(Qt::ToolTip); + QHBoxLayout *l = new QHBoxLayout; + d->label = new QLabel; + d->label->setWordWrap(true); + d->imageLabel = new QLabel; + d->imageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); + l->addWidget(d->imageLabel); + l->addWidget(d->label); + setLayout(l); + + d->showTimer = new QTimer(this); + d->showTimer->setSingleShot(true); + d->hideTimer = new QTimer(this); + d->hideTimer->setSingleShot(true); + + connect(d->showTimer, SIGNAL(timeout()), SLOT(slotShowToolTip())); + connect(d->hideTimer, SIGNAL(timeout()), SLOT(slotResetTimer())); +} + +void ToolTip::setData(const Plasma::ToolTipData &data) +{ + d->label->setText("

" + data.mainText + "

" + + data.subText + "

"); + d->imageLabel->setPixmap(data.image); +} + +ToolTip::~ToolTip() +{ + delete d; +} + +} +#include "tooltip_p.moc" diff --git a/widgets/tooltip_p.h b/widgets/tooltip_p.h new file mode 100644 index 000000000..7aa4e4ea4 --- /dev/null +++ b/widgets/tooltip_p.h @@ -0,0 +1,64 @@ +/* + * Copyright 2007 by Dan Meltzer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library 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 PLASMATOOLTIP_H +#define PLASMATOOLTIP_H + +#include //ToolTipData struct + +#include // base class +#include // stack allocated +#include // stack allocated +#include // stack allocated + +namespace Plasma { + + class ToolTipData; + +/** + @author Dan Meltzer +* A Singleton tooltip. Before calling show it is necessary to +* call setLocation and setData +*/ +class ToolTip : public QWidget +{ + Q_OBJECT +public: + ToolTip(); + ~ToolTip(); + + static ToolTip *instance(); + void show(const QPoint &location, const Plasma::ToolTipData &data); + void hide(); + +private Q_SLOTS: + void slotResetTimer(); + void slotShowToolTip(); + +private: + void setData(const Plasma::ToolTipData &data); + + class Private; + Private *const d; +}; + +} + +#endif + diff --git a/widgets/widget.cpp b/widgets/widget.cpp index 18be542d0..23572ef44 100644 --- a/widgets/widget.cpp +++ b/widgets/widget.cpp @@ -26,7 +26,9 @@ #include #include +#include #include +#include #include #include #include @@ -36,6 +38,7 @@ #include "layouts/freelayout.h" #include "plasma/plasma.h" +#include "tooltip_p.h" namespace Plasma { @@ -71,6 +74,7 @@ class Widget::Private bool wasMovable; bool shouldPaint(QPainter *painter, const QTransform &transform); + ToolTipData toolTip; }; QGraphicsItem* Widget::graphicsItem() @@ -495,6 +499,21 @@ void Widget::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *opti // Replaced by widget's own function } +ToolTipData Widget::toolTip() const +{ + return d->toolTip; +} + +void Widget::setToolTip(const ToolTipData &tip) +{ + d->toolTip = tip; + if (ToolTip::instance()->isVisible()) { + QPoint viewPos = view()->mapFromScene(scenePos()); + QPoint globalPos = view()->mapToGlobal(viewPos); + ToolTip::instance()->show(globalPos, d->toolTip); + } +} + QVariant Widget::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == QGraphicsItem::ItemChildRemovedChange) { @@ -530,5 +549,23 @@ void Widget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) } } +void Widget::hoverEnterEvent(QGraphicsSceneHoverEvent *e) +{ + if (d->toolTip.image.isNull() && + d->toolTip.subText.isEmpty() && + d->toolTip.mainText.isEmpty()) { + + return; //Nothing to show + } + QPoint viewPos = view()->mapFromScene(scenePos()); + QPoint globalPos = view()->mapToGlobal(viewPos); + ToolTip::instance()->show(globalPos, d->toolTip); +} + +void Widget::hoverLeaveEvent(QGraphicsSceneHoverEvent *e) +{ + ToolTip::instance()->hide(); +} + } // Plasma namespace diff --git a/widgets/widget.h b/widgets/widget.h index 4f3f09337..0541e4d32 100644 --- a/widgets/widget.h +++ b/widgets/widget.h @@ -23,20 +23,31 @@ #define WIDGET_H_ #include +#include #include #include +#include #include #include class QGraphicsView; +class QGraphicsSceneHoverEvent; namespace Plasma { +struct PLASMA_EXPORT ToolTipData +{ + QString mainText; //Important information + QString subText; //Elaborates on the Main Text + QPixmap image; // Icon to show; +}; + class Layout; + /** * Base class for all Widgets in Plasma. * @@ -272,6 +283,17 @@ protected: */ virtual void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + /** + * The Data from the tooltip + * @returns A ToolTip::Data object with current information + */ + ToolTipData toolTip() const; + + /** + * Setter for data shown in tooltip + * @param data a ToolTip::Data object containing icon and text + */ + void setToolTip( const ToolTipData &dt ); /** * Reimplemented from QGraphicsItem */ @@ -281,6 +303,8 @@ protected: void setSize(qreal width, qreal height); void setSize(const QSizeF& size); void managingLayoutChanged(); + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); private: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);