enable dragging from desktop to panel
note: there's no visual feedback before you release the mouse button, and there's no way to drag back to the desktop. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=770333
This commit is contained in:
parent
29215641ef
commit
be64c5939d
@ -19,6 +19,7 @@
|
||||
|
||||
#include "applethandle_p.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QtGui/QGraphicsSceneMouseEvent>
|
||||
#include <QtGui/QLinearGradient>
|
||||
#include <QtGui/QPainter>
|
||||
@ -31,6 +32,7 @@
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
|
||||
#include "plasma/view.h"
|
||||
#include "applet.h"
|
||||
#include "containment.h"
|
||||
#include "corona.h"
|
||||
@ -328,6 +330,27 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
Phase::self()->animateItem(m_applet, Phase::Disappear);
|
||||
}
|
||||
break;
|
||||
case MoveButton: {
|
||||
//find out if we were dropped on a panel or something
|
||||
QWidget *w = QApplication::topLevelAt(event->screenPos());
|
||||
kDebug() << "move to widget" << w;
|
||||
if (w) {
|
||||
Plasma::View *v = qobject_cast<Plasma::View *>(w);
|
||||
if (v) {
|
||||
Containment *c = v->containment();
|
||||
//XXX the dashboard view won't give us a containment. if it did, this could
|
||||
//break shit.
|
||||
if (c && c != m_containment) {
|
||||
//we actually have been dropped on another containment, so move there
|
||||
//we have a screenpos, we need a scenepos
|
||||
//FIXME how reliable is this transform?
|
||||
QPoint pos = v->mapFromGlobal(event->screenPos());
|
||||
switchContainment(c, v->mapToScene(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -378,17 +401,9 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
if (containments[i]->sceneBoundingRect().contains(event->scenePos())) {
|
||||
// add the applet to the new containment
|
||||
// and take it from the old one
|
||||
QPointF scenePosition = scenePos();
|
||||
//kDebug() << "moving to other containment with position" << pos() << event->scenePos();
|
||||
//kDebug() << "position before reparenting" << pos() << scenePos();
|
||||
m_containment = containments[i];
|
||||
//m_containment->addChild(m_applet);
|
||||
//setParentItem(containments[i]);
|
||||
m_containment->addApplet(m_applet);
|
||||
setParentItem(m_containment);
|
||||
m_applet->setParentItem(this);
|
||||
setPos(m_containment->mapFromScene(scenePosition));
|
||||
update();
|
||||
switchContainment(containments[i], scenePos());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -493,6 +508,31 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
//pos relative to scene
|
||||
void AppletHandle::switchContainment(Containment *containment, const QPointF &pos)
|
||||
{
|
||||
Applet *applet=m_applet;
|
||||
switch (containment->containmentType()) {
|
||||
case Containment::PanelContainment:
|
||||
kDebug() << "panel";
|
||||
//we need to fully disassociate the applet and handle, then kill the handle
|
||||
forceDisappear(); //takes care of event filter and killing handle
|
||||
m_applet=0; //make sure we don't try to act on the applet again
|
||||
applet->disconnect(this); //make sure the applet doesn't tell us to do anything
|
||||
containment->addApplet(applet, containment->mapFromScene(pos));
|
||||
break;
|
||||
default: //FIXME assuming everything else behaves like desktop
|
||||
kDebug() << "desktop";
|
||||
m_containment = containment;
|
||||
containment->addApplet(m_applet);
|
||||
setParentItem(containment);
|
||||
m_applet->setParentItem(this);
|
||||
setPos(containment->mapFromScene(pos));
|
||||
//setPos(pos);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
QVariant AppletHandle::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
if (change == ItemPositionHasChanged && m_applet) {
|
||||
|
@ -74,6 +74,12 @@ class AppletHandle : public QObject, public QGraphicsItem
|
||||
void calculateSize();
|
||||
ButtonType mapToButton(const QPointF &point) const;
|
||||
void forceDisappear();
|
||||
/**
|
||||
* move our applet to another containment
|
||||
* @param containment the containment to move to
|
||||
* @param pos the (scene-relative) position to place it at
|
||||
*/
|
||||
void switchContainment(Containment *containment, const QPointF &pos);
|
||||
|
||||
QRectF m_rect;
|
||||
ButtonType m_pressedButton;
|
||||
|
185
containment.cpp
185
containment.cpp
@ -404,63 +404,9 @@ Applet* Containment::addApplet(const QString& name, const QVariantList& args, ui
|
||||
applet = new Applet;
|
||||
}
|
||||
|
||||
switch (containmentType()) {
|
||||
case PanelContainment:
|
||||
{
|
||||
//panels don't want backgrounds, which is important when setting geometry
|
||||
applet->setDrawStandardBackground(false);
|
||||
|
||||
// Calculate where the user wants the applet to go before adding it
|
||||
int index = -1;
|
||||
QPointF position = appletGeometry.topLeft();
|
||||
BoxLayout *l = dynamic_cast<BoxLayout *>(layout());
|
||||
if (!delayInit && l && position != QPointF(-1, -1)) {
|
||||
foreach (Applet *existingApplet, d->applets) {
|
||||
if (formFactor() == Horizontal) {
|
||||
qreal middle = (existingApplet->geometry().left() +
|
||||
existingApplet->geometry().right()) / 2.0;
|
||||
// Applets are checked in order so there is no need to check
|
||||
// if the position is equal to or greater than the applet's
|
||||
// leftmost point. This also allows for dropping in the gap
|
||||
// between applets.
|
||||
if (position.x() < middle) {
|
||||
index = l->indexOf(existingApplet);
|
||||
break;
|
||||
} else if (position.x() <= existingApplet->geometry().right()) {
|
||||
index = l->indexOf(existingApplet) + 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
qreal middle = (existingApplet->geometry().top() +
|
||||
existingApplet->geometry().bottom()) / 2.0;
|
||||
if (position.y() < middle) {
|
||||
index = l->indexOf(existingApplet);
|
||||
break;
|
||||
} else if (position.y() <= existingApplet->geometry().bottom()) {
|
||||
index = l->indexOf(existingApplet) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addApplet(applet);
|
||||
prepareApplet(applet, delayInit);
|
||||
|
||||
// Reposition the applet after adding has been done
|
||||
if (index != -1) {
|
||||
l->insertItem(index, l->takeAt(l->indexOf(applet)));
|
||||
d->applets.removeAll(applet);
|
||||
d->applets.insert(index, applet);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
addApplet(applet);
|
||||
prepareApplet(applet, delayInit);
|
||||
addApplet(applet, appletGeometry.topLeft(), delayInit);
|
||||
|
||||
if (containmentType() != PanelContainment) {
|
||||
//kDebug() << "adding applet" << applet->name() << "with a default geometry of" << appletGeometry << appletGeometry.isValid();
|
||||
if (appletGeometry.isValid()) {
|
||||
applet->setGeometry(appletGeometry);
|
||||
@ -484,6 +430,106 @@ Applet* Containment::addApplet(const QString& name, const QVariantList& args, ui
|
||||
return applet;
|
||||
}
|
||||
|
||||
//pos must be relative to the containment already. use mapfromscene.
|
||||
//what we're trying to do here for panels is make the applet go to the requested position,
|
||||
//or somewhere close to it, and get integrated properly into the containment as if it were created
|
||||
//there.
|
||||
void Containment::addApplet(Applet *applet, const QPointF &pos, bool dontInit)
|
||||
{
|
||||
if (!applet) {
|
||||
kDebug() << "adding null applet!?!";
|
||||
return;
|
||||
}
|
||||
|
||||
Containment *currentContainment = applet->containment();
|
||||
int index = -1;
|
||||
|
||||
if (containmentType() == PanelContainment) {
|
||||
//panels don't want backgrounds, which is important when setting geometry
|
||||
applet->setDrawStandardBackground(false);
|
||||
|
||||
// Calculate where the user wants the applet to go before adding it
|
||||
//so long as this isn't a new applet with a delayed init
|
||||
if (! dontInit || (currentContainment && currentContainment != this)) {
|
||||
index = indexAt(pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentContainment && currentContainment != this) {
|
||||
applet->removeSceneEventFilter(currentContainment);
|
||||
KConfigGroup oldConfig = applet->config();
|
||||
applet->resetConfigurationObject();
|
||||
currentContainment->d->applets.removeAll(applet);
|
||||
addChild(applet);
|
||||
|
||||
// now move the old config to the new location
|
||||
KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
|
||||
oldConfig.reparent(&c);
|
||||
} else {
|
||||
addChild(applet);
|
||||
}
|
||||
|
||||
d->applets << applet;
|
||||
|
||||
connect(applet, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(appletDestroyed(QObject*)));
|
||||
|
||||
if (containmentType() == PanelContainment) {
|
||||
// Reposition the applet after adding has been done
|
||||
if (index != -1) {
|
||||
BoxLayout *l = dynamic_cast<BoxLayout *>(layout());
|
||||
l->insertItem(index, l->takeAt(l->indexOf(applet)));
|
||||
d->applets.removeAll(applet);
|
||||
d->applets.insert(index, applet);
|
||||
}
|
||||
} else {
|
||||
//FIXME if it came from a panel its bg was disabled
|
||||
//maybe we should expect the applet to handle that on a constraint update?
|
||||
|
||||
//should we really do this? hell, do we have any business playing with the geometry of
|
||||
//non-panel applets at all?
|
||||
if (pos != QPointF(-1, -1)) {
|
||||
applet->setPos(pos);
|
||||
}
|
||||
}
|
||||
prepareApplet(applet, dontInit); //must at least flush constraints
|
||||
}
|
||||
|
||||
//containment-relative pos... right?
|
||||
int Containment::indexAt(const QPointF &pos) const
|
||||
{
|
||||
if (pos == QPointF(-1, -1)) {
|
||||
return -1;
|
||||
}
|
||||
BoxLayout *l = dynamic_cast<BoxLayout *>(layout());
|
||||
if (l) {
|
||||
foreach (Applet *existingApplet, d->applets) {
|
||||
if (formFactor() == Horizontal) {
|
||||
qreal middle = (existingApplet->geometry().left() +
|
||||
existingApplet->geometry().right()) / 2.0;
|
||||
// Applets are checked in order so there is no need to check
|
||||
// if the position is equal to or greater than the applet's
|
||||
// leftmost point. This also allows for dropping in the gap
|
||||
// between applets.
|
||||
if (pos.x() < middle) {
|
||||
return l->indexOf(existingApplet);
|
||||
} else if (pos.x() <= existingApplet->geometry().right()) {
|
||||
return l->indexOf(existingApplet) + 1;
|
||||
}
|
||||
} else {
|
||||
qreal middle = (existingApplet->geometry().top() +
|
||||
existingApplet->geometry().bottom()) / 2.0;
|
||||
if (pos.y() < middle) {
|
||||
return l->indexOf(existingApplet);
|
||||
} else if (pos.y() <= existingApplet->geometry().bottom()) {
|
||||
return l->indexOf(existingApplet) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Containment::prepareApplet(Applet *applet, bool delayInit)
|
||||
{
|
||||
if (delayInit) {
|
||||
@ -549,33 +595,6 @@ bool Containment::regionIsEmpty(const QRectF ®ion, Applet *ignoredApplet) con
|
||||
return true;
|
||||
}
|
||||
|
||||
void Containment::addApplet(Applet *applet)
|
||||
{
|
||||
Containment *currentContainment = applet->containment();
|
||||
if (currentContainment && currentContainment != this) {
|
||||
applet->removeSceneEventFilter(currentContainment);
|
||||
KConfigGroup oldConfig = applet->config();
|
||||
applet->resetConfigurationObject();
|
||||
currentContainment->d->applets.removeAll(applet);
|
||||
addChild(applet);
|
||||
|
||||
// now move the old config to the new location
|
||||
KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
|
||||
oldConfig.reparent(&c);
|
||||
} else {
|
||||
addChild(applet);
|
||||
}
|
||||
|
||||
d->applets << applet;
|
||||
|
||||
if (currentContainment) {
|
||||
applet->installSceneEventFilter(this);
|
||||
}
|
||||
|
||||
connect(applet, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(appletDestroyed(QObject*)));
|
||||
}
|
||||
|
||||
void Containment::appletDestroyed(QObject* object)
|
||||
{
|
||||
// we do a static_cast here since it really isn't an Applet by this
|
||||
|
@ -183,9 +183,17 @@ class PLASMA_EXPORT Containment : public Applet
|
||||
void clearApplets();
|
||||
|
||||
/**
|
||||
* add existing applet to this containment
|
||||
* add existing applet to this containment at pos
|
||||
* @param pos the containment-relative position
|
||||
* @param dontInit if true, init() will not be called on the applet
|
||||
*/
|
||||
void addApplet(Applet * applet);
|
||||
void addApplet(Applet *applet, const QPointF &pos = QPointF(-1, -1), bool dontInit = true);
|
||||
|
||||
/**
|
||||
* @return the index to insert an applet at if you want it near the point pos.
|
||||
* @param pos the containment-relative position
|
||||
*/
|
||||
virtual int indexAt(const QPointF &pos) const;
|
||||
|
||||
/**
|
||||
* Sets the physical screen this Containment is associated with.
|
||||
|
Loading…
Reference in New Issue
Block a user