plasma-framework/extenderitem.cpp
Rob Scheepmaker dcaf4a4b8a And finally we can drag even the last ExtenderItem from PopupApplet without stuff
breaking all around, and some random crashes are avoided too, all by making the
Dialog in PopupApplet no longer of the type Qt::Popup and installing an event filter
to still hide the dialog when you click somewhere else on your screen.


svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=857095
2008-09-04 17:09:34 +00:00

872 lines
28 KiB
C++

/***************************************************************************
* Copyright 2008 by Rob Scheepmaker <r.scheepmaker@student.utwente.nl> *
* *
* 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 "extenderitem.h"
#include <QApplication>
#include <QAction>
#include <QGraphicsSceneResizeEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsLinearLayout>
#include <QLayout>
#include <QPainter>
#include <QTimer>
#include <KDebug>
#include <KIcon>
#include <KWindowSystem>
#include "applet.h"
#include "containment.h"
#include "corona.h"
#include "dialog.h"
#include "extender.h"
#include "panelsvg.h"
#include "theme.h"
#include "view.h"
#include "private/applet_p.h"
#include "private/extender_p.h"
namespace Plasma
{
class ExtenderItemPrivate
{
public:
ExtenderItemPrivate(ExtenderItem *extenderItem, Extender *hostExtender)
: q(extenderItem),
widget(0),
toplevel(0),
previousTargetExtender(0),
extender(hostExtender),
title(QString()),
sourceAppletId(hostExtender->d->applet->id()),
mousePressed(false),
expirationTimer(0)
{
}
~ExtenderItemPrivate()
{
delete toplevel;
}
/**
* @return a Rect containing the area of the detachable where the draghandle can be drawn.
*/
QRectF dragHandleRect()
{
qreal left, top, right, bottom;
dragger->getMargins(left, top, right, bottom);
QRectF rect(0, 0, q->size().width(),
dragger->elementSize("hint-preferred-icon-size").height() + top + bottom);
return rect;
}
QRectF titleRect()
{
qreal left, top, right, bottom;
dragger->getMargins(left, top, right, bottom);
return dragHandleRect().adjusted(left + collapseIcon->size().width() + 1, top,
-toolbox->size().width(), -bottom);
}
//XXX kinda duplicated from applethandle.
//returns true if the applet overlaps with a different view then the current one.
bool leaveCurrentView(const QRect &rect)
{
if ((q->sceneBoundingRect().left() < 0)) {
//always leaveCurrentView when the item is in a Plasma::Dialog which can easy be
//seen by checking if it is in topleft quadrant and it's not just there because it's
//being viewed by the toplevel view.
return true;
}
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
if (widget->geometry().intersects(rect) && widget->isVisible() && widget != toplevel) {
//is this widget a plasma view, a different view then our current one,
//AND not a dashboardview?
QGraphicsView *v = qobject_cast<QGraphicsView*>(widget);
QGraphicsView *currentV = 0;
if (hostApplet()) {
currentV = qobject_cast<QGraphicsView*>(hostApplet()->containment()->view());
}
if (v && v != currentV) {
return true;
}
}
}
return false;
}
QRect screenRect() {
return hostApplet()->containment()->view()
->mapFromScene(q->sceneBoundingRect()).boundingRect();
}
void toggleCollapse() {
q->setCollapsed(!q->isCollapsed());
}
void updateToolBox() {
if (toolbox && dragger && toolboxLayout) {
//clean the layout.
uint iconHeight = dragger->elementSize("hint-preferred-icon-size").height();
while (toolboxLayout->count()) {
QGraphicsLayoutItem *icon = toolboxLayout->itemAt(0);
QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(icon);
widget->deleteLater();
toolboxLayout->removeAt(0);
}
//add the actions that are actually set to visible.
foreach (QAction *action, actions) {
if (action->isVisible()) {
Icon *icon = new Icon(q);
icon->setAction(action);
QSizeF iconSize = icon->sizeFromIconSize(iconHeight);
icon->setMinimumSize(iconSize);
icon->setMaximumSize(iconSize);
toolboxLayout->addItem(icon);
}
}
toolboxLayout->updateGeometry();
qreal left, top, right, bottom;
dragger->getMargins(left, top, right, bottom);
//position the toolbox correctly.
QSizeF minimum = toolboxLayout->minimumSize();
toolbox->resize(minimum);
toolbox->setPos(q->size().width() - minimum.width(),
((dragger->size().height() + top + bottom)/2) -
(minimum.height()/2));
toolbox->update();
}
}
//TODO: something like this as static function in corona might be a good idea.
QPointF scenePosFromScreenPos(const QPoint &pos) const
{
//get the stacking order of the toplevel windows and remove the toplevel view that's
//only here while dragging, since we're not interested in finding that.
QList<WId> order = KWindowSystem::stackingOrder();
if (toplevel) {
order.removeOne(toplevel->winId());
}
QGraphicsView *found = 0;
foreach (QWidget *w, QApplication::topLevelWidgets()) {
QGraphicsView *v = 0;
//first check if we're over a Dialog.
Dialog *dialog = qobject_cast<Dialog*>(w);
if (dialog) {
if (dialog->isVisible() && dialog->geometry().contains(pos)) {
v = qobject_cast<QGraphicsView*>(dialog->layout()->itemAt(0)->widget());
if (v) {
return v->mapToScene(v->mapFromGlobal(pos));
}
}
} else {
v = qobject_cast<QGraphicsView *>(w);
}
//else check if it is a QGV:
if (v && w->isVisible() && w->geometry().contains(pos)) {
if (found && order.contains(found->winId())) {
if (order.indexOf(found->winId()) < order.indexOf(v->winId())) {
found = v;
}
} else {
found = v;
}
}
}
Q_ASSERT(found);
return found->mapToScene(found->mapFromGlobal(pos));
}
Applet *hostApplet() const
{
if (extender) {
return extender->d->applet;
} else {
return 0;
}
}
ExtenderItem *q;
QGraphicsWidget *widget;
QGraphicsWidget *toolbox;
QGraphicsLinearLayout *toolboxLayout;
QGraphicsView *toplevel;
Extender *previousTargetExtender;
Extender *extender;
Applet *sourceApplet;
KConfigGroup config;
PanelSvg *dragger;
PanelSvg *appletBackground;
Icon *collapseIcon;
QAction *returnAction;
QMap<QString, QAction*> actions;
QString title;
QString name;
uint sourceAppletId;
uint extenderItemId;
QPointF deltaScene;
QPoint mousePos;
bool mousePressed;
bool mouseOver;
QTimer *expirationTimer;
static uint s_maxExtenderItemId;
};
uint ExtenderItemPrivate::s_maxExtenderItemId = 0;
ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId)
: QGraphicsWidget(hostExtender),
d(new ExtenderItemPrivate(this, hostExtender))
{
Q_ASSERT(hostExtender);
//set the extenderId
if (extenderItemId) {
d->extenderItemId = extenderItemId;
ExtenderItemPrivate::s_maxExtenderItemId =
qMax(ExtenderItemPrivate::s_maxExtenderItemId, extenderItemId);
} else {
d->extenderItemId = ++ExtenderItemPrivate::s_maxExtenderItemId;
}
d->sourceApplet = hostExtender->d->applet;
//create items's configgroup
if (hostExtender->d->applet) {
KConfigGroup cg = hostExtender->d->applet->config("ExtenderItems");
KConfigGroup dg = KConfigGroup(&cg, QString::number(d->extenderItemId));
if (!dg.readEntry("sourceAppletId", 0)) {
//The item is new
dg.writeEntry("sourceAppletPluginName", hostExtender->d->applet->pluginName());
dg.writeEntry("sourceAppletId", hostExtender->d->applet->id());
d->sourceAppletId = hostExtender->d->applet->id();
d->sourceApplet = hostExtender->d->applet;
} else {
//The item allready exists.
d->name = dg.readEntry("extenderItemName", "");
d->sourceAppletId = dg.readEntry("sourceAppletId", 0);
//Set the sourceapplet.
Corona *corona = hostExtender->d->applet->containment()->corona();
foreach (Containment *containment, corona->containments()) {
foreach (Applet *applet, containment->applets()) {
if (applet->id() == d->sourceAppletId &&
applet->pluginName() == dg.readEntry("sourceAppletPluginName", "")) {
d->sourceApplet = applet;
}
}
}
}
}
//create the dragger and standard applet background.
d->dragger = new PanelSvg(this);
d->dragger->setImagePath("widgets/dragger");
d->appletBackground = new PanelSvg(this);
d->appletBackground->setImagePath("widgets/background");
d->appletBackground->setEnabledBorders(0);
//create the toolbox.
d->toolbox = new QGraphicsWidget(this);
d->toolboxLayout = new QGraphicsLinearLayout(d->toolbox);
d->toolbox->setLayout(d->toolboxLayout);
//allow the theme to set the size of the icon.
//TODO: discuss with others to determine details of the theming implementation. I don't really
//like this approach, but it works...
QSizeF iconSize = d->dragger->elementSize("hint-preferred-icon-size");
qreal left, top, right, bottom;
d->dragger->getMargins(left, top, right, bottom);
//create the collapse/applet icon.
d->collapseIcon = new Icon(KIcon(hostExtender->d->applet->icon()), "", this);
d->collapseIcon->resize(d->collapseIcon->sizeFromIconSize(iconSize.height()));
d->collapseIcon->setPos(left, (d->dragger->size().height() + top + bottom)/2 -
d->collapseIcon->size().height()/2);
connect(d->collapseIcon, SIGNAL(clicked()), this, SLOT(toggleCollapse()));
//Add the return to source action.
d->returnAction = new QAction(this);
d->returnAction->setIcon(KIcon("returntosource"));
d->returnAction->setEnabled(true);
d->returnAction->setVisible(true);
connect(d->returnAction, SIGNAL(triggered()), this, SLOT(moveBackToSource()));
addAction("returntosource", d->returnAction);
//set the extender we want to move to.
setExtender(hostExtender);
setCollapsed(false); //sets the size hints.
setAcceptHoverEvents(true);
d->updateToolBox();
updateGeometry();
}
ExtenderItem::~ExtenderItem()
{
delete d;
}
KConfigGroup ExtenderItem::config() const
{
KConfigGroup cg = extender()->d->applet->config("ExtenderItems");
return KConfigGroup(&cg, QString::number(d->extenderItemId));
}
void ExtenderItem::setTitle(const QString &title)
{
d->title = title;
update();
}
QString ExtenderItem::title() const
{
return d->title;
}
void ExtenderItem::setName(const QString &name)
{
d->name = name;
config().writeEntry("extenderItemName", name);
}
QString ExtenderItem::name() const
{
return d->name;
}
void ExtenderItem::setWidget(QGraphicsWidget *widget)
{
widget->setParentItem(this);
widget->setPos(QPointF(0, d->dragHandleRect().height()));
d->widget = widget;
setCollapsed(isCollapsed()); //updates the size hints.
}
QGraphicsWidget *ExtenderItem::widget() const
{
return d->widget;
}
void ExtenderItem::setIcon(const QIcon &icon)
{
d->collapseIcon->setIcon(icon);
}
void ExtenderItem::setIcon(const QString &icon)
{
d->collapseIcon->setIcon(icon);
}
QIcon ExtenderItem::icon() const
{
return d->collapseIcon->icon();
}
void ExtenderItem::setExtender(Extender *extender, const QPointF &pos)
{
//We are switching extender...
//first remove this item from the old extender.
if (d->extender) {
d->extender->d->removeExtenderItem(this);
emit d->extender->itemDetached(this);
}
//move the configuration.
if (d->hostApplet() && (extender != d->extender)) {
KConfigGroup c = extender->d->applet->config("ExtenderItems");
config().reparent(&c);
}
d->extender = extender;
//change parent.
setParentItem(extender);
extender->d->addExtenderItem(this, pos);
//cancel the timer.
if (d->expirationTimer && isDetached()) {
d->expirationTimer->stop();
delete d->expirationTimer;
d->expirationTimer = 0;
}
}
Extender *ExtenderItem::extender() const
{
return d->extender;
}
bool ExtenderItem::isCollapsed() const
{
if (!d->widget) {
return true;
} else {
return !d->widget->isVisible();
}
}
void ExtenderItem::setAutoExpireDelay(uint time)
{
if (!time) {
if (d->expirationTimer) {
d->expirationTimer->stop();
delete d->expirationTimer;
d->expirationTimer = 0;
}
return;
}
if (!isDetached()) {
if (!d->expirationTimer) {
d->expirationTimer = new QTimer(this);
connect(d->expirationTimer, SIGNAL(timeout()), this, SLOT(destroy()));
}
d->expirationTimer->stop();
d->expirationTimer->setSingleShot(true);
d->expirationTimer->setInterval(time);
d->expirationTimer->start();
}
}
bool ExtenderItem::autoExpireDelay() const
{
if (d->expirationTimer) {
return d->expirationTimer->interval();
} else {
return 0;
}
}
bool ExtenderItem::isDetached() const
{
if (d->hostApplet()) {
return (sourceAppletId() != d->hostApplet()->id());
} else {
return false;
}
}
void ExtenderItem::addAction(const QString &name, QAction *action)
{
Q_ASSERT(action);
d->actions[name] = action;
connect(action, SIGNAL(changed()), this, SLOT(updateToolBox()));
d->updateToolBox();
}
QAction *ExtenderItem::action(const QString &name) const
{
if (d->actions.contains(name)) {
return d->actions[name];
} else {
return 0;
}
}
uint ExtenderItem::sourceAppletId() const
{
return d->sourceAppletId;
}
void ExtenderItem::destroy()
{
d->hostApplet()->config("ExtenderItems").deleteGroup(QString::number(d->extenderItemId));
if (d->extender) {
d->extender->d->removeExtenderItem(this);
}
deleteLater();
}
void ExtenderItem::setCollapsed(bool collapsed)
{
if (!d->widget) {
setPreferredSize(QSizeF(200, d->dragHandleRect().height()));
setMinimumSize(QSizeF(0, d->dragHandleRect().height()));
//FIXME: wasn't there some sort of QWIDGETMAXSIZE thingy?
setMaximumSize(QSizeF(1000, d->dragHandleRect().height()));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
updateGeometry();
return;
}
qreal left, top, right, bottom;
d->dragger->getMargins(left, top, right, bottom);
d->widget->setVisible(!collapsed);
if (collapsed) {
setPreferredSize(QSizeF(d->widget->preferredWidth(), d->dragHandleRect().height()));
setMinimumSize(QSizeF(d->widget->minimumWidth(), d->dragHandleRect().height()));
setMaximumSize(QSizeF(d->widget->maximumWidth(), d->dragHandleRect().height()));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
//FIXME: why don't tooltips work?
//d->collapseIcon->setToolTip(i18n("Expand this widget"));
} else {
setPreferredSize(QSizeF(d->widget->preferredWidth(),
d->widget->preferredHeight() + d->dragHandleRect().height()));
setMinimumSize( QSizeF(d->widget->minimumWidth(),
d->widget->minimumHeight() + d->dragHandleRect().height()));
setMaximumSize( QSizeF(d->widget->maximumWidth(),
d->widget->maximumHeight() + d->dragHandleRect().height()));
setSizePolicy(d->widget->sizePolicy());
//d->collapseIcon->setToolTip(i18n("Collapse this widget"));
}
if (d->extender) {
d->extender->d->adjustSizeHints();
}
}
void ExtenderItem::moveBackToSource()
{
if (!d->sourceApplet) {
return;
}
setExtender(d->sourceApplet->d->extender);
}
void ExtenderItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setRenderHint(QPainter::TextAntialiasing, true);
painter->setRenderHint(QPainter::Antialiasing, true);
if (d->mousePressed) {
//only paint the standard applet background when dragging the thing around.
d->appletBackground->paintPanel(painter); //, QRectF(QPointF(0,0), size()));
}
d->dragger->paintPanel(painter); //, d->dragHandleRect());
//draw the title.
Plasma::Theme *theme = Plasma::Theme::defaultTheme();
QFont font = theme->font(Plasma::Theme::DefaultFont);
font.setPointSize(font.pointSize() - 2);
//XXX: duplicated from windowtaskitem.
//TODO: hmm, create something generic for this... there's probably more stuff that wants to have
//this functionality
QRectF rect = QRectF(d->titleRect().width() - 30, 0, 30, d->titleRect().height());
QPixmap pixmap(d->titleRect().size().toSize());
pixmap.fill(Qt::transparent);
QPainter p(&pixmap);
p.setPen(theme->color(Plasma::Theme::TextColor));
p.setFont(font);
p.drawText(QRectF(QPointF(0, 0), d->titleRect().size()),
Qt::TextSingleLine | Qt::AlignVCenter | Qt::AlignLeft,
d->title);
// Create the alpha gradient for the fade out effect
QLinearGradient alphaGradient(0, 0, 1, 0);
alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
//TODO: correct handling of right to left text.
alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(rect, alphaGradient);
p.end();
painter->drawPixmap(d->titleRect().topLeft(), pixmap);
}
void ExtenderItem::resizeEvent(QGraphicsSceneResizeEvent *event)
{
qreal left, top, right, bottom;
d->dragger->getMargins(left, top, right, bottom);
//resize the dragger
QSizeF newDraggerSize = event->newSize();
newDraggerSize.setHeight(d->dragger->elementSize("hint-preferred-icon-size").height() + top + bottom);
d->dragger->resizePanel(newDraggerSize);
//resize the applet background
d->appletBackground->resizePanel(event->newSize());
//resize the widget
if (d->widget) {
QSizeF newWidgetSize = event->newSize();
newWidgetSize.setHeight(newWidgetSize.height() - d->dragger->size().height() - top - bottom);
d->widget->resize(newWidgetSize);
}
d->updateToolBox();
}
void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
kDebug() << "the mouse pressed yeah yeah yeah!";
if (!(d->dragHandleRect().contains(event->pos()))) {
return;
}
d->mousePressed = true;
d->deltaScene = pos();
Applet *parentApplet = d->hostApplet();
d->mousePos = event->pos().toPoint();
parentApplet->raise();
setZValue(parentApplet->zValue());
if (d->extender) {
//d->extender->itemHoverEnterEvent(this);
//d->extender->itemHoverMoveEvent(this, d->extender->mapFromScene(event->scenePos()));
d->extender->itemHoverMoveEvent(this, d->extender->mapFromScene(d->scenePosFromScreenPos(event->screenPos())));
}
d->extender->d->removeExtenderItem(this);
//call the move event, since that spawns a toplevel view when this extender item is in a
//Plasma::Dialog, which is very essential since else the dialog will close before having been
//able to receive any move events.
//mouseMoveEvent(event);
QApplication::setOverrideCursor(Qt::ClosedHandCursor);
}
void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (!d->mousePressed) {
return;
}
//keep track of the movement in scene coordinates. we use this to set the position of the
//applet when remaining in the current view.
d->deltaScene += event->scenePos() - event->lastScenePos();
//set a rect in screencoordinates so we can check when we need to move to a toplevel
//view.
QRect screenRect = QRect();
screenRect.setTopLeft(event->screenPos() - d->mousePos);
screenRect.setSize(d->screenRect().size());
Corona *corona = d->hostApplet()->containment()->corona();
if (d->leaveCurrentView(screenRect)) {
//we're moving the applet to a toplevel view, so place it somewhere out of sight
//first: in the topleft quadrant.
if (!d->toplevel) {
//XXX duplication from applethandle
//create a toplevel view and aim it at the applet.
d->toplevel = new QGraphicsView(corona, 0);
corona->addOffscreenWidget(this);
update();
d->toplevel->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint);
d->toplevel->setFrameShape(QFrame::NoFrame);
d->toplevel->resize(screenRect.size());
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->centerOn(this);
//We might have to scale the view, because we might be zoomed out.
qreal scale = screenRect.width() / boundingRect().width();
d->toplevel->scale(scale, scale);
d->toplevel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->toplevel->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->toplevel->update();
d->toplevel->show();
}
//move the toplevel view.
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->setGeometry(screenRect);
} else {
corona->removeOffscreenWidget(this);
setParentItem(d->hostApplet());
setPos(d->deltaScene);
//remove the toplevel view.
if (d->toplevel) {
delete d->toplevel;
d->toplevel = 0;
}
}
//let's insert spacers in applets we're hovering over for some usefull visual feedback.
//check which view we're hovering over and use that information to get the mouse
//position in scene coordinates (event->scenePos won't work, since it doesn't take in
//consideration that you're leaving the current view).
QPointF mousePos = d->scenePosFromScreenPos(event->screenPos());
//find the extender we're hovering over.
Extender *targetExtender = 0;
foreach (Containment *containment, corona->containments()) {
foreach (Applet *applet, containment->applets()) {
if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos)
|| applet->extender()->sceneBoundingRect().contains(mousePos))) {
targetExtender = applet->extender();
}
}
}
//remove any previous spacers.
if (targetExtender != d->previousTargetExtender) {
if (d->previousTargetExtender) {
d->previousTargetExtender->itemHoverLeaveEvent(this);
}
d->previousTargetExtender = targetExtender;
if (targetExtender) {
targetExtender->itemHoverEnterEvent(this);
}
}
//insert a spacer if the applet accepts detachables.
if (targetExtender) {
if (targetExtender->sceneBoundingRect().contains(mousePos)) {
targetExtender->itemHoverMoveEvent(this, targetExtender->mapFromScene(mousePos));
}
}
}
void ExtenderItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
if (d->titleRect().contains(event->pos())) {
if (!d->mouseOver) {
QApplication::setOverrideCursor(Qt::OpenHandCursor);
d->mouseOver = true;
}
} else {
if (d->mouseOver) {
QApplication::restoreOverrideCursor();
d->mouseOver = false;
}
}
}
void ExtenderItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
if (d->mouseOver) {
QApplication::restoreOverrideCursor();
d->mouseOver = false;
}
}
void ExtenderItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (d->mousePressed) {
d->mousePressed = false;
//remove the toplevel view
if (d->toplevel) {
delete d->toplevel;
d->toplevel = 0;
}
//let's insert spacers in applets we're hovering over for some usefull visual feedback.
//check which view we're hovering over and use that information to get the mouse
//position in scene coordinates (event->scenePos won't work, since it doesn't take in
//consideration that you're leaving the current view).
QPointF mousePos = d->scenePosFromScreenPos(event->screenPos());
//find the extender we're hovering over.
Extender *targetExtender = 0;
Corona *corona = qobject_cast<Corona*>(scene());
corona->removeOffscreenWidget(this);
foreach (Containment *containment, corona->containments()) {
foreach (Applet *applet, containment->applets()) {
if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos)
|| applet->extender()->sceneBoundingRect().contains(mousePos))) {
targetExtender = applet->extender();
}
}
}
//are we hovering over an applet that accepts extender items?
if (targetExtender) {
if (targetExtender->sceneBoundingRect().contains(mousePos)) {
setExtender(targetExtender, targetExtender->mapFromScene(mousePos));
} else {
setExtender(targetExtender);
}
} else {
//apparently, it is not, so instantiate a new ExtenderApplet.
//TODO: maybe we alow the user to choose a default extenderapplet.
kDebug() << "Instantiate a new ExtenderApplet";
mousePos = d->scenePosFromScreenPos(event->screenPos() - d->mousePos);
foreach (Containment *containment, corona->containments()) {
if (containment->sceneBoundingRect().contains(mousePos)) {
Applet *applet = containment->addApplet("extenderapplet",
QVariantList(),
QRectF(mousePos, size()));
setExtender(applet->extender());
}
}
}
QApplication::restoreOverrideCursor();
}
}
} // namespace Plasma
#include "extenderitem.moc"