Start of improved applet drag & drop. What works now is:
* dragging an applet creates a top level window so the applet won't appear behind the panel when dragging, as is the case now. * dragging leaves a semi transparent version of the applet at the original location, so it's clear to the user where the applet came from and where it will go when the drag is cancelled. There are still some open issues, I'm working on those... svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=806484
This commit is contained in:
parent
bb55e8eb78
commit
1172ef79e9
59
applet.cpp
59
applet.cpp
@ -700,23 +700,43 @@ QList<QAction*> Applet::contextualActions()
|
||||
|
||||
void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
QPainter *p;
|
||||
QPixmap pixmap(size().toSize());
|
||||
|
||||
QGraphicsView* qgv = qobject_cast<QGraphicsView*>(widget->parent());
|
||||
bool ghost = (qgv && (qgv == d->ghostView));
|
||||
|
||||
if (ghost) {
|
||||
// The applet has to be displayed semi transparent. Create a pixmap and a painter on
|
||||
// that pixmap where the applet can draw on so we can draw the result transparently
|
||||
// at the end.
|
||||
kDebug() << "Painting ghosted...";
|
||||
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
p = new QPainter();
|
||||
p->begin(&pixmap);
|
||||
} else {
|
||||
p = painter;
|
||||
}
|
||||
|
||||
if (d->shadow && d->shadow->shadowedSize() != boundingRect().size()) {
|
||||
//kDebug() << "sizes are " << d->shadow->shadowedSize() << boundingRect().size();
|
||||
d->shadow->generate();
|
||||
}
|
||||
|
||||
painter->save();
|
||||
p->save();
|
||||
|
||||
if (transform().isRotating()) {
|
||||
painter->setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
p->setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
p->setRenderHint(QPainter::Antialiasing);
|
||||
}
|
||||
|
||||
if (d->background &&
|
||||
formFactor() != Plasma::Vertical &&
|
||||
formFactor() != Plasma::Horizontal) {
|
||||
//kDebug() << "option rect is" << option->rect;
|
||||
d->background->paintPanel(painter, option->rect, QPointF(0,0));
|
||||
d->background->paintPanel(p, option->rect, QPointF(0,0));
|
||||
}
|
||||
|
||||
if (!d->failed) {
|
||||
@ -731,17 +751,29 @@ void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QW
|
||||
Containment::StyleOption coption(*option);
|
||||
coption.view = v;
|
||||
|
||||
paintInterface(painter, &coption, contentsRect);
|
||||
paintInterface(p, &coption, contentsRect);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
p->restore();
|
||||
return;
|
||||
}
|
||||
|
||||
//kDebug() << "paint interface of" << (QObject*) this;
|
||||
paintInterface(painter, option, contentsRect);
|
||||
paintInterface(p, option, contentsRect);
|
||||
}
|
||||
p->restore();
|
||||
|
||||
if (ghost) {
|
||||
// Lets display the pixmap that we've just drawn... transparently.
|
||||
p->setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p->fillRect(pixmap.rect(), QColor(0, 0, 0, (0.3 * 255)));
|
||||
p->end();
|
||||
|
||||
delete p;
|
||||
|
||||
kDebug() << "draw the pixmap!";
|
||||
painter->drawPixmap(0, 0, pixmap);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
@ -800,6 +832,17 @@ void Applet::setAspectRatioMode(Plasma::AspectRatioMode mode)
|
||||
d->aspectRatioMode = mode;
|
||||
}
|
||||
|
||||
QGraphicsView * Applet::ghostView()
|
||||
{
|
||||
return d->ghostView;
|
||||
}
|
||||
|
||||
void Applet::setGhostView( QGraphicsView * view )
|
||||
{
|
||||
d->ghostView = view;
|
||||
update();
|
||||
}
|
||||
|
||||
void Applet::registerAsDragHandle( QGraphicsItem * item )
|
||||
{
|
||||
if (!item) {
|
||||
|
13
applet.h
13
applet.h
@ -230,6 +230,19 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget
|
||||
*/
|
||||
void setAspectRatioMode(Plasma::AspectRatioMode);
|
||||
|
||||
/**
|
||||
* @return The view where the applet appears ghosted.
|
||||
*/
|
||||
QGraphicsView * ghostView();
|
||||
|
||||
/**
|
||||
* Sets a view which displays the applet semi transparent.
|
||||
*
|
||||
* @param view The view where the applet should appear 'ghosted'. Set to
|
||||
* 0 to don't ghost the applet anywhere.
|
||||
*/
|
||||
void setGhostView(QGraphicsView * view);
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets.
|
||||
*
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
KConfigGroup *mainConfig;
|
||||
Plasma::Constraints pendingConstraints;
|
||||
Plasma::AspectRatioMode aspectRatioMode;
|
||||
QGraphicsView* ghostView;
|
||||
ImmutabilityType immutability;
|
||||
int constraintsTimerId;
|
||||
bool hasConfigurationInterface : 1;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <KColorScheme>
|
||||
#include <KGlobalSettings>
|
||||
#include <KIcon>
|
||||
#include <KWindowSystem>
|
||||
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
@ -57,7 +58,8 @@ AppletHandle::AppletHandle(Containment *parent, Applet *applet)
|
||||
m_scaleWidth(1.0),
|
||||
m_scaleHeight(1.0),
|
||||
m_buttonsOnRight(false),
|
||||
m_pendingFade(false)
|
||||
m_pendingFade(false),
|
||||
m_topview(0)
|
||||
{
|
||||
KColorScheme colorScheme(QPalette::Active, KColorScheme::View, Theme::defaultTheme()->colorScheme());
|
||||
m_gradientColor = colorScheme.background(KColorScheme::NormalBackground).color();
|
||||
@ -270,6 +272,10 @@ void AppletHandle::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
setZValue(m_applet->zValue());
|
||||
}
|
||||
event->accept();
|
||||
//set mousePos to the position in the applet, in screencoords, so it becomes easy
|
||||
//to reposition the toplevel view to the correct position.
|
||||
m_mousePos = event->screenPos() - m_applet->view()->mapToGlobal(
|
||||
m_applet->view()->mapFromScene(m_applet->pos()));
|
||||
update();
|
||||
return;
|
||||
}
|
||||
@ -333,6 +339,12 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
break;
|
||||
case MoveButton: {
|
||||
if (m_topview) {
|
||||
m_topview->hide();
|
||||
delete m_topview;
|
||||
m_topview = 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;
|
||||
@ -340,14 +352,21 @@ void AppletHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
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
|
||||
QPoint pos = v->mapFromGlobal(event->screenPos() - m_mousePos);
|
||||
|
||||
//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 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));
|
||||
} else {
|
||||
//just update the position
|
||||
kDebug() << "just update the position";
|
||||
m_applet->setPos(v->mapToScene(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -392,25 +411,37 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
QPointF delta = curPos-lastPos;
|
||||
|
||||
if (m_pressedButton == MoveButton) {
|
||||
setPos(pos()+delta);
|
||||
// test for containment change
|
||||
if (!m_containment->sceneBoundingRect().contains(event->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) {
|
||||
if (containments[i]->sceneBoundingRect().contains(event->scenePos())) {
|
||||
// add the applet to the new containment
|
||||
// and take it from the old one
|
||||
//kDebug() << "moving to other containment with position" << pos() << event->scenePos();
|
||||
//kDebug() << "position before reparenting" << pos() << scenePos();
|
||||
switchContainment(containments[i], scenePos());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
//TODO: when zoomed out, this doesn't work correctly
|
||||
m_topview->setSceneRect(m_applet->sceneBoundingRect());
|
||||
|
||||
// Calculate the size of the applet in screen coordinates.
|
||||
QPointF bottomRight = m_applet->pos();
|
||||
bottomRight.setX(bottomRight.x() + m_applet->size().width());
|
||||
bottomRight.setY(bottomRight.y() + m_applet->size().height());
|
||||
|
||||
QPoint tL = m_applet->view()->mapToGlobal(m_applet->view()->mapFromScene(
|
||||
m_applet->pos()));
|
||||
QPoint bR = m_applet->view()->mapToGlobal(m_applet->view()->mapFromScene(
|
||||
bottomRight));
|
||||
|
||||
m_topview->resize(bR.x() - tL.x(), bR.y() - tL.y());
|
||||
m_topview->show();
|
||||
|
||||
m_applet->setGhostView(m_applet->containment()->view());
|
||||
}
|
||||
|
||||
m_topview->move((event->screenPos() - m_mousePos));
|
||||
|
||||
} else if (m_pressedButton == RotateButton ||
|
||||
m_pressedButton == ResizeButton) {
|
||||
if (_k_distanceForPoint(delta) <= 1.0) {
|
||||
@ -510,6 +541,7 @@ void AppletHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//pos relative to scene
|
||||
void AppletHandle::switchContainment(Containment *containment, const QPointF &pos)
|
||||
{
|
||||
@ -665,7 +697,6 @@ void AppletHandle::calculateSize()
|
||||
}
|
||||
|
||||
m_rect.adjust(-HANDLE_WIDTH, -HANDLE_WIDTH, HANDLE_WIDTH, HANDLE_WIDTH);
|
||||
|
||||
if (m_applet->pos().x() <= ((HANDLE_WIDTH * 2) + ICON_SIZE)) {
|
||||
m_rect.adjust(0.0, 0.0, ICON_SIZE, 0.0);
|
||||
m_buttonsOnRight = true;
|
||||
|
@ -31,6 +31,7 @@ namespace Plasma
|
||||
{
|
||||
class Applet;
|
||||
class Containment;
|
||||
class View;
|
||||
|
||||
class AppletHandle : public QObject, public QGraphicsItem
|
||||
{
|
||||
@ -96,6 +97,9 @@ class AppletHandle : public QObject, public QGraphicsItem
|
||||
QTimer *m_hoverTimer;
|
||||
bool m_buttonsOnRight;
|
||||
bool m_pendingFade;
|
||||
View *m_topview;
|
||||
QPoint m_mousePos; //the position of the mousecursor relative to the
|
||||
//applets position.
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user