Plasma
appletoverlay.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 "appletoverlay.h"
00021 #include "newspaper.h"
00022 #include "../common/appletmovespacer.h"
00023
00024 #include <QGraphicsSceneMouseEvent>
00025 #include <QGraphicsLinearLayout>
00026 #include <QPainter>
00027 #include <QTimer>
00028
00029 #include <KGlobalSettings>
00030 #include <KIconLoader>
00031
00032 #include <Plasma/Applet>
00033 #include <Plasma/Svg>
00034 #include <Plasma/FrameSvg>
00035 #include <Plasma/PaintUtils>
00036 #include <Plasma/ScrollWidget>
00037
00038 AppletOverlay::AppletOverlay(QGraphicsWidget *parent, Newspaper *newspaper)
00039 : QGraphicsWidget(parent),
00040 m_applet(0),
00041 m_newspaper(newspaper),
00042 m_spacer(0),
00043 m_spacerLayout(0),
00044 m_spacerIndex(0),
00045 m_scrollDown(false),
00046 m_clickDrag(false)
00047 {
00048 setAcceptHoverEvents(true);
00049 setAcceptDrops(true);
00050 setZValue(900);
00051 m_scrollTimer = new QTimer(this);
00052 m_scrollTimer->setSingleShot(false);
00053 connect(m_scrollTimer, SIGNAL(timeout()), this, SLOT(scrollTimeout()));
00054
00055 m_icons = new Plasma::Svg(this);
00056 m_icons->setImagePath("widgets/configuration-icons");
00057 m_icons->setContainsMultipleImages(true);
00058 }
00059
00060 AppletOverlay::~AppletOverlay()
00061 {
00062 }
00063
00064 void AppletOverlay::appletDestroyed()
00065 {
00066 m_applet = 0;
00067 }
00068
00069 void AppletOverlay::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00070 {
00071 Q_UNUSED(widget)
00072
00073 QColor c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00074 c.setAlphaF(0.15);
00075
00076 painter->fillRect(option->exposedRect, c);
00077
00078 if (m_applet) {
00079 QRectF geom = m_applet->contentsRect();
00080 geom.translate(m_applet->pos());
00081
00082 QPointF offset = m_newspaper->m_mainWidget->pos() + m_newspaper->m_scrollWidget->pos();
00083 geom.moveTopLeft(geom.topLeft() + offset);
00084 geom = geom.intersected(m_newspaper->m_scrollWidget->geometry());
00085 c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
00086 c.setAlphaF(0.30);
00087 QPainterPath p = Plasma::PaintUtils::roundedRectangle(geom, 4);
00088 painter->save();
00089 painter->setRenderHint(QPainter::Antialiasing, true);
00090 painter->fillPath(p, c);
00091 painter->restore();
00092 QRect iconRect(0, 0, KIconLoader::SizeLarge, KIconLoader::SizeLarge);
00093 iconRect.moveCenter(geom.center().toPoint());
00094 m_icons->paint(painter, iconRect, "move");
00095 }
00096 }
00097
00098 void AppletOverlay::mousePressEvent(QGraphicsSceneMouseEvent *event)
00099 {
00100 if (event->button() != Qt::LeftButton) {
00101
00102 int z = zValue();
00103 setZValue(-100);
00104
00105 m_newspaper->showContextMenu(event->pos(), event->pos().toPoint());
00106 setZValue(z);
00107 return;
00108 }
00109
00110 if (m_clickDrag) {
00111 m_clickDrag = false;
00112 m_origin = QPoint();
00113 return;
00114 }
00115
00116 if (m_applet) {
00117 m_origin = event->pos();
00118 showSpacer(event->pos());
00119 if (m_spacerLayout) {
00120 m_spacerLayout->removeItem(m_applet);
00121 m_applet->raise();
00122 }
00123 if (m_spacer) {
00124 m_spacer->setMinimumHeight(m_applet->size().height());
00125 }
00126 }
00127 }
00128
00129 void AppletOverlay::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
00130 {
00131 if (m_clickDrag) {
00132
00133 QGraphicsSceneMouseEvent me;
00134 me.setPos(event->pos());
00135 me.setLastPos(event->lastPos());
00136 mouseMoveEvent(&me);
00137 return;
00138 }
00139
00140 QPointF offset = m_newspaper->m_mainWidget->pos() + m_newspaper->m_scrollWidget->pos();
00141 disconnect(m_applet, SIGNAL(destroyed()), this, SLOT(appletDestroyed()));
00142 m_applet = 0;
00143
00144 Plasma::Applet *oldApplet;
00145
00146
00147 foreach (Plasma::Applet *applet, m_newspaper->applets()) {
00148 if (applet->geometry().contains(event->pos()-offset)) {
00149 m_applet = applet;
00150 connect(applet, SIGNAL(destroyed()), this, SLOT(appletDestroyed()));
00151 break;
00152 }
00153 }
00154 if (m_applet != oldApplet) {
00155 update();
00156 }
00157 }
00158
00159 void AppletOverlay::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00160 {
00161 if (m_spacer) {
00162 QPointF delta = event->pos()-event->lastPos();
00163 m_applet->moveBy(delta.x(), delta.y());
00164 showSpacer(event->pos());
00165 }
00166
00167 if (m_newspaper->orientation() == Qt::Vertical) {
00168 if (m_newspaper->m_scrollWidget->pos().y() + event->pos().y() > m_newspaper->m_scrollWidget->size().height()*0.70) {
00169 m_scrollTimer->start(50);
00170 m_scrollDown = true;
00171 } else if (m_newspaper->m_scrollWidget->pos().y() + event->pos().y() < m_newspaper->m_scrollWidget->size().height()*0.30) {
00172 m_scrollTimer->start(50);
00173 m_scrollDown = false;
00174 } else {
00175 m_scrollTimer->stop();
00176 }
00177 } else {
00178 if (m_newspaper->m_scrollWidget->pos().x() + event->pos().x() > m_newspaper->m_scrollWidget->size().width()*0.70) {
00179 m_scrollTimer->start(50);
00180 m_scrollDown = true;
00181 } else if (m_newspaper->m_scrollWidget->pos().x() + event->pos().x() < m_newspaper->m_scrollWidget->size().width()*0.30) {
00182 m_scrollTimer->start(50);
00183 m_scrollDown = false;
00184 } else {
00185 m_scrollTimer->stop();
00186 }
00187 }
00188
00189 update();
00190 }
00191
00192 void AppletOverlay::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00193 {
00194 Q_UNUSED(event)
00195
00196 m_scrollTimer->stop();
00197
00198 QPoint delta = event->pos().toPoint() - m_origin.toPoint();
00199 if (m_origin != QPointF() && delta.manhattanLength() < KGlobalSettings::dndEventDelay()) {
00200 m_clickDrag = true;
00201 m_origin = QPointF();
00202 return;
00203 }
00204
00205 if (m_spacer && m_spacerLayout) {
00206 m_spacerLayout->insertItem(m_spacerIndex, m_applet);
00207 m_spacerLayout->removeItem(m_spacer);
00208 }
00209
00210 delete m_spacer;
00211 m_spacer = 0;
00212 m_spacerLayout = 0;
00213 m_spacerIndex = 0;
00214 }
00215
00216 void AppletOverlay::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00217 {
00218 showSpacer(event->pos());
00219 m_newspaper->m_dragging = true;
00220 event->accept();
00221 }
00222
00223 void AppletOverlay::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00224 {
00225 if (event->pos().y() > size().height()*0.70) {
00226 m_scrollTimer->start(50);
00227 m_scrollDown = true;
00228 } else if (event->pos().y() < size().height()*0.30) {
00229 m_scrollTimer->start(50);
00230 m_scrollDown = false;
00231 } else {
00232 m_scrollTimer->stop();
00233 }
00234
00235 showSpacer(event->pos());
00236 }
00237
00238 void AppletOverlay::dropEvent(QGraphicsSceneDragDropEvent *event)
00239 {
00240 m_newspaper->dropEvent(event);
00241 m_newspaper->m_dragging = false;
00242
00243 if (m_spacerLayout) {
00244 m_spacerLayout->removeItem(m_spacer);
00245 }
00246
00247 if (m_spacer) {
00248 m_spacer->deleteLater();
00249 }
00250
00251 m_spacer = 0;
00252 m_spacerLayout = 0;
00253 m_spacerIndex = 0;
00254 }
00255
00256 void AppletOverlay::spacerRequestedDrop(QGraphicsSceneDragDropEvent *event)
00257 {
00258 dropEvent(event);
00259 }
00260
00261 void AppletOverlay::showSpacer(const QPointF &pos)
00262 {
00263 if (!scene()) {
00264 return;
00265 }
00266
00267 QPointF translatedPos = pos - m_newspaper->m_mainWidget->pos() - m_newspaper->m_scrollWidget->pos();
00268
00269 QGraphicsLinearLayout *lay = 0;
00270
00271 for (int i = 0; i < m_newspaper->m_mainLayout->count(); ++i) {
00272 QGraphicsLinearLayout *candidateLay = dynamic_cast<QGraphicsLinearLayout *>(m_newspaper->m_mainLayout->itemAt(i));
00273
00274
00275 if (!candidateLay) {
00276 continue;
00277 }
00278
00279 if (m_newspaper->m_orientation == Qt::Horizontal) {
00280 if (pos.y() < candidateLay->geometry().bottom()) {
00281 lay = candidateLay;
00282 break;
00283 }
00284
00285 } else {
00286 if (pos.x() < candidateLay->geometry().right()) {
00287 lay = candidateLay;
00288 break;
00289 }
00290 }
00291 }
00292
00293
00294 if (!lay) {
00295 QGraphicsLinearLayout *candidateLay = dynamic_cast<QGraphicsLinearLayout *>(m_newspaper->m_mainLayout->itemAt(m_newspaper->m_mainLayout->count()-1));
00296
00297 if (candidateLay && candidateLay->count() <= 2) {
00298 lay = candidateLay;
00299 }
00300 }
00301
00302
00303 if (!lay) {
00304 lay = m_newspaper->addColumn();
00305 }
00306
00307 if (pos == QPoint()) {
00308 if (m_spacer) {
00309 lay->removeItem(m_spacer);
00310 m_spacer->hide();
00311 }
00312 return;
00313 }
00314
00315
00316 if (m_spacer && m_spacer->geometry().contains(translatedPos)) {
00317 return;
00318 }
00319
00320 int insertIndex = -1;
00321
00322 for (int i = 0; i < lay->count(); ++i) {
00323 QRectF siblingGeometry = lay->itemAt(i)->geometry();
00324
00325 if (m_newspaper->m_orientation == Qt::Horizontal) {
00326 qreal middle = siblingGeometry.center().x();
00327 if (translatedPos.x() < middle) {
00328 insertIndex = i;
00329 break;
00330 } else if (translatedPos.x() <= siblingGeometry.right()) {
00331 insertIndex = i + 1;
00332 break;
00333 }
00334 } else {
00335 qreal middle = siblingGeometry.center().y();
00336
00337 if (translatedPos.y() < middle) {
00338 insertIndex = i;
00339 break;
00340 } else if (translatedPos.y() <= siblingGeometry.bottom()) {
00341 insertIndex = i + 1;
00342 break;
00343 }
00344 }
00345 }
00346
00347 if (m_spacerLayout == lay && m_spacerIndex < insertIndex) {
00348 --insertIndex;
00349 }
00350 if (lay->count() > 1 && insertIndex >= lay->count() - 1) {
00351 --insertIndex;
00352 }
00353
00354 m_spacerIndex = insertIndex;
00355 if (insertIndex != -1) {
00356 if (!m_spacer) {
00357 m_spacer = new AppletMoveSpacer(this);
00358 connect (m_spacer, SIGNAL(dropRequested(QGraphicsSceneDragDropEvent *)),
00359 this, SLOT(spacerRequestedDrop(QGraphicsSceneDragDropEvent *)));
00360 }
00361 if (m_spacerLayout) {
00362 m_spacerLayout->removeItem(m_spacer);
00363 }
00364 m_spacer->show();
00365 lay->insertItem(insertIndex, m_spacer);
00366 m_spacerLayout = lay;
00367 }
00368 }
00369
00370 void AppletOverlay::scrollTimeout()
00371 {
00372 if (!m_applet) {
00373 return;
00374 }
00375
00376 if (m_newspaper->orientation() == Qt::Vertical) {
00377 if (m_scrollDown) {
00378 if (m_newspaper->m_mainWidget->geometry().bottom() > m_newspaper->m_scrollWidget->geometry().bottom()) {
00379 m_newspaper->m_mainWidget->moveBy(0, -10);
00380 m_applet->moveBy(0, 10);
00381 }
00382 } else {
00383 if (m_newspaper->m_mainWidget->pos().y() < 0) {
00384 m_newspaper->m_mainWidget->moveBy(0, 10);
00385 m_applet->moveBy(0, -10);
00386 }
00387 }
00388 } else {
00389 if (m_scrollDown) {
00390 if (m_newspaper->m_mainWidget->geometry().right() > m_newspaper->m_scrollWidget->geometry().right()) {
00391 m_newspaper->m_mainWidget->moveBy(-10, 0);
00392 m_applet->moveBy(10, 0);
00393 }
00394 } else {
00395 if (m_newspaper->m_mainWidget->pos().x() < 0) {
00396 m_newspaper->m_mainWidget->moveBy(10, 0);
00397 m_applet->moveBy(-10, 0);
00398 }
00399 }
00400 }
00401 }
00402
00403 #include <appletoverlay.moc>
00404