Plasma
panelappletoverlay.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00053
00054
00055
00056
00057
00058
00059
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())),
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
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
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
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
00249
00250 if (m_orientation == Qt::Horizontal) {
00251
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
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
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
00284 setMouseTracking(true);
00285 event->setAccepted(false);
00286 return;
00287 }
00288 }
00289
00290 releaseMouse();
00291
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
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
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
00347
00348
00349
00350
00351 QTimer::singleShot(0, this, SLOT(syncGeometry()));
00352 }
00353
00354 void PanelAppletOverlay::syncGeometry()
00355 {
00356 if (!m_layout) {
00357 return;
00358 }
00359
00360
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
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