Couple of improvements to applet drag&drop:
* Only move applet to toplevel window when overlapping other plasma views, ignoring other windows and such. * Drag & drop now works reasonably well when using multiple desktop containments ('activities'), both when zoomed in as when zoomed out. Only a couple of issues remaining. * Containment's addApplet function now cleans up the pointer to the applethandle in the preview containment, Avoiding some nasty crashes when moving applets between containments. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=809841
This commit is contained in:
parent
a91f242a50
commit
8b20aab3fb
@ -1311,8 +1311,8 @@ QRect Applet::screenRect() const
|
|||||||
bottomRight.setX(bottomRight.x() + size().width());
|
bottomRight.setX(bottomRight.x() + size().width());
|
||||||
bottomRight.setY(bottomRight.y() + size().height());
|
bottomRight.setY(bottomRight.y() + size().height());
|
||||||
|
|
||||||
QPoint tL = view()->mapToGlobal(containment()->view()->mapFromScene(pos()));
|
QPoint tL = containment()->view()->mapToGlobal(containment()->view()->mapFromScene(pos()));
|
||||||
QPoint bR = view()->mapToGlobal(containment()->view()->mapFromScene(bottomRight));
|
QPoint bR = containment()->view()->mapToGlobal(containment()->view()->mapFromScene(bottomRight));
|
||||||
kDebug() << "screenRect = " << QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y());
|
kDebug() << "screenRect = " << QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y());
|
||||||
|
|
||||||
return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
|
return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
|
||||||
|
103
applethandle.cpp
103
applethandle.cpp
@ -98,10 +98,6 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
|||||||
//will only update this after the handle is destroyed, and we
|
//will only update this after the handle is destroyed, and we
|
||||||
//will track changes to it in the mouseMoveEvent.
|
//will track changes to it in the mouseMoveEvent.
|
||||||
m_screenRect = m_applet->screenRect();
|
m_screenRect = m_applet->screenRect();
|
||||||
//add a small margin to the screenRect so, that when we check
|
|
||||||
//if we are over another view than the source view, we won't
|
|
||||||
//detect the top level view.
|
|
||||||
m_screenRect.adjust(-2, -2, 2, 2);
|
|
||||||
|
|
||||||
connect(m_hoverTimer, SIGNAL(timeout()), this, SLOT(fadeIn()));
|
connect(m_hoverTimer, SIGNAL(timeout()), this, SLOT(fadeIn()));
|
||||||
connect(m_applet, SIGNAL(destroyed(QObject*)), this, SLOT(appletDestroyed()));
|
connect(m_applet, SIGNAL(destroyed(QObject*)), this, SLOT(appletDestroyed()));
|
||||||
@ -109,6 +105,13 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
|||||||
setAcceptsHoverEvents(true);
|
setAcceptsHoverEvents(true);
|
||||||
m_hoverTimer->start();
|
m_hoverTimer->start();
|
||||||
|
|
||||||
|
//We got to be able to see the applet while dragging to to another containment,
|
||||||
|
//so we want a high zValue.
|
||||||
|
//TODO: restore applets original zValue before destroying the handle.
|
||||||
|
//FIXME: apparently this doesn't work: sometimes an applet still get's drawn behind
|
||||||
|
//the containment it's being dragged to, sometimes it doesn't.
|
||||||
|
m_zValue = m_applet->zValue();
|
||||||
|
m_applet->raise();
|
||||||
setZValue(m_applet->zValue());
|
setZValue(m_applet->zValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,12 +295,8 @@ void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
//set mousePos to the position in the applet, in screencoords, so it becomes easy
|
//set mousePos to the position in the applet, in screencoords, so it becomes easy
|
||||||
//to reposition the toplevel view to the correct position.
|
//to reposition the toplevel view to the correct position.
|
||||||
QPoint localpos = m_applet->containment()->view()
|
QPoint localpos = m_containment->view()->mapFromScene(m_applet->scenePos());
|
||||||
->mapFromScene(m_applet->pos() + m_pos);
|
m_mousePos = event->screenPos() - m_containment->view()->mapToGlobal(localpos);
|
||||||
m_mousePos = event->screenPos() - m_applet->containment()->view()
|
|
||||||
->mapToGlobal(localpos);
|
|
||||||
//set the starting position
|
|
||||||
m_pos = pos();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -305,21 +304,24 @@ void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
QGraphicsItem::mousePressEvent(event);
|
QGraphicsItem::mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppletHandle::goTopLevel(const QPoint & pos) {
|
bool AppletHandle::leaveCurrentView(const QRect &rect) const
|
||||||
Plasma::View *v = Plasma::View::topLevelViewAt(pos);
|
{
|
||||||
if (v) {
|
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
|
||||||
Containment *c = v->containment();
|
if (widget->geometry().intersects(rect)) {
|
||||||
|
//is this widget a plasma view, a different view then our current one,
|
||||||
if (c && c != m_containment) {
|
//AND not a dashboardview?
|
||||||
return true;
|
Plasma::View *v = qobject_cast<Plasma::View *>(widget);
|
||||||
} else {
|
if (v && v != m_applet->containment()->view()
|
||||||
return false;
|
&& v != m_topview
|
||||||
|
&& v->containment() != m_containment) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
//kDebug() << "button pressed:" << m_pressedButton << ", fade pending?" << m_pendingFade;
|
//kDebug() << "button pressed:" << m_pressedButton << ", fade pending?" << m_pendingFade;
|
||||||
@ -384,9 +386,9 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//find out if we were dropped on a panel or something
|
//find out if we were dropped on a panel or something
|
||||||
if (goTopLevel(m_screenRect.center())) {
|
if (leaveCurrentView(m_screenRect)) {
|
||||||
Plasma::View *v = Plasma::View::topLevelViewAt(m_screenRect.center());
|
Plasma::View *v = Plasma::View::topLevelViewAt(m_screenRect.center());
|
||||||
if (v) {
|
if (v && v != m_containment->view()) {
|
||||||
Containment *c = v->containment();
|
Containment *c = v->containment();
|
||||||
//We decide where we've been dropped by looking at the center of the
|
//We decide where we've been dropped by looking at the center of the
|
||||||
//applet.
|
//applet.
|
||||||
@ -396,6 +398,30 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
//FIXME how reliable is this transform?
|
//FIXME how reliable is this transform?
|
||||||
switchContainment(c, v->mapToScene(pos));
|
switchContainment(c, v->mapToScene(pos));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// test for containment change
|
||||||
|
kDebug() << "testing for containment change, sceneBoundingRect = " << m_containment->sceneBoundingRect();
|
||||||
|
if (!m_containment->sceneBoundingRect().contains(m_applet->scenePos())) {
|
||||||
|
// see which containment it belongs to
|
||||||
|
Corona * corona = qobject_cast<Corona*>(scene());
|
||||||
|
if (corona) {
|
||||||
|
QList<Containment*> containments = corona->containments();
|
||||||
|
for (int i = 0; i < containments.size(); ++i) {
|
||||||
|
QPointF pos;
|
||||||
|
pos = containments[i]->view()->mapToScene(containments[i]->view()
|
||||||
|
->mapFromGlobal(m_screenRect.topLeft()));
|
||||||
|
|
||||||
|
if (containments[i]->sceneBoundingRect().contains(pos)) {
|
||||||
|
//kDebug() << "new containment = " << containments[i];
|
||||||
|
kDebug() << "rect = " << containments[i]->sceneBoundingRect();
|
||||||
|
// add the applet to the new containment and take it from the old one
|
||||||
|
kDebug() << "moving to other containment with position" << pos;;
|
||||||
|
switchContainment(containments[i], pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -445,17 +471,10 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
m_screenRect = QRect(event->screenPos() - m_mousePos,
|
m_screenRect = QRect(event->screenPos() - m_mousePos,
|
||||||
m_applet->screenRect().size());
|
m_applet->screenRect().size());
|
||||||
|
|
||||||
//add a small margin, to avoid detecting the toplevel view when checking
|
|
||||||
//if we have to move to a toplevel window.
|
|
||||||
m_screenRect.adjust(-2, -2, 2, 2);
|
|
||||||
|
|
||||||
kDebug() << "m_screenRect = " << m_screenRect;
|
kDebug() << "m_screenRect = " << m_screenRect;
|
||||||
|
|
||||||
//Are we moving out of the current view?
|
//Are we moving out of the current view?
|
||||||
bool toTopLevel = goTopLevel(m_screenRect.topLeft()) ||
|
bool toTopLevel = leaveCurrentView(m_screenRect);
|
||||||
goTopLevel(m_screenRect.topRight()) ||
|
|
||||||
goTopLevel(m_screenRect.bottomLeft()) ||
|
|
||||||
goTopLevel(m_screenRect.bottomRight());
|
|
||||||
|
|
||||||
if (!toTopLevel) {
|
if (!toTopLevel) {
|
||||||
setPos(m_pos);
|
setPos(m_pos);
|
||||||
@ -469,7 +488,7 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!m_topview) { //create a new toplevel view
|
if (!m_topview) { //create a new toplevel view
|
||||||
m_topview = new View(m_applet->containment(), -1, 0);
|
m_topview = new View(m_containment, -1, 0);
|
||||||
|
|
||||||
m_topview->setTrackContainmentChanges(false);
|
m_topview->setTrackContainmentChanges(false);
|
||||||
m_topview->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint
|
m_topview->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint
|
||||||
@ -502,7 +521,7 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
m_topview->show();
|
m_topview->show();
|
||||||
|
|
||||||
m_applet->setGhostView(m_applet->containment()->view());
|
m_applet->setGhostView(m_containment->view());
|
||||||
|
|
||||||
//TODO: non compositing users are screwed: masking looks terrible.
|
//TODO: non compositing users are screwed: masking looks terrible.
|
||||||
//Consider always enabling the applet background. Stuff like the analog clock
|
//Consider always enabling the applet background. Stuff like the analog clock
|
||||||
@ -623,6 +642,7 @@ void AppletHandle::switchContainment(Containment *containment, const QPointF &po
|
|||||||
case Containment::PanelContainment:
|
case Containment::PanelContainment:
|
||||||
kDebug() << "panel";
|
kDebug() << "panel";
|
||||||
//we need to fully disassociate the applet and handle, then kill the handle
|
//we need to fully disassociate the applet and handle, then kill the handle
|
||||||
|
applet->setZValue(m_zValue);
|
||||||
forceDisappear(); //takes care of event filter and killing 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
|
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
|
applet->disconnect(this); //make sure the applet doesn't tell us to do anything
|
||||||
@ -631,11 +651,18 @@ void AppletHandle::switchContainment(Containment *containment, const QPointF &po
|
|||||||
default: //FIXME assuming everything else behaves like desktop
|
default: //FIXME assuming everything else behaves like desktop
|
||||||
kDebug() << "desktop";
|
kDebug() << "desktop";
|
||||||
m_containment = containment;
|
m_containment = containment;
|
||||||
containment->addApplet(m_applet);
|
//FIXME: destorying the applethandle might not be necesarry. I'm having issues
|
||||||
setParentItem(containment);
|
//getting it to work correctly while keeping the handle though, so for now just
|
||||||
m_applet->setParentItem(this);
|
//destroy it.
|
||||||
setPos(containment->mapFromScene(pos));
|
applet->setZValue(m_zValue);
|
||||||
//setPos(pos);
|
forceDisappear();
|
||||||
|
m_applet=0;
|
||||||
|
applet->disconnect(this);
|
||||||
|
containment->addApplet(applet, containment->mapFromScene(pos));
|
||||||
|
//setParentItem(containment);
|
||||||
|
//m_applet->setParentItem(this);
|
||||||
|
//setPos(containment->mapFromScene(pos));
|
||||||
|
//update();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class AppletHandle : public QObject, public QGraphicsItem
|
|||||||
* @param pos the (scene-relative) position to place it at
|
* @param pos the (scene-relative) position to place it at
|
||||||
*/
|
*/
|
||||||
void switchContainment(Containment *containment, const QPointF &pos);
|
void switchContainment(Containment *containment, const QPointF &pos);
|
||||||
bool goTopLevel(const QPoint & pos);
|
bool leaveCurrentView(const QRect &rect) const;
|
||||||
|
|
||||||
QRectF m_rect;
|
QRectF m_rect;
|
||||||
ButtonType m_pressedButton;
|
ButtonType m_pressedButton;
|
||||||
@ -103,6 +103,7 @@ class AppletHandle : public QObject, public QGraphicsItem
|
|||||||
QPoint m_mousePos; //mousepos relative to applet
|
QPoint m_mousePos; //mousepos relative to applet
|
||||||
QRect m_screenRect; //boudingrect of applet in screencoords
|
QRect m_screenRect; //boudingrect of applet in screencoords
|
||||||
QPointF m_pos; //current position of applet in sceneCoords
|
QPointF m_pos; //current position of applet in sceneCoords
|
||||||
|
qreal m_zValue; //current zValue of the applet, so it can be restored after drag.
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -494,6 +494,9 @@ void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
|
|||||||
applet->removeSceneEventFilter(currentContainment);
|
applet->removeSceneEventFilter(currentContainment);
|
||||||
KConfigGroup oldConfig = applet->config();
|
KConfigGroup oldConfig = applet->config();
|
||||||
currentContainment->d->applets.removeAll(applet);
|
currentContainment->d->applets.removeAll(applet);
|
||||||
|
if (currentContainment->d->handles.contains(applet)) {
|
||||||
|
currentContainment->d->handles.remove(applet);
|
||||||
|
}
|
||||||
applet->setParentItem(this);
|
applet->setParentItem(this);
|
||||||
|
|
||||||
// now move the old config to the new location
|
// now move the old config to the new location
|
||||||
@ -501,7 +504,7 @@ void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
|
|||||||
oldConfig.reparent(&c);
|
oldConfig.reparent(&c);
|
||||||
applet->d->resetConfigurationObject();
|
applet->d->resetConfigurationObject();
|
||||||
} else {
|
} else {
|
||||||
applet->setParentItem(this);
|
applet->setParentItem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->applets << applet;
|
d->applets << applet;
|
||||||
|
Loading…
Reference in New Issue
Block a user