From c1fb3655cd34bfe73a1f4459e98e5912779d361d Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Wed, 16 Jul 2008 23:27:34 +0000 Subject: [PATCH] * register widgets when data is set on them if they aren't already registered * allocate ToolTip objects only as needed * invoke tool tip show/hide slots on the associated widget to allow for dynamic tooltip data svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=833526 --- tooltip.cpp | 37 ++++++++++++---- tooltip_p.h | 6 ++- tooltipmanager.cpp | 106 ++++++++++++++++++++++++++++----------------- tooltipmanager.h | 82 +++++++++++++++++++++-------------- 4 files changed, 149 insertions(+), 82 deletions(-) diff --git a/tooltip.cpp b/tooltip.cpp index f3c8a5b61..58046822d 100644 --- a/tooltip.cpp +++ b/tooltip.cpp @@ -49,11 +49,12 @@ namespace Plasma { class ToolTipPrivate { public: - ToolTipPrivate() + ToolTipPrivate(QObject *s) : label(0) , imageLabel(0) , preview(0) , windowToPreview(0) + , source(s) { } QLabel *label; @@ -61,7 +62,7 @@ class ToolTipPrivate WindowPreview *preview; WId windowToPreview; PanelSvg *background; - + QObject *source; }; void ToolTip::showEvent(QShowEvent *e) @@ -70,6 +71,14 @@ void ToolTip::showEvent(QShowEvent *e) d->preview->setInfo(); } +void ToolTip::hideEvent(QHideEvent *e) +{ + QWidget::hideEvent(e); + if (d->source) { + QMetaObject::invokeMethod(d->source, SLOT(toolTipHidden())); + } +} + void ToolTip::mouseReleaseEvent(QMouseEvent* event) { if (rect().contains(event->pos())) { @@ -77,10 +86,14 @@ void ToolTip::mouseReleaseEvent(QMouseEvent* event) } } -ToolTip::ToolTip() +ToolTip::ToolTip(QObject *source) : QWidget(0) - , d( new ToolTipPrivate ) + , d(new ToolTipPrivate(source)) { + if (source) { + connect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed())); + } + setWindowFlags(Qt::ToolTip); QGridLayout *l = new QGridLayout; d->preview = new WindowPreview; @@ -97,7 +110,6 @@ ToolTip::ToolTip() l->addWidget(d->imageLabel, 1, 0); l->addWidget(d->label, 1, 1); setLayout(l); - } ToolTip::~ToolTip() @@ -120,16 +132,20 @@ void ToolTip::setContent(const ToolTipManager::ToolTipContent &data) void ToolTip::prepareShowing() { - if( d->windowToPreview != 0 ) { + if (d->source) { + QMetaObject::invokeMethod(d->source, SLOT(toolTipAboutToShow())); + } + + if (d->windowToPreview != 0) { // show/hide the preview area d->preview->show(); } else { d->preview->hide(); } - layout()->activate(); + layout()->activate(); resize(sizeHint()); - + if (isVisible()) { d->preview->setInfo(); } else { @@ -156,6 +172,11 @@ void ToolTip::paintEvent(QPaintEvent *e) d->background->paintPanel(&painter, rect()); } +void ToolTip::sourceDestroyed() +{ + d->source = 0; +} + void ToolTip::updateTheme() { d->background->setImagePath("widgets/tooltip"); diff --git a/tooltip_p.h b/tooltip_p.h index b7828ee43..36e063086 100644 --- a/tooltip_p.h +++ b/tooltip_p.h @@ -38,7 +38,7 @@ class ToolTip : public QWidget { Q_OBJECT public: - ToolTip(); + ToolTip(QObject *source); ~ToolTip(); void updateTheme(); void setContent(const ToolTipManager::ToolTipContent &data); @@ -46,11 +46,15 @@ public: protected: void showEvent(QShowEvent *); + void hideEvent(QHideEvent *); void mouseReleaseEvent(QMouseEvent *); void resizeEvent(QResizeEvent *); void paintEvent(QPaintEvent *); +private Q_SLOTS: + void sourceDestroyed(); + private: ToolTipPrivate *const d; }; diff --git a/tooltipmanager.cpp b/tooltipmanager.cpp index 6603f822f..6ad4729df 100644 --- a/tooltipmanager.cpp +++ b/tooltipmanager.cpp @@ -1,22 +1,23 @@ -/************************************************************************** -* Copyright 2007 by Dan Meltzer * -* Copyright (C) 2008 by Alexis Ménard * -* * -* 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 . * -***************************************************************************/ +/*************************************************************************** + * Copyright 2007 by Dan Meltzer * + * Copyright 2008 by Aaron Seigo * + * Copyright 2008 by Alexis Ménard * + * * + * 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" //Qt @@ -90,6 +91,16 @@ ToolTipManager *ToolTipManager::self() return &privateInstance->self; } +ToolTipManager::ToolTipContent::ToolTipContent() + : windowToPreview(0) +{ +} + +bool ToolTipManager::ToolTipContent::isEmpty() const +{ + return mainText.isEmpty() && subText.isEmpty() && image.isNull() && windowToPreview == 0; +} + ToolTipManager::ToolTipManager(QObject* parent) : QObject(parent), d(new ToolTipManagerPrivate) @@ -113,7 +124,7 @@ ToolTipManager::~ToolTipManager() void ToolTipManager::showToolTip(QGraphicsWidget *widget) { - ToolTip * tooltip = d->tooltips.value(widget); + ToolTip *tooltip = d->tooltips.value(widget); if (tooltip) { if (d->currentWidget) { hideToolTip(d->currentWidget); @@ -134,11 +145,10 @@ void ToolTipManager::showToolTip(QGraphicsWidget *widget) bool ToolTipManager::isWidgetToolTipDisplayed(QGraphicsWidget *widget) { - ToolTip * tooltip = d->tooltips.value(widget); + ToolTip *tooltip = d->tooltips.value(widget); if (tooltip) { return tooltip->isVisible(); - } - else { + } else { return false; } } @@ -152,23 +162,23 @@ void ToolTipManager::delayedHideToolTip() void ToolTipManager::hideToolTip(QGraphicsWidget *widget) { - ToolTip * tooltip = d->tooltips.value(widget); - if (tooltip) { - d->showTimer->stop(); // stop the timer to show the tooltip - d->delayedHide = false; - d->currentWidget = 0; - tooltip->hide(); - } + ToolTip *tooltip = d->tooltips.value(widget); + if (tooltip) { + d->showTimer->stop(); // stop the timer to show the tooltip + d->delayedHide = false; + d->currentWidget = 0; + tooltip->hide(); + } } void ToolTipManager::registerWidget(QGraphicsWidget *widget) { if (!d->tooltips.contains(widget)) { //the tooltip is not registered we add it in our map of tooltips - d->tooltips.insert(widget,new ToolTip()); + d->tooltips.insert(widget, 0); widget->installEventFilter(this); //connect to object destruction - connect(widget,SIGNAL(destroyed(QObject *)),this,SLOT(onWidgetDestroyed(QObject *))); + connect(widget, SIGNAL(destroyed(QObject *)),this,SLOT(onWidgetDestroyed(QObject *))); } } @@ -178,19 +188,30 @@ void ToolTipManager::unregisterWidget(QGraphicsWidget *widget) return; } widget->removeEventFilter(this); - ToolTip * tooltip = d->tooltips.take(widget); + ToolTip *tooltip = d->tooltips.take(widget); if (tooltip) { delete tooltip; } } -void ToolTipManager::setWidgetToolTipContent(QGraphicsWidget *widget,const ToolTipContent &data) +void ToolTipManager::setToolTipContent(QGraphicsWidget *widget, const ToolTipContent &data) { if (!d->tooltips.contains(widget)) { + registerWidget(widget); + } + + ToolTip *tooltip = d->tooltips.value(widget); + + if (data.isEmpty()) { + delete tooltip; + d->tooltips.insert(widget, 0); return; } - ToolTip * tooltip = d->tooltips.value(widget); + if (!tooltip) { + d->tooltips.insert(widget, new ToolTip(widget)); + } + tooltip->setContent(data); tooltip->updateTheme(); } @@ -234,10 +255,12 @@ void ToolTipManagerPrivate::onWidgetDestroyed(QObject *object) while (iterator.hasNext()) { iterator.next(); if (iterator.key() == w) { - ToolTip * tooltip = iterator.value(); + ToolTip *tooltip = iterator.value(); tooltips.remove(iterator.key()); - tooltip->hide(); - delete tooltip; + if (tooltip) { + tooltip->hide(); + delete tooltip; + } } } } @@ -262,7 +285,7 @@ void ToolTipManagerPrivate::showToolTip() return; } - ToolTip * tooltip = tooltips.value(currentWidget); + ToolTip *tooltip = tooltips.value(currentWidget); if (tooltip) { tooltip->prepareShowing(); tooltip->move(ToolTipManager::popupPosition(currentWidget,tooltip->size())); @@ -295,7 +318,10 @@ bool ToolTipManager::eventFilter(QObject *watched, QEvent *event) // created the widget can receive a hover event before it is fully // initialized, in which case view() will return 0. const Applet * applet = ToolTipManager::getItemItsApplet(widget); - if (!applet) break; + if (!applet) { + break; + } + QGraphicsView *parentView = applet->view(); if (parentView) { showToolTip(widget); diff --git a/tooltipmanager.h b/tooltipmanager.h index 73663d23e..63d9e3baf 100644 --- a/tooltipmanager.h +++ b/tooltipmanager.h @@ -1,22 +1,23 @@ /*************************************************************************** -* Copyright (C) 2007 by Alexis Ménard * -* Copyright 2007 by Dan Meltzer * -* * -* 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 . * -***************************************************************************/ + * Copyright 2008 by Alexis Ménard * + * Copyright 2008 by Aaron Seigo * + * Copyright 2007 by Dan Meltzer * + * * + * 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 PLASMA_TOOLTIP_MANAGER_H #define PLASMA_TOOLTIP_MANAGER_H @@ -46,8 +47,19 @@ namespace Plasma /** * @short The class to manage tooltips on QGraphicsWidget in Plasma * - * Manage tooltips on QGraphicsWidget. First you have to register your widget by calling registerWidget on the ToolTipManager singleton. After this you have to set the content of the tooltip by calling setWidgetToolTipContent using the struct ToolTipContent. The tooltip manager unregister automatically the widget when it is destroyed but if you want to do it manually call unregisterWidget. If you use plasma's applets show/hide of tooltip is automatically manage but if you use custom QGraphicsWidget, please call showToolTip on you hoverEnterEvent or hideToolTip on you hoverLeaveEvent. + * Manage tooltips on QGraphicsWidget. First you have to register your widget by calling + * registerWidget on the ToolTipManager singleton. After this you have to set the content of + * the tooltip by calling setToolTipContent using the struct ToolTipContent. Calling + * setToolTipContent on a widget that is not registered will cause it to be registered. + * + * The tooltip manager unregister automatically the widget when it is destroyed but if + * you want to do it manually call unregisterWidget. + * + * When a tooltip for a widget is about to be shown, the widget's toolTipAboutToShow slot will be + * invoked if it exists. Similarly, when a tooltip is hidden, the widget's toolTipHidden() slow + * will be invoked if it exists. This allows widgets to provide on-demand tooltip data. */ + class PLASMA_EXPORT ToolTipManager : public QObject { Q_OBJECT @@ -58,11 +70,13 @@ namespace Plasma */ struct ToolTipContent { - ToolTipContent() : windowToPreview( 0 ) {} - QString mainText; /**Important information, e.g. the title*/ - QString subText; /** Elaborates on the Main Text */ - QPixmap image; /** Icon to show */ - WId windowToPreview; /** Id of a window if you want to show a preview */ + ToolTipContent(); + bool isEmpty() const; + + QString mainText; /**Important information, e.g. the title*/ + QString subText; /** Elaborates on the Main Text */ + QPixmap image; /** Icon to show */ + WId windowToPreview; /** Id of a window if you want to show a preview */ }; /** @@ -75,12 +89,12 @@ namespace Plasma * Default constructor. Usually you want to use the singleton instead. */ explicit ToolTipManager(QObject* parent = 0); - + /** * Default destructor. */ ~ToolTipManager(); - + /** * Function to show a tooltip of a widget registered in the tooltip manager * @param widget the widget on which the tooltip will be displayed @@ -120,19 +134,21 @@ namespace Plasma void unregisterWidget(QGraphicsWidget *widget); /** - * Function to set the content of a tooltip on a desired widget - * @param widget the desired widget - * @param data the content of the tooltip - */ - void setWidgetToolTipContent(QGraphicsWidget *widget,const ToolTipContent &data); - + * Function to set the content of a tooltip on a desired widget. + * + * @param widget the desired widget + * @param data the content of the tooltip. If an empty ToolTipContent is passed in, + * the tooltip content will be reset. + */ + void setToolTipContent(QGraphicsWidget *widget, const ToolTipContent &data); + /** * Function to know if widget has a tooltip registered in the tooltip manager * @param widget the widget * @return true if this widget has a tooltip */ bool widgetHasToolTip(QGraphicsWidget *widget) const; - + /** * Reccomended position for a popup window like a menu or a tooltip * given its size