• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Plasma

panelappletoverlay.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2008 Aaron Seigo <aseigo@kde.org>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as
00006  *   published by the Free Software Foundation; either version 2,
00007  *   or (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "panelappletoverlay.h"
00021 
00022 #include <QApplication>
00023 #include <QGraphicsLinearLayout>
00024 #include <QPainter>
00025 #include <QTimer>
00026 
00027 #include <KGlobalSettings>
00028 #include <KIcon>
00029 
00030 #include <Plasma/Applet>
00031 #include <Plasma/Containment>
00032 #include <Plasma/PaintUtils>
00033 #include <Plasma/Theme>
00034 #include <Plasma/View>
00035 
00036 class AppletMoveSpacer : public QGraphicsWidget
00037 {
00038 public:
00039     AppletMoveSpacer(Plasma::Applet *applet)
00040         : QGraphicsWidget(applet->containment()),
00041           m_applet(applet)
00042     {
00043     }
00044 
00045 protected:
00046     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * widget = 0)
00047     {
00048         Q_UNUSED(option)
00049         Q_UNUSED(widget)
00050 
00051         /*
00052            results in odd painting corruption
00053         if (collidesWithItem(m_applet, Qt::IntersectsItemBoundingRect)) {
00054             painter->fillRect(contentsRect(), Qt::transparent);
00055             return;
00056         }
00057         */
00058 
00059         //TODO: make this a pretty gradient?
00060         painter->setRenderHint(QPainter::Antialiasing);
00061         QPainterPath p = Plasma::PaintUtils::roundedRectangle(contentsRect().adjusted(1, 1, -2, -2), 4);
00062         QColor c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00063         c.setAlphaF(0.3);
00064 
00065         painter->fillPath(p, c);
00066     }
00067 
00068 private:
00069     QGraphicsWidget *m_applet;
00070 };
00071 
00072 PanelAppletOverlay::PanelAppletOverlay(Plasma::Applet *applet, QWidget *parent)
00073     : QWidget(parent),
00074       m_applet(applet),
00075       m_spacer(0),
00076       m_layout(static_cast<QGraphicsLinearLayout*>(applet->containment()->layout())), // ++assumptions;
00077       m_index(0),
00078       m_clickDrag(false)
00079 {
00080     int i = 0;
00081     for (; i < m_layout->count(); ++i) {
00082         QGraphicsWidget *w = dynamic_cast<QGraphicsWidget*>(m_layout->itemAt(i));
00083         if (w == m_applet) {
00084             m_index = i;
00085             break;
00086         }
00087     }
00088 
00089     syncOrientation();
00090     syncGeometry();
00091 
00092     connect(m_applet, SIGNAL(destroyed(QObject*)), this, SLOT(deleteLater()));
00093     connect(m_applet, SIGNAL(geometryChanged()), this, SLOT(delaySyncGeometry()));
00094 }
00095 
00096 PanelAppletOverlay::~PanelAppletOverlay()
00097 {
00098     if (m_spacer) {
00099         if (m_layout) {
00100             m_layout->removeItem(m_spacer);
00101         }
00102 
00103         m_spacer->deleteLater();
00104         m_spacer = 0;
00105     }
00106 }
00107 
00108 void PanelAppletOverlay::paintEvent(QPaintEvent *event)
00109 {
00110     Q_UNUSED(event)
00111 
00112     QStyleOption op;
00113     op.initFrom(this);
00114 
00115     bool hovered = op.state & QStyle::State_MouseOver;
00116     bool mover = mouseGrabber() == this;
00117     if (!hovered || mover) {
00118         return;
00119     }
00120 
00121     QPainter p(this);
00122     KIcon icon("transform-move");
00123     int iconSize;
00124     QRect iconRect;
00125 
00126     if (m_orientation == Qt::Horizontal) {
00127         iconSize = qMin(qMin(height(), int(m_applet->size().width())), 64);
00128         iconRect = QRect(rect().center() - QPoint(iconSize / 2, iconSize / 2), QSize(iconSize, iconSize));
00129     } else {
00130         iconSize = qMin(qMin(width(), int(m_applet->size().height())), 64);
00131         iconRect = QRect(rect().center() - QPoint(iconSize / 2, iconSize / 2), QSize(iconSize, iconSize));
00132     }
00133 
00134     p.drawPixmap(iconRect, icon.pixmap(iconSize, iconSize));
00135 }
00136 
00137 void PanelAppletOverlay::mousePressEvent(QMouseEvent *event)
00138 {
00139     Q_UNUSED(event)
00140 
00141     //kDebug() << m_clickDrag;
00142     if (m_clickDrag) {
00143         setMouseTracking(false);
00144         m_clickDrag = false;
00145         m_origin = QPoint();
00146         return;
00147     }
00148 
00149     if (event->button() != Qt::LeftButton) {
00150         //kDebug() << "sending even to" << (QWidget*)parent();
00151         Plasma::View *view = dynamic_cast<Plasma::View*>(parent());
00152 
00153         if (view && view->containment()) {
00154             view->containment()->showContextMenu(mapToParent(event->pos()), event->globalPos());
00155         }
00156 
00157         return;
00158     }
00159 
00160     m_clickDrag = false;
00161     if (!m_spacer) {
00162         m_spacer = new AppletMoveSpacer(m_applet);
00163     } else {
00164         m_layout->removeItem(m_spacer);
00165     }
00166 
00167     m_origin = mapToParent(event->pos());
00168     m_spacer->setMinimumSize(m_applet->geometry().size());
00169     m_spacer->setMaximumSize(m_applet->geometry().size());
00170     m_layout->removeItem(m_applet);
00171     m_layout->insertItem(m_index, m_spacer);
00172     m_applet->setZValue(m_applet->zValue() + 1);
00173 
00174     if (m_orientation == Qt::Horizontal) {
00175         m_offset = geometry().x() - m_origin.x();
00176     } else {
00177         m_offset = geometry().y() - m_origin.y();
00178     }
00179 
00180     grabMouse();
00181 }
00182 
00183 void PanelAppletOverlay::mouseMoveEvent(QMouseEvent *event)
00184 {
00185     if (!m_layout) {
00186         return;
00187     }
00188 
00189     Plasma::FormFactor f = m_applet->formFactor();
00190 
00191     if ( ((f != Plasma::Horizontal && f != Plasma::Vertical) && rect().intersects(m_applet->rect().toRect())) ||
00192           ((f == Plasma::Horizontal || f == Plasma::Vertical) && !rect().contains(event->globalPos())) ) {
00193         Plasma::View *view = Plasma::View::topLevelViewAt(event->globalPos());
00194         kDebug() << "checking view" << view << m_applet->view();
00195 
00196         if (!view) {
00197             return;
00198         }
00199 
00200         QPointF pos = view->mapFromGlobal(event->globalPos());
00201         if (view != m_applet->view()) {
00202             Plasma::Containment *c = view->containment();
00203 
00204             syncOrientation();
00205             syncGeometry();
00206 
00207             if (m_spacer) {
00208                 m_layout->removeItem(m_spacer);
00209                 m_spacer->deleteLater();
00210                 m_spacer = 0;
00211             }
00212 
00213             QPointF pos = m_applet->view()->mapFromGlobal(event->globalPos());
00214             QRectF g = m_applet->geometry();
00215             pos += QPoint(m_offset, m_offset);
00216             g.moveTo(pos);
00217             m_applet->setGeometry(g);
00218             m_layout->removeItem(m_spacer);
00219             m_spacer->deleteLater();
00220             m_layout = 0;
00221             m_spacer = 0;
00222             c->addApplet(m_applet, pos, false);
00223             releaseMouse();
00224             return;
00225         }
00226     }
00227 
00228     if (!m_spacer) {
00229         m_spacer = new AppletMoveSpacer(m_applet);
00230         m_spacer->setMinimumSize(m_applet->geometry().size());
00231         m_spacer->setMaximumSize(m_applet->geometry().size());
00232         m_layout->removeItem(m_applet);
00233         m_layout->insertItem(m_index, m_spacer);
00234     }
00235 
00236     QPoint p = mapToParent(event->pos());
00237     QRectF g = m_applet->geometry();
00238 
00239     //kDebug() << p << g << "<-- movin'?";
00240     if (m_orientation == Qt::Horizontal) {
00241         g.moveLeft(p.x() + m_offset);
00242     } else {
00243         g.moveTop(p.y() + m_offset);
00244     }
00245 
00246     m_applet->setGeometry(g);
00247 
00248     // swap items if we pass completely over the next/previous item or cross
00249     // more than halfway across it, whichever comes first
00250     if (m_orientation == Qt::Horizontal) {
00251         //kDebug() << m_prevGeom << g << m_nextGeom;
00252         if (m_prevGeom.isValid() && g.left() <= m_prevGeom.left()) {
00253             swapWithPrevious();
00254         } else if (m_nextGeom.isValid() && g.right() >= m_nextGeom.right()) {
00255             swapWithNext();
00256         }
00257     } else if (m_prevGeom.isValid() && g.top() <= m_prevGeom.top()) {
00258         swapWithPrevious();
00259     } else if (m_nextGeom.isValid() && g.bottom() >= m_nextGeom.bottom()) {
00260         swapWithNext();
00261     }
00262 
00263     //kDebug() << "=================================";
00264 }
00265 
00266 void PanelAppletOverlay::mouseReleaseEvent(QMouseEvent *event)
00267 {
00268     Q_UNUSED(event)
00269     if (!m_spacer) {
00270         releaseMouse();
00271         return;
00272     }
00273 
00274     if (!m_origin.isNull()) {
00275         //kDebug() << m_clickDrag << m_origin << mapToParent(event->pos());
00276         if (m_orientation == Qt::Horizontal) {
00277             m_clickDrag = abs(mapToParent(event->pos()).x() - m_origin.x()) < KGlobalSettings::dndEventDelay();
00278         } else {
00279             m_clickDrag = abs(mapToParent(event->pos()).y() - m_origin.y()) < KGlobalSettings::dndEventDelay();
00280         }
00281 
00282         if (m_clickDrag) {
00283             //kDebug() << "click dragging." << this << mouseGrabber();
00284             setMouseTracking(true);
00285             event->setAccepted(false);
00286             return;
00287         }
00288     }
00289 
00290     releaseMouse();
00291     //kDebug();
00292     m_layout->removeItem(m_spacer);
00293     m_spacer->deleteLater();
00294     m_spacer = 0;
00295 
00296     m_layout->insertItem(m_index, m_applet);
00297     m_applet->setZValue(m_applet->zValue() - 1);
00298 }
00299 
00300 void PanelAppletOverlay::enterEvent(QEvent *event)
00301 {
00302     Q_UNUSED(event)
00303     update();
00304 }
00305 
00306 void PanelAppletOverlay::leaveEvent(QEvent *event)
00307 {
00308     Q_UNUSED(event)
00309     update();
00310 }
00311 
00312 void PanelAppletOverlay::swapWithPrevious()
00313 {
00314     //kDebug();
00315     --m_index;
00316 
00317     if (m_index > 0) {
00318         m_prevGeom = m_layout->itemAt(m_index - 1)->geometry();
00319     } else {
00320         m_prevGeom = QRectF();
00321     }
00322 
00323     m_nextGeom = m_layout->itemAt(m_index + 1)->geometry();
00324     m_layout->removeItem(m_spacer);
00325     m_layout->insertItem(m_index, m_spacer);
00326 }
00327 
00328 void PanelAppletOverlay::swapWithNext()
00329 {
00330     //kDebug();
00331     ++m_index;
00332 
00333     if (m_index < m_layout->count() - 1) {
00334         m_nextGeom = m_layout->itemAt(m_index + 1)->geometry();
00335     } else {
00336         m_nextGeom = QRectF();
00337     }
00338 
00339     m_prevGeom = m_layout->itemAt(m_index - 1)->geometry();
00340     m_layout->removeItem(m_spacer);
00341     m_layout->insertItem(m_index, m_spacer);
00342 }
00343 
00344 void PanelAppletOverlay::delaySyncGeometry()
00345 {
00346     // we need to do this because it gets called in a round-about-way
00347     // from our own mouseMoveEvent. if we call syncGeometry directly,
00348     // we end up with a maze of duplicated and confused mouseMoveEvents
00349     // of which only half are real (the other half being caused by the
00350     // immediate call to syncGeometry!)
00351     QTimer::singleShot(0, this, SLOT(syncGeometry()));
00352 }
00353 
00354 void PanelAppletOverlay::syncGeometry()
00355 {
00356     if (!m_layout) {
00357         return;
00358     }
00359 
00360     //kDebug();
00361     setGeometry(m_applet->geometry().toRect());
00362 
00363     if (m_index > 0) {
00364         m_prevGeom = m_layout->itemAt(m_index - 1)->geometry();
00365     } else {
00366         m_prevGeom = QRectF();
00367     }
00368 
00369     //kDebug() << m_index << m_layout->count();
00370     if (m_index < m_layout->count() - 1) {
00371         m_nextGeom = m_layout->itemAt(m_index + 1)->geometry();
00372     } else {
00373         m_nextGeom = QRectF();
00374     }
00375 }
00376 
00377 void PanelAppletOverlay::syncOrientation()
00378 {
00379     m_orientation = m_applet->formFactor() == Plasma::Horizontal ? Qt::Horizontal : Qt::Vertical;
00380 }
00381 
00382 #include "panelappletoverlay.moc"
00383 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal