Plasma
itembackground.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright 2009 by Alessandro Diaferia <alediaferia@gmail.com> * 00003 * Copyright 2009 by Marco Martin <notmart@gmail.com> * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU Library General Public License as * 00007 * published by the Free Software Foundation; either version 2, or * 00008 * (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program; if not, write to the * 00017 * Free Software Foundation, Inc., * 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * 00019 ***************************************************************************/ 00020 #include "itembackground.h" 00021 00022 #include <QPainter> 00023 #include <QTimer> 00024 #include <QStyleOptionGraphicsItem> 00025 00026 #include <QPropertyAnimation> 00027 00028 #include <kdebug.h> 00029 00030 #include <plasma/framesvg.h> 00031 #include <plasma/animator.h> 00032 #include <plasma/theme.h> 00033 namespace Plasma 00034 { 00035 00036 class ItemBackgroundPrivate 00037 { 00038 public: 00039 ItemBackgroundPrivate(ItemBackground *parent) 00040 : q(parent), 00041 target(0) 00042 {} 00043 00044 void animationUpdate(qreal progress); 00045 void targetDestroyed(QObject*); 00046 void frameSvgChanged(); 00047 void refreshCurrentTarget(); 00048 00049 ItemBackground * const q; 00050 QGraphicsItem *target; 00051 Plasma::FrameSvg *frameSvg; 00052 QRectF oldGeometry; 00053 QRectF newGeometry; 00054 QPropertyAnimation *anim; 00055 qreal opacity; 00056 bool fading; 00057 bool fadeIn; 00058 bool immediate; 00059 }; 00060 00061 ItemBackground::ItemBackground(QGraphicsWidget *parent) 00062 : QGraphicsWidget(parent), 00063 d(new ItemBackgroundPrivate(this)) 00064 { 00065 d->frameSvg = new Plasma::FrameSvg(this); 00066 d->anim = new QPropertyAnimation(this, "animationUpdate", this); 00067 d->anim->setStartValue(0); 00068 d->anim->setEndValue(1); 00069 d->opacity = 1; 00070 d->fading = false; 00071 d->fadeIn = false; 00072 d->immediate = false; 00073 00074 d->frameSvg->setImagePath("widgets/viewitem"); 00075 d->frameSvg->setEnabledBorders(Plasma::FrameSvg::AllBorders); 00076 d->frameSvg->setCacheAllRenderedFrames(true); 00077 d->frameSvg->setElementPrefix("hover"); 00078 00079 setCacheMode(DeviceCoordinateCache); 00080 setFlag(ItemIsMovable, false); 00081 setFlag(ItemIsSelectable, false); 00082 setFlag(ItemIsFocusable, false); 00083 00084 setFlag(QGraphicsItem::ItemSendsGeometryChanges, false); 00085 00086 qreal l, t, r, b; 00087 d->frameSvg->getMargins(l, t, r, b); 00088 setContentsMargins(l, t, r, b); 00089 00090 connect(d->frameSvg, SIGNAL(repaintNeeded()), this, SLOT(frameSvgChanged())); 00091 00092 setAcceptedMouseButtons(0); 00093 setZValue(-800); 00094 } 00095 00096 ItemBackground::~ItemBackground() 00097 { 00098 delete d; 00099 } 00100 00101 QRectF ItemBackground::target() const 00102 { 00103 return d->newGeometry; 00104 } 00105 00106 void ItemBackground::setTarget(const QRectF &newGeometry) 00107 { 00108 d->oldGeometry = geometry(); 00109 d->newGeometry = newGeometry; 00110 00111 if (!isVisible() && (!d->target || !d->target->isVisible())) { 00112 setGeometry(d->newGeometry); 00113 targetReached(newGeometry); 00114 if (d->target) { 00115 emit targetItemReached(d->target); 00116 } 00117 return; 00118 } 00119 00120 QGraphicsWidget *pw = parentWidget(); 00121 if (pw) { 00122 d->newGeometry = d->newGeometry.intersected(QRectF(QPointF(0,0), pw->size())); 00123 } 00124 00125 if (d->anim->state() != QAbstractAnimation::Stopped) { 00126 d->anim->stop(); 00127 } 00128 00129 if (d->target && d->target->isVisible() && !isVisible()) { 00130 setZValue(d->target->zValue()-1); 00131 setGeometry(newGeometry); 00132 d->oldGeometry = newGeometry; 00133 show(); 00134 } else { 00135 d->fading = false; 00136 d->opacity = 1; 00137 d->anim->start(); 00138 } 00139 00140 } 00141 00142 void ItemBackground::setTargetItem(QGraphicsItem *target) 00143 { 00144 if (d->target && d->target != target) { 00145 QObject *obj = 0; 00146 if (d->target->isWidget()) { 00147 obj = static_cast<QGraphicsWidget*>(d->target); 00148 obj->removeEventFilter(this); 00149 } else { 00150 d->target->removeSceneEventFilter(this); 00151 obj = dynamic_cast<QObject *>(d->target); 00152 } 00153 00154 if (obj) { 00155 disconnect(obj, 0, this, 0); 00156 } 00157 } 00158 00159 if (!target) { 00160 hide(); 00161 } 00162 00163 bool newTarget = (d->target != target); 00164 d->target = target; 00165 if (target) { 00166 setZValue(target->zValue() - 1); 00167 if (parentItem() != target->parentItem()) { 00168 QTransform t = transform(); 00169 setTransform(QTransform()); 00170 QRectF geom = mapToScene(geometry()).boundingRect(); 00171 setGeometry(mapFromScene(geom).boundingRect()); 00172 setTransform(t); 00173 } 00174 00175 QRectF rect = target->boundingRect(); 00176 rect.moveTopLeft(mapToParent(mapFromScene(target->mapToScene(QPointF(0, 0))))); 00177 00178 setTarget(rect); 00179 00180 00181 if (newTarget) { 00182 QObject *obj = 0; 00183 if (target->isWidget()) { 00184 obj = static_cast<QGraphicsWidget*>(target); 00185 obj->installEventFilter(this); 00186 } else { 00187 d->target->installSceneEventFilter(this); 00188 obj = dynamic_cast<QObject *>(target); 00189 } 00190 00191 if (obj) { 00192 connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(targetDestroyed(QObject*))); 00193 } 00194 } 00195 } 00196 } 00197 00198 QGraphicsItem *ItemBackground::targetItem() const 00199 { 00200 return d->target; 00201 } 00202 00203 bool ItemBackground::eventFilter(QObject *watched, QEvent *event) 00204 { 00205 QGraphicsWidget *targetWidget = static_cast<QGraphicsWidget *>(d->target); 00206 if (watched == targetWidget) { 00207 if (event->type() == QEvent::GraphicsSceneResize || 00208 event->type() == QEvent::GraphicsSceneMove) { 00209 // We need to wait for the parent widget to resize... 00210 QTimer::singleShot(0, this, SLOT(refreshCurrentTarget()) ); 00211 } else if (event->type() == QEvent::Show) { 00212 setTargetItem(targetWidget); 00213 } 00214 } 00215 00216 return false; 00217 } 00218 00219 bool ItemBackground::sceneEventFilter(QGraphicsItem *watched, QEvent *event) 00220 { 00221 if (watched == d->target) { 00222 if (event->type() == QEvent::GraphicsSceneMove) { 00223 QTimer::singleShot(0, this, SLOT(refreshCurrentTarget()) ); 00224 } 00225 } 00226 00227 return false; 00228 } 00229 00230 void ItemBackground::resizeEvent(QGraphicsSceneResizeEvent *) 00231 { 00232 d->frameSvg->resizeFrame(size()); 00233 } 00234 00235 QVariant ItemBackground::itemChange(GraphicsItemChange change, const QVariant &value) 00236 { 00237 if (d->immediate) { 00238 return value; 00239 } 00240 00241 if (change == ItemVisibleChange) { 00242 bool visible = value.toBool(); 00243 bool retVisible = visible; 00244 if (visible == isVisible() || d->anim->state() == QAbstractAnimation::Stopped) { 00245 retVisible = true; 00246 } 00247 d->fading = true; 00248 d->fadeIn = visible; 00249 00250 if (d->anim->state() != QAbstractAnimation::Stopped) { 00251 d->anim->stop(); 00252 } 00253 00254 d->anim->setDuration(250); 00255 d->anim->start(); 00256 00257 return retVisible; 00258 00259 } 00260 return value; 00261 } 00262 00263 void ItemBackground::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 00264 { 00265 Q_UNUSED(widget) 00266 00267 if (qFuzzyCompare(d->opacity, (qreal)1.0)) { 00268 d->frameSvg->paintFrame(painter, option->rect.topLeft()); 00269 } else if (qFuzzyCompare(d->opacity+1, (qreal)1.0)) { 00270 return; 00271 } else { 00272 QPixmap framePix = d->frameSvg->framePixmap(); 00273 QPainter bufferPainter(&framePix); 00274 bufferPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); 00275 bufferPainter.fillRect(framePix.rect(), QColor(0, 0, 0, 255 * d->opacity)); 00276 bufferPainter.end(); 00277 painter->drawPixmap(framePix.rect(), framePix, framePix.rect()); 00278 } 00279 } 00280 00281 void ItemBackground::setAnimationUpdate(qreal progress) 00282 { 00283 d->animationUpdate(progress); 00284 } 00285 00286 qreal ItemBackground::animationUpdate() const 00287 { 00288 return d->opacity; 00289 } 00290 00291 void ItemBackgroundPrivate::animationUpdate(qreal progress) 00292 { 00293 if (progress == 1) { 00294 if ((!fading) || (fadeIn)) { 00295 emit q->targetReached(newGeometry); 00296 if (target) { 00297 emit q->targetItemReached(target); 00298 } 00299 } 00300 } 00301 00302 if (fading) { 00303 opacity = fadeIn?progress:1-progress; 00304 if (!fadeIn && qFuzzyCompare(opacity+1, (qreal)1.0)) { 00305 immediate = true; 00306 q->hide(); 00307 immediate = false; 00308 } 00309 } else if (oldGeometry != newGeometry) { 00310 q->setGeometry(oldGeometry.x() + (newGeometry.x() - oldGeometry.x()) * progress, 00311 oldGeometry.y() + (newGeometry.y() - oldGeometry.y()) * progress, 00312 oldGeometry.width() + (newGeometry.width() - oldGeometry.width()) * progress, 00313 oldGeometry.height() + (newGeometry.height() - oldGeometry.height()) * progress); 00314 } 00315 00316 q->update(); 00317 emit q->animationStep(progress); 00318 } 00319 00320 void ItemBackgroundPrivate::targetDestroyed(QObject*) 00321 { 00322 target = 0; 00323 q->setTargetItem(0); 00324 } 00325 00326 void ItemBackgroundPrivate::frameSvgChanged() 00327 { 00328 qreal l, t, r, b; 00329 frameSvg->getMargins(l, t, r, b); 00330 q->setContentsMargins(l, t, r, b); 00331 q->update(); 00332 emit q->appearanceChanged(); 00333 } 00334 00335 void ItemBackgroundPrivate::refreshCurrentTarget() 00336 { 00337 q->setTargetItem(target); 00338 } 00339 00340 } // Plasma namespace 00341 00342 00343 #include "itembackground.moc" 00344 00345
KDE 4.6 API Reference