Improved drag&drop: when an applet gets dragged, it now only moves to a toplevel

window when necesarry (when the applet moves over another view or window).


svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=806641
This commit is contained in:
Rob Scheepmaker 2008-05-11 22:02:35 +00:00
parent c4ff00eb0f
commit 143b126bca
4 changed files with 102 additions and 48 deletions

View File

@ -252,6 +252,7 @@ AppletHandle::ButtonType AppletHandle::mapToButton(const QPointF &point) const
//return m_applet->mapToParent(m_applet->shape()).contains(point) ? NoButton : MoveButton; //return m_applet->mapToParent(m_applet->shape()).contains(point) ? NoButton : MoveButton;
} }
void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event) void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (m_pendingFade) { if (m_pendingFade) {
@ -345,29 +346,22 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
m_topview = 0; m_topview = 0;
m_applet->setGhostView(0); m_applet->setGhostView(0);
} }
//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();
QPoint pos = v->mapFromGlobal(event->screenPos() - m_mousePos);
//XXX the dashboard view won't give us a //find out if we were dropped on a panel or something
//containment. if it did, this could Plasma::View *v = Plasma::View::topLevelViewAt(event->screenPos());
//break shit. if (v) {
if (c && c != m_containment) { Containment *c = v->containment();
//we actually have been dropped on another QPoint pos = v->mapFromGlobal(event->screenPos() - m_mousePos);
//containment, so move there
//we have a screenpos, we need a scenepos //XXX the dashboard view won't give us a
//FIXME how reliable is this transform? //containment. if it did, this could
switchContainment(c, v->mapToScene(pos)); //break shit.
} else { if (c && c != m_containment) {
//just update the position //we actually have been dropped on another
kDebug() << "just update the position"; //containment, so move there
m_applet->setPos(v->mapToScene(pos)); //we have a screenpos, we need a scenepos
} //FIXME how reliable is this transform?
switchContainment(c, v->mapToScene(pos));
} }
} }
break; break;
@ -397,6 +391,15 @@ qreal _k_angleForPoints(const QPointF &center, const QPointF &pt1, const QPointF
return beta - alpha; return beta - alpha;
} }
bool AppletHandle::goTopLevel(const QPoint & pos) {
Plasma::View *v = Plasma::View::topLevelViewAt(pos);
if (v != m_applet->containment()->view()) {
return true;
} else {
return false;
}
}
void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
static const qreal snapAngle = M_PI_2 /* $i 3.14159 / 2.0 */; static const qreal snapAngle = M_PI_2 /* $i 3.14159 / 2.0 */;
@ -411,34 +414,65 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QPointF delta = curPos-lastPos; QPointF delta = curPos-lastPos;
if (m_pressedButton == MoveButton) { if (m_pressedButton == MoveButton) {
if (!m_topview) { //create a new toplevel view if (m_pos == QPointF(0, 0)) {
m_topview = new View(m_applet->containment(), -1, 0); m_pos = pos();
m_topview->setTrackContainmentChanges(false);
m_topview->setWindowFlags(Qt::Widget | Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint);
KWindowSystem::setState(m_topview->winId(), NET::SkipTaskbar | NET::SkipPager);
m_topview->setWallpaperEnabled(false);
m_topview->resize(m_applet->screenRect().size());
kDebug() << "resizing topview to: " << m_applet->screenRect().size();
//TODO: when zoomed out, this doesn't work correctly
m_topview->setSceneRect(m_applet->sceneBoundingRect());
m_topview->centerOn(m_applet);
//We might have to scale the qgv, because we might be zoomed out.
qreal scale = m_applet->screenRect().width() / m_applet->boundingRect().width();
kDebug() << "scaling topview with: " << scale;
m_topview->scale(scale, scale);
m_topview->show();
m_applet->setGhostView(m_applet->containment()->view());
} }
m_pos = m_pos + delta;
m_topview->move((event->screenPos() - m_mousePos)); QRect screenRect = QRect(event->screenPos() - m_mousePos,
m_applet->screenRect().size());
kDebug() << "screenRect = " << screenRect;
//add a 1 pixelmargin 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.
screenRect.adjust(-1, -1, 1, 1);
//Are we moving out of the current view?
bool toTopLevel = goTopLevel(screenRect.topLeft()) ||
goTopLevel(screenRect.topRight()) ||
goTopLevel(screenRect.bottomLeft()) ||
goTopLevel(screenRect.bottomRight());
kDebug() << "toTopLevel = " << toTopLevel;
if (!toTopLevel) {
setPos(m_pos);
if (m_topview) {
m_topview->hide();
delete m_topview;
m_topview = 0;
m_applet->setGhostView(0);
}
} else {
if (!m_topview) { //create a new toplevel view
m_topview = new View(m_applet->containment(), -1, 0);
m_topview->setTrackContainmentChanges(false);
m_topview->setWindowFlags(Qt::Widget | Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint);
KWindowSystem::setState(m_topview->winId(), NET::SkipTaskbar | NET::SkipPager);
m_topview->setWallpaperEnabled(false);
m_topview->resize(m_applet->screenRect().size());
kDebug() << "resizing topview to: " << m_applet->screenRect().size();
//TODO: when zoomed out, this doesn't work correctly
m_topview->setSceneRect(m_applet->sceneBoundingRect());
m_topview->centerOn(m_applet);
//We might have to scale the qgv, because we might be zoomed out.
qreal scale = m_applet->screenRect().width() / m_applet->boundingRect().width();
kDebug() << "scaling topview with: " << scale;
m_topview->scale(scale, scale);
m_topview->show();
m_applet->setGhostView(m_applet->containment()->view());
}
m_topview->move((event->screenPos() - m_mousePos));
}
} else if (m_pressedButton == RotateButton || } else if (m_pressedButton == RotateButton ||
m_pressedButton == ResizeButton) { m_pressedButton == ResizeButton) {
@ -670,6 +704,7 @@ void AppletHandle::startFading(FadeType anim)
m_animId = Animator::self()->customAnimation(40, (int)time, Animator::EaseInOutCurve, this, "fadeAnimation"); m_animId = Animator::self()->customAnimation(40, (int)time, Animator::EaseInOutCurve, this, "fadeAnimation");
} }
void AppletHandle::forceDisappear() void AppletHandle::forceDisappear()
{ {
setAcceptsHoverEvents(false); setAcceptsHoverEvents(false);

View File

@ -81,6 +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);
QRectF m_rect; QRectF m_rect;
ButtonType m_pressedButton; ButtonType m_pressedButton;
@ -100,6 +101,7 @@ class AppletHandle : public QObject, public QGraphicsItem
View *m_topview; View *m_topview;
QPoint m_mousePos; //the position of the mousecursor relative to the QPoint m_mousePos; //the position of the mousecursor relative to the
//applets position. //applets position.
QPointF m_pos;
}; };
} }

View File

@ -232,6 +232,16 @@ bool View::trackContainmentChanges()
return d->trackChanges; return d->trackChanges;
} }
View * View::topLevelViewAt(const QPoint & pos)
{
QWidget *w = QApplication::topLevelAt(pos);
if (w) {
Plasma::View *v = qobject_cast<Plasma::View *>(w);
return v;
} else {
return 0;
}
}
} // namespace Plasma } // namespace Plasma

7
view.h
View File

@ -20,6 +20,7 @@
#ifndef VIEW_H #ifndef VIEW_H
#define VIEW_H #define VIEW_H
#include <QApplication>
#include <QtGui/QGraphicsView> #include <QtGui/QGraphicsView>
#include <KDE/KConfigGroup> #include <KDE/KConfigGroup>
@ -135,6 +136,12 @@ public:
*/ */
bool trackContainmentChanges(); bool trackContainmentChanges();
/**
* @param pos the position in screen coordinates.
* @return the Plasma::View that is at position pos.
*/
static View * topLevelViewAt(const QPoint & pos);
/** /**
* @return the id of the View set in the constructor * @return the id of the View set in the constructor
*/ */