00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kgamepopupitem.h"
00019 #include <QPainter>
00020 #include <QTimeLine>
00021 #include <QTimer>
00022 #include <QGraphicsScene>
00023 #include <QGraphicsView>
00024 #include <QGraphicsTextItem>
00025
00026 #include <KIcon>
00027 #include <KDebug>
00028 #include <kcolorscheme.h>
00029
00030
00031 static const int MARGIN = 15;
00032
00033 static const int SHOW_OFFSET = 5;
00034
00035 static const int SOME_SPACE = 10;
00036
00037 static const qreal BORDER_PEN_WIDTH = 1.0;
00038
00039 class TextItemWithOpacity : public QGraphicsTextItem
00040 {
00041 public:
00042 TextItemWithOpacity( QGraphicsItem* parent = 0 )
00043 :QGraphicsTextItem(parent), m_opacity(1.0) {}
00044 void setOpacity(qreal opa) { m_opacity = opa; }
00045 void setTextColor(KStatefulBrush brush) { m_brush = brush; }
00046 virtual void paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget )
00047 {
00048
00049
00050
00051 setDefaultTextColor(m_brush.brush(widget).color());
00052 p->save();
00053 p->setOpacity(m_opacity);
00054 QGraphicsTextItem::paint(p,option,widget);
00055 p->restore();
00056 }
00057 private:
00058 qreal m_opacity;
00059 KStatefulBrush m_brush;
00060 };
00061
00062 class KGamePopupItemPrivate
00063 {
00064 private:
00065 KGamePopupItemPrivate(const KGamePopupItemPrivate&);
00066 const KGamePopupItemPrivate& operator=(const KGamePopupItemPrivate&);
00067 public:
00068 KGamePopupItemPrivate()
00069 : m_position( KGamePopupItem::BottomLeft ), m_timeout(2000),
00070 m_opacity(1.0), m_animOpacity(-1), m_hoveredByMouse(false), m_textChildItem(0),
00071 m_sharpness(KGamePopupItem::Square) {}
00075 QTimeLine m_timeLine;
00079 QTimer m_timer;
00083 QRectF m_boundRect;
00087 KGamePopupItem::Position m_position;
00091 int m_timeout;
00095 qreal m_opacity;
00099 qreal m_animOpacity;
00103 QPixmap m_iconPix;
00107 bool m_hoveredByMouse;
00111 TextItemWithOpacity* m_textChildItem;
00117 QRectF m_visibleSceneRect;
00121 KStatefulBrush m_brush;
00125 KGamePopupItem::Sharpness m_sharpness;
00129 QPainterPath m_path;
00130 };
00131
00132 KGamePopupItem::KGamePopupItem(QGraphicsItem * parent)
00133 : QGraphicsItem(parent), d(new KGamePopupItemPrivate)
00134 {
00135 hide();
00136 d->m_textChildItem = new TextItemWithOpacity(this);
00137 d->m_textChildItem->setTextInteractionFlags( Qt::LinksAccessibleByMouse );
00138
00139
00140 d->m_textChildItem->setFlag( QGraphicsItem::ItemIsFocusable, false );
00141
00142 connect( d->m_textChildItem, SIGNAL(linkActivated(const QString&)),
00143 SIGNAL(linkActivated(const QString&)));
00144 connect( d->m_textChildItem, SIGNAL(linkHovered(const QString&)),
00145 SLOT(onLinkHovered(const QString&)));
00146
00147 setZValue(100);
00148 d->m_textChildItem->setZValue(100);
00149
00150 KIcon infoIcon("dialog-information");
00151
00152 setMessageIcon( infoIcon.pixmap(32, 32) );
00153
00154 d->m_timer.setSingleShot(true);
00155
00156 setAcceptsHoverEvents(true);
00157
00158
00159 d->m_brush = KStatefulBrush( KColorScheme::Tooltip, KColorScheme::NormalBackground );
00160 d->m_textChildItem->setTextColor( KStatefulBrush(KColorScheme::Tooltip, KColorScheme::NormalText) );
00161
00162 connect( &d->m_timeLine, SIGNAL(frameChanged(int)), SLOT(animationFrame(int)) );
00163 connect( &d->m_timeLine, SIGNAL(finished()), SLOT(hideMe()));
00164 connect( &d->m_timer, SIGNAL(timeout()), SLOT(playHideAnimation()) );
00165 }
00166
00167 void KGamePopupItem::paint( QPainter* p, const QStyleOptionGraphicsItem *option, QWidget* widget )
00168 {
00169 Q_UNUSED(option);
00170 Q_UNUSED(widget);
00171
00172 p->save();
00173
00174 QPen pen = p->pen();
00175 pen.setWidthF( BORDER_PEN_WIDTH );
00176 p->setPen(pen);
00177
00178 if( d->m_animOpacity != -1)
00179 p->setOpacity(d->m_animOpacity);
00180 else
00181 p->setOpacity(d->m_opacity);
00182 p->setBrush(d->m_brush.brush(widget));
00183 p->drawPath(d->m_path);
00184 p->drawPixmap( MARGIN, static_cast<int>(d->m_boundRect.height()/2) - d->m_iconPix.height()/2,
00185 d->m_iconPix );
00186 p->restore();
00187 }
00188
00189 void KGamePopupItem::showMessage( const QString& text, Position pos, ReplaceMode mode )
00190 {
00191 if(d->m_timeLine.state() == QTimeLine::Running || d->m_timer.isActive())
00192 {
00193 if (mode == ReplacePrevious)
00194 forceHide(InstantHide);
00195 else
00196 return;
00197 }
00198
00199
00200
00201 QGraphicsView *sceneView = scene()->views().at(0);
00202 QPolygonF poly = sceneView->mapToScene( sceneView->viewport()->contentsRect() );
00203 d->m_visibleSceneRect = poly.boundingRect();
00204
00205 d->m_textChildItem->setHtml(text);
00206
00207 d->m_position = pos;
00208
00209
00210 prepareGeometryChange();
00211
00212
00213 qreal w = d->m_textChildItem->boundingRect().width()+MARGIN*2+d->m_iconPix.width()+SOME_SPACE;
00214 qreal h = d->m_textChildItem->boundingRect().height()+MARGIN*2;
00215 if( d->m_iconPix.height() > h )
00216 h = d->m_iconPix.height() + MARGIN*2;
00217 d->m_boundRect = QRectF(0, 0, w, h);
00218
00219
00220
00221 const qreal borderRadius = BORDER_PEN_WIDTH / 2.0;
00222 d->m_boundRect.adjust( -borderRadius ,
00223 -borderRadius ,
00224 borderRadius ,
00225 borderRadius );
00226
00227 QPainterPath roundRectPath;
00228 roundRectPath.moveTo(w, d->m_sharpness);
00229 roundRectPath.arcTo(w-(2*d->m_sharpness), 0.0,(2*d->m_sharpness), (d->m_sharpness), 0.0, 90.0);
00230 roundRectPath.lineTo(d->m_sharpness, 0.0);
00231 roundRectPath.arcTo(0.0, 0.0, (2*d->m_sharpness), (2*d->m_sharpness), 90.0, 90.0);
00232 roundRectPath.lineTo(0.0, h-(d->m_sharpness));
00233 roundRectPath.arcTo(0.0, h-(2*d->m_sharpness), 2*d->m_sharpness, 2*d->m_sharpness, 180.0, 90.0);
00234 roundRectPath.lineTo(w-(d->m_sharpness), h);
00235 roundRectPath.arcTo(w-(2*d->m_sharpness), h-(2*d->m_sharpness), (2*d->m_sharpness), (2*d->m_sharpness), 270.0, 90.0);
00236 roundRectPath.closeSubpath();
00237
00238 d->m_path = roundRectPath;
00239
00240
00241 d->m_textChildItem->setPos( d->m_textChildItem->x(),
00242 d->m_boundRect.height()/2 - d->m_textChildItem->boundingRect().height()/2);
00243
00244
00245 setupTimeline();
00246
00247
00248 animationFrame(d->m_timeLine.startFrame());
00249 show();
00250 d->m_timeLine.start();
00251
00252 if(d->m_timeout != 0)
00253 {
00254
00255 d->m_timer.start( 300+d->m_timeout );
00256 }
00257 }
00258
00259 void KGamePopupItem::setupTimeline()
00260 {
00261 d->m_timeLine.setDirection( QTimeLine::Forward );
00262 d->m_timeLine.setDuration(300);
00263 if( d->m_position == TopLeft || d->m_position == TopRight )
00264 {
00265 int start = static_cast<int>(d->m_visibleSceneRect.top() - d->m_boundRect.height() - SHOW_OFFSET);
00266 int end = static_cast<int>(d->m_visibleSceneRect.top() + SHOW_OFFSET);
00267 d->m_timeLine.setFrameRange( start, end );
00268 }
00269 else if( d->m_position == BottomLeft || d->m_position == BottomRight )
00270 {
00271 int start = static_cast<int>(d->m_visibleSceneRect.bottom()+SHOW_OFFSET);
00272 int end = static_cast<int>(d->m_visibleSceneRect.bottom() - d->m_boundRect.height() - SHOW_OFFSET);
00273 d->m_timeLine.setFrameRange( start, end );
00274 }
00275 else if( d->m_position == Center )
00276 {
00277 d->m_timeLine.setFrameRange(0, d->m_timeLine.duration());
00278 setPos( d->m_visibleSceneRect.left() +
00279 d->m_visibleSceneRect.width()/2 - d->m_boundRect.width()/2,
00280 d->m_visibleSceneRect.top() +
00281 d->m_visibleSceneRect.height()/2 - d->m_boundRect.height()/2);
00282 }
00283
00284 }
00285
00286 void KGamePopupItem::animationFrame(int frame)
00287 {
00288 if( d->m_position == TopLeft || d->m_position == BottomLeft )
00289 setPos( d->m_visibleSceneRect.left()+SHOW_OFFSET, frame );
00290 else if( d->m_position == TopRight || d->m_position == BottomRight )
00291 setPos( d->m_visibleSceneRect.right()-d->m_boundRect.width()-SHOW_OFFSET, frame );
00292 else if( d->m_position == Center )
00293 {
00294 d->m_animOpacity = frame*d->m_opacity/d->m_timeLine.duration();
00295 d->m_textChildItem->setOpacity( d->m_animOpacity );
00296 update();
00297 }
00298 }
00299
00300 void KGamePopupItem::playHideAnimation()
00301 {
00302 if( d->m_hoveredByMouse )
00303 return;
00304
00305
00306 d->m_timeLine.setDirection( QTimeLine::Backward );
00307 d->m_timeLine.start();
00308 }
00309
00310 void KGamePopupItem::setMessageTimeout( int msec )
00311 {
00312 d->m_timeout = msec;
00313 }
00314
00315 void KGamePopupItem::setMessageOpacity( qreal opacity )
00316 {
00317 d->m_opacity = opacity;
00318 d->m_textChildItem->setOpacity(opacity);
00319 }
00320
00321 QRectF KGamePopupItem::boundingRect() const
00322 {
00323 return d->m_boundRect;
00324 }
00325
00326 KGamePopupItem::~KGamePopupItem()
00327 {
00328 delete d;
00329 }
00330
00331 void KGamePopupItem::hideMe()
00332 {
00333 d->m_animOpacity = -1;
00334
00335 d->m_textChildItem->setOpacity(d->m_opacity);
00336
00337
00338 if( d->m_timeLine.direction() == QTimeLine::Backward )
00339 {
00340 hide();
00341 emit hidden();
00342 }
00343 }
00344
00345 void KGamePopupItem::hoverEnterEvent( QGraphicsSceneHoverEvent* )
00346 {
00347 d->m_hoveredByMouse = true;
00348 }
00349
00350 void KGamePopupItem::hoverLeaveEvent( QGraphicsSceneHoverEvent* )
00351 {
00352 d->m_hoveredByMouse = false;
00353
00354 if( d->m_timeout != 0 && !d->m_timer.isActive() && d->m_timeLine.state() != QTimeLine::Running )
00355 playHideAnimation();
00356 }
00357
00358 void KGamePopupItem::setMessageIcon( const QPixmap& pix )
00359 {
00360 d->m_iconPix = pix;
00361 d->m_textChildItem->setPos( MARGIN+pix.width()+SOME_SPACE, MARGIN );
00362
00363 }
00364
00365 int KGamePopupItem::messageTimeout() const
00366 {
00367 return d->m_timeout;
00368 }
00369
00370 void KGamePopupItem::forceHide(HideType howToHide)
00371 {
00372 if(!isVisible())
00373 return;
00374
00375 if(howToHide == InstantHide)
00376 {
00377 d->m_timeLine.stop();
00378 d->m_timer.stop();
00379 hide();
00380 emit hidden();
00381 }
00382 else if(howToHide == AnimatedHide)
00383 {
00384
00385
00386 d->m_hoveredByMouse = false;
00387 d->m_timer.stop();
00388 playHideAnimation();
00389 }
00390 }
00391
00392 qreal KGamePopupItem::messageOpacity() const
00393 {
00394 return d->m_opacity;
00395 }
00396
00397 void KGamePopupItem::setBackgroundBrush( const QBrush& brush )
00398 {
00399 d->m_brush = KStatefulBrush(brush);
00400 }
00401
00402 void KGamePopupItem::setTextColor( const QColor& color )
00403 {
00404 KStatefulBrush brush(color, d->m_brush.brush(QPalette::Active));
00405 d->m_textChildItem->setTextColor(brush);
00406 }
00407
00408 void KGamePopupItem::onLinkHovered(const QString& link)
00409 {
00410 if(link.isEmpty())
00411 d->m_textChildItem->setCursor( Qt::ArrowCursor );
00412 else
00413 d->m_textChildItem->setCursor( Qt::PointingHandCursor );
00414 emit linkHovered(link);
00415 }
00416
00417 void KGamePopupItem::setSharpness( Sharpness sharpness )
00418 {
00419 d->m_sharpness = sharpness;
00420 }
00421
00422 KGamePopupItem::Sharpness KGamePopupItem::sharpness() const
00423 {
00424 return d->m_sharpness;
00425 }
00426
00427 void KGamePopupItem::mousePressEvent( QGraphicsSceneMouseEvent* )
00428 {
00429
00430
00431 }
00432
00433 void KGamePopupItem::mouseReleaseEvent( QGraphicsSceneMouseEvent* )
00434 {
00435 forceHide();
00436 }
00437
00438
00439 #include "kgamepopupitem.moc"