diff --git a/applet.cpp b/applet.cpp index 8a3ad28b0..ed2ae6b50 100644 --- a/applet.cpp +++ b/applet.cpp @@ -700,23 +700,43 @@ QList Applet::contextualActions() void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + QPainter *p; + QPixmap pixmap(size().toSize()); + + QGraphicsView* qgv = qobject_cast(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) { diff --git a/applet.h b/applet.h index fc365e279..0736d607e 100644 --- a/applet.h +++ b/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. * diff --git a/applet_p.h b/applet_p.h index d5f475abc..2ed12c7a6 100644 --- a/applet_p.h +++ b/applet_p.h @@ -85,6 +85,7 @@ public: KConfigGroup *mainConfig; Plasma::Constraints pendingConstraints; Plasma::AspectRatioMode aspectRatioMode; + QGraphicsView* ghostView; ImmutabilityType immutability; int constraintsTimerId; bool hasConfigurationInterface : 1; diff --git a/applethandle.cpp b/applethandle.cpp index abd20157c..4d33bddc8 100644 --- a/applethandle.cpp +++ b/applethandle.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -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(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(scene()); - if (corona) { - QList 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; diff --git a/applethandle_p.h b/applethandle_p.h index 840cb36f1..1fa421fa7 100644 --- a/applethandle_p.h +++ b/applethandle_p.h @@ -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. }; }