plasma-framework/tooltipmanager.cpp
Alexis Ménard aa2a6f536d oops don't compile ;) revert the last commit
svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=833299
2008-07-16 15:52:56 +00:00

312 lines
8.9 KiB
C++

/**************************************************************************
* Copyright 2007 by Dan Meltzer <hydrogen@notyetimplemented.com> *
* Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com> *
* *
* 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
#include <QLabel>
#include <QTimer>
#include <QGridLayout>
#include <QGraphicsView>
#include <QDesktopWidget>
//KDE
#include <KWindowSystem>
//Plasma
#include <plasma/theme.h>
#include <plasma/panelsvg.h>
#include <plasma/tooltip_p.h>
#include <plasma/applet.h>
#include <plasma/view.h>
#include <plasma/containment.h>
namespace Plasma
{
class ToolTipManagerPrivate
{
public :
ToolTipManagerPrivate()
: currentWidget(0)
, showTimer(0)
, hideTimer(0)
{
}
~ToolTipManagerPrivate()
{
}
void showToolTip();
void resetShownState();
QGraphicsWidget *currentWidget;
bool isShown;
bool delayedHide;
QTimer *showTimer;
QTimer *hideTimer;
QMap<QGraphicsWidget *, ToolTip *> tooltips;
};
//TOOLTIP IMPLEMENTATION
class ToolTipManagerSingleton
{
public:
ToolTipManagerSingleton()
{
}
ToolTipManager self;
};
K_GLOBAL_STATIC( ToolTipManagerSingleton, privateInstance )
ToolTipManager *ToolTipManager::self()
{
return &privateInstance->self;
}
ToolTipManager::ToolTipManager(QObject* parent)
: QObject(parent),
d(new ToolTipManagerPrivate)
{
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeUpdated()));
themeUpdated();
d->showTimer = new QTimer(this);
d->showTimer->setSingleShot(true);
d->hideTimer = new QTimer(this);
d->hideTimer->setSingleShot(true);
connect(d->showTimer, SIGNAL(timeout()), SLOT(showToolTip()));
connect(d->hideTimer, SIGNAL(timeout()), SLOT(resetShownState()));
}
ToolTipManager::~ToolTipManager()
{
if (d) delete d;
}
void ToolTipManager::showToolTip(QGraphicsWidget *widget)
{
ToolTip * tooltip = d->tooltips.value(widget);
if (tooltip) {
if (d->currentWidget) {
hideToolTip(d->currentWidget);
}
d->hideTimer->stop();
d->delayedHide = false;
d->showTimer->stop();
d->currentWidget = widget;
if (d->isShown) {
// small delay to prevent unnecessary showing when the mouse is moving quickly across items
// which can be too much for less powerful CPUs to keep up with
d->showTimer->start(200);
} else {
d->showTimer->start(500);
}
}
}
bool ToolTipManager::isWidgetToolTipDisplayed(QGraphicsWidget *widget)
{
ToolTip * tooltip = d->tooltips.value(widget);
if (tooltip) {
return tooltip->isVisible();
}
else {
return false;
}
}
void ToolTipManager::delayedHideToolTip()
{
d->showTimer->stop(); // stop the timer to show the tooltip
d->delayedHide = true;
d->hideTimer->start(250);
}
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();
}
}
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());
//connect to object destruction
connect(widget,SIGNAL(destroyed(QObject *)),this,SLOT(onWidgetDestroyed(QObject *)));
}
}
void ToolTipManager::unregisterWidget(QGraphicsWidget *widget)
{
if (d->tooltips.contains(widget)) {
ToolTip * tooltip = d->tooltips.take(widget);
if (tooltip) {
delete tooltip;
}
}
}
void ToolTipManager::setWidgetToolTipContent(QGraphicsWidget *widget,const ToolTipContent &data)
{
if (!d->tooltips.contains(widget)) {
return;
}
else {
ToolTip * tooltip = d->tooltips.value(widget);
tooltip->setContent(data);
tooltip->updateTheme();
}
}
bool ToolTipManager::widgetHasToolTip(QGraphicsWidget *widget)
{
return d->tooltips.contains(widget);
}
void ToolTipManager::themeUpdated()
{
QMapIterator<QGraphicsWidget*, ToolTip *> iterator(d->tooltips);
while (iterator.hasNext()) {
iterator.next();
iterator.value()->updateTheme();
}
}
void ToolTipManager::onWidgetDestroyed(QObject * object)
{
if (object) {
QMapIterator<QGraphicsWidget*, ToolTip *> iterator(d->tooltips);
while (iterator.hasNext()) {
iterator.next();
if (iterator.key() == object) {
ToolTip * tooltip = iterator.value();
d->tooltips.remove(iterator.key());
d->showTimer->stop(); // stop the timer to show the tooltip
d->delayedHide = false;
d->currentWidget = 0;
tooltip->hide();
delete tooltip;
}
}
}
}
void ToolTipManagerPrivate::resetShownState()
{
if (currentWidget) {
ToolTip * tooltip = tooltips.value(currentWidget);
if ((tooltip && !tooltip->isVisible()) || delayedHide) {
//One might have moused out and back in again
delayedHide = false;
isShown = false;
tooltip->hide();
currentWidget = 0;
}
}
}
void ToolTipManagerPrivate::showToolTip()
{
if (!currentWidget) {
return;
}
ToolTip * tooltip = tooltips.value(currentWidget);
if (tooltip) {
tooltip->prepareShowing();
tooltip->move(ToolTipManager::popupPosition(currentWidget,tooltip->size()));
isShown = true; //ToolTip is visible
}
}
QPoint ToolTipManager::popupPosition(const QGraphicsItem * item, const QSize &s)
{
const Plasma::Applet * applet = dynamic_cast<const Applet *>(item);
if (!applet) {
const QGraphicsItem * currentItem = item->parentItem();
while(currentItem->parentItem() && !dynamic_cast<const Applet *>(currentItem))
{
currentItem=currentItem->parentItem();
}
applet = dynamic_cast<const Applet *>(currentItem);
if (!applet) return QPoint(0,0);
}
QGraphicsView *v = applet->view();
Q_ASSERT(v);
QPoint pos = v->mapFromScene(item->scenePos());
pos = v->mapToGlobal(pos);
//kDebug() << "==> position is" << scenePos() << v->mapFromScene(scenePos()) << pos;
Plasma::View *pv = dynamic_cast<Plasma::View *>(v);
Plasma::Location loc = Floating;
if (pv) {
loc = pv->containment()->location();
}
switch (loc) {
case BottomEdge:
pos = QPoint(pos.x(), pos.y() - s.height());
break;
case TopEdge:
pos = QPoint(pos.x(), pos.y() + (int)item->boundingRect().size().height());
break;
case LeftEdge:
pos = QPoint(pos.x() + (int)item->boundingRect().size().width(), pos.y());
break;
case RightEdge:
pos = QPoint(pos.x() - s.width(), pos.y());
break;
default:
if (pos.y() - s.height() > 0) {
pos = QPoint(pos.x(), pos.y() - s.height());
} else {
pos = QPoint(pos.x(), pos.y() + (int)item->boundingRect().size().height());
}
}
//are we out of screen?
QRect screenRect = QApplication::desktop()->screenGeometry(pv ? pv->containment()->screen() : -1);
//kDebug() << "==> rect for" << (pv ? pv->containment()->screen() : -1) << "is" << screenRect;
if (pos.rx() + s.width() > screenRect.right()) {
pos.rx() -= ((pos.rx() + s.width()) - screenRect.right());
}
if (pos.ry() + s.height() > screenRect.bottom()) {
pos.ry() -= ((pos.ry() + s.height()) - screenRect.bottom());
}
pos.rx() = qMax(0, pos.rx());
return pos;
}
}
#include "tooltipmanager.moc"