00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include <qtimer.h>
00013
#include <qpixmap.h>
00014
#include <qimage.h>
00015
#include <qapplication.h>
00016
#include <qpainter.h>
00017
#include <qstyle.h>
00018
#include <qmutex.h>
00019
#include <qcursor.h>
00020
00021
00022
#include "ALabel.h"
00023
00024
00025 ALabel::ALabel(
QWidget* parent,
const char* name,
00026 QPixmap* hoverOverImage,
00027
int setMethod,
int removalMethod,
00028
int resetMethod,
int removalBeforeResetMethod,
00029
int initDelay,
int accel) :
QLabel(parent,name)
00030 {
00031
delayedActionHead = NULL;
00032
delayedActionTail = NULL;
00033
00034
00035 this->setMethod = setMethod;
00036 this->removalMethod = removalMethod;
00037 this->removalBeforeResetMethod = removalBeforeResetMethod;
00038 this->resetMethod = resetMethod;
00039
00040
00041 this->hoverOverImage = hoverOverImage;
00042
drawHoverOverImage =
false;
00043
00044 setMouseTracking(
true);
00045
handCursorShown =
false;
00046
00047
00048
imageShown =
false;
00049
animating =
false;
00050
resettingImage =
false;
00051
pixStore = NULL;
00052
resetPixStore = NULL;
00053
00054
00055 setWFlags(WRepaintNoErase);
00056
00057
00058 this->initDelay = initDelay;
00059 this->accel = accel;
00060 this->
minDelay = 1;
00061
00062
00063
timer =
new QTimer();
00064 connect(
timer, SIGNAL(timeout()),
this, SLOT(
animate()) );
00065 }
00066
00067 void ALabel::setAnimationMethods(
int setMethod,
int removalMethod,
00068
int resetMethod,
int removalBeforeResetMethod )
00069 {
00070
00071 this->setMethod = setMethod;
00072 this->removalMethod = removalMethod;
00073 this->removalBeforeResetMethod = removalBeforeResetMethod;
00074 this->resetMethod = resetMethod;
00075 }
00076
00077 void ALabel::setPixmap (
const QPixmap & p )
00078 {
00079
00080
queueMutex.lock();
00081
animatingBoolMutex.lock();
00082
00083
if(
animating ||
delayedActionHead != NULL)
00084 {
00085
appendJob(
new QPixmap(p));
00086
animatingBoolMutex.unlock();
00087
queueMutex.unlock();
00088
return;
00089 }
00090
00091
else
00092 {
00093
animating =
true;
00094
animatingBoolMutex.unlock();
00095
queueMutex.unlock();
00096
internalSetPixmap( p );
00097 }
00098 }
00099
00100 void ALabel::internalSetPixmap (
const QPixmap & p )
00101 {
00102
00103
if(
pixStore)
00104 {
00105
resettingImage =
true;
00106
00107
00108
if(
resetPixStore)
00109 {
00110
00111
delete resetPixStore;
00112 }
00113
resetPixStore =
new QImage(p.convertToImage());
00114
00115
00116
animationType =
removalBeforeResetMethod;
00117
00118
00119
animatePixmap();
00120 }
00121
00122
else
00123 {
00124
resettingImage =
false;
00125
00126
pixStore =
new QImage(p.convertToImage());
00127
animationType =
setMethod;
00128
animatePixmap();
00129 }
00130 }
00131
00132 void ALabel::removePixmap (
bool forceImmediate)
00133 {
00134
00135
queueMutex.lock();
00136
animatingBoolMutex.lock();
00137
00138
if(
animating ||
delayedActionHead != NULL)
00139 {
00140
appendJob( NULL );
00141
animatingBoolMutex.unlock();
00142
queueMutex.unlock();
00143
return;
00144 }
00145
00146
else
00147 {
00148
00149
if(
pixStore != NULL)
00150
animating =
true;
00151
00152
animatingBoolMutex.unlock();
00153
queueMutex.unlock();
00154
00155
if(
animating)
00156
internalRemovePixmap( forceImmediate );
00157 }
00158 }
00159
00160 void ALabel::internalRemovePixmap(
bool forceImmediate )
00161 {
00162
00163
if(forceImmediate)
00164
animationType =
DISAPPEAR_IMMEDIATELY;
00165
else
00166
animationType =
removalMethod;
00167
00168
animatePixmap();
00169 }
00170
00171 void ALabel::animatePixmap()
00172 {
00173
00174
00175
00176
if(
animationType ==
SLIDE_OUT_LEFT ||
00177
animationType ==
SLIDE_OUT_RIGHT ||
00178
animationType ==
DISAPPEAR_IMMEDIATELY)
00179 {
step =
pixStore->width()-1; }
00180
else
00181 {
step = 1; }
00182
00183
00184
delay =
initDelay;
00185
00186
00187
lastTime.start();
00188
00189
00190
animate();
00191 }
00192
00193 void ALabel::animate()
00194 {
00195
00196
00197
int lastStep =
step;
00198
00199
00200
if(
animationType ==
APPEAR_IMMEDIATELY)
00201 step =
pixStore->width();
00202
else if(
animationType ==
DISAPPEAR_IMMEDIATELY)
00203 step = 0;
00204
else
00205 {
00206
00207
currentTime.start();
00208
double ms =
lastTime.msecsTo(
currentTime);
00209
00210
00211
int inc = (
int)(ms/(
delay+1));
00212
00213
if(
animationType ==
SLIDE_OUT_LEFT ||
00214
animationType ==
SLIDE_OUT_RIGHT)
00215 { inc = -inc; }
00216
00217
00218
if(inc != 0)
00219 {
00220
lastTime =
currentTime;
00221 }
00222
00223
00224 step = step + inc;
00225
00226
00227
if(
animationType ==
FADE_TRANSITION)
00228 {
00229
if(step > 100)
00230 step = 100;
00231 }
00232
else
00233 {
00234
if(step >
pixStore->width())
00235 step =
pixStore->width();
00236
else if(step < 0)
00237 step = 0;
00238 }
00239 }
00240
00241
00242
if(
animationType ==
FADE_TRANSITION)
00243 {
00244
if(step != lastStep)
00245 {
00246
00247
double w1 =
pixStore->width();
00248
double h1 =
pixStore->height();
00249
double w2 =
resetPixStore->width();
00250
double h2 =
resetPixStore->height();
00251
double alpha = ((
double)step) / 100.0;
00252
int w = (
int) ( w1 + (w2-w1)*alpha );
00253
int h = (
int) ( h1 + (h2-h1)*alpha );
00254
00255
00256 QImage oldImg =
pixStore->scale( w, h );
00257 QImage newImg =
resetPixStore->scale( w, h );
00258
00259
00260
int maxDepth =
pixStore->depth();
00261
if(
resetPixStore->depth() > maxDepth)
00262 maxDepth =
resetPixStore->depth();
00263
00264 QImage tmpImage(w, h, maxDepth);
00265
00266
int x,y;
00267
for(x = 0; x<w; x++)
00268 {
00269
for(y = 0; y<h; y++)
00270 {
00271 QRgb v1 = oldImg.pixel(x,y);
00272 QRgb v2 = newImg.pixel(x,y);
00273
int r = (
int) (alpha* qRed(v2) + (1-alpha)*qRed(v1));
00274
int g = (
int) (alpha* qGreen(v2) + (1-alpha)*qGreen(v1));
00275
int b = (
int) (alpha* qBlue(v2) + (1-alpha)*qBlue(v1));
00276
00277 tmpImage.setPixel(x, y, qRgb(r,g,
b) );
00278 }
00279 }
00280
00281
00282 QPixmap tmpPixmap(step,
pixStore->height() );
00283 tmpPixmap.convertFromImage( tmpImage );
00284 QLabel::setPixmap( tmpPixmap );
00285
00286
00287
00288
00289
00290
00291
if(h2 < h1)
00292 repaint(
true);
00293
else
00294 repaint(
false);
00295 }
00296 }
00297
00298
else if(step != lastStep &&
00299 (
00300
animationType !=
DISAPPEAR_IMMEDIATELY ||
00301 (
animationType ==
DISAPPEAR_IMMEDIATELY && !
resettingImage)
00302 )
00303 )
00304 {
00305
00306
if(step == 0)
00307 {
00308 QLabel::setPixmap( NULL );
00309 emit
pixmapRemoved();
00310 repaint(
true);
00311 }
00312
00313
else if(step ==
pixStore->width() )
00314 {
00315 QLabel::setPixmap( *
pixStore );
00316 repaint(
false);
00317 }
00318
00319
else
00320 {
00321
00322 QImage tmpImage(step,
pixStore->height(),
pixStore->depth() );
00323
int x,y;
00324
for(x = 0; x<step; x++)
00325 {
00326
for(y = 0; y<
pixStore->height(); y++)
00327 {
00328
if(
animationType ==
SLIDE_IN_LEFT ||
00329
animationType ==
SLIDE_OUT_LEFT)
00330 { tmpImage.setPixel( x, y,
pixStore->pixel(
pixStore->width()-step+x,y) ); }
00331
else
00332 { tmpImage.setPixel( x, y,
pixStore->pixel(x,y) ); }
00333 }
00334 }
00335
00336
00337 QPixmap tmpPixmap(step,
pixStore->height() );
00338 tmpPixmap.convertFromImage( tmpImage );
00339 QLabel::setPixmap( tmpPixmap );
00340
00341
if(
animationType ==
SLIDE_OUT_LEFT ||
00342
animationType ==
SLIDE_OUT_RIGHT)
00343 repaint(
true);
00344
else
00345 repaint(
false);
00346 }
00347 }
00348
00349
00350
if(
00351 ((
animationType ==
SLIDE_IN_LEFT ||
00352
animationType ==
SLIDE_IN_RIGHT) && step <
pixStore->width()) ||
00353 ((
animationType ==
SLIDE_OUT_LEFT ||
00354
animationType ==
SLIDE_OUT_RIGHT) && step > 0) ||
00355 (
animationType ==
FADE_TRANSITION && step < 100)
00356 )
00357 {
00358
00359
delay =
delay -
accel;
00360
if(
delay <
minDelay)
delay =
minDelay;
00361
00362
00363
timer->start(
delay, TRUE );
00364 }
00365
00366
00367
else
00368 {
00369
00370
if(step == 0)
00371 {
00372
imageShown =
false;
00373
delete pixStore;
00374
pixStore = NULL;
00375 }
00376
else
00377 {
00378
imageShown =
true;
00379 }
00380
00381
00382
00383
if(
resettingImage &&
animationType !=
FADE_TRANSITION)
00384 {
00385
resettingImage =
false;
00386
00387
if(
pixStore)
00388 {
00389
00390
delete pixStore;
00391
pixStore = NULL;
00392 }
00393
00394
pixStore =
resetPixStore;
00395 resetPixStore = NULL;
00396
animationType =
resetMethod;
00397
animatePixmap();
00398 }
00399
00400
else
00401 {
00402
00403
if(
animationType ==
FADE_TRANSITION )
00404 {
00405
resettingImage =
false;
00406
delete pixStore;
00407
pixStore =
resetPixStore;
00408 resetPixStore = NULL;
00409 }
00410
00411
00412
queueMutex.lock();
00413
00414
00415
cleanStack();
00416
00417
if(
delayedActionHead == NULL)
00418 {
00419
00420
queueMutex.unlock();
00421
animatingBoolMutex.lock();
00422
animating =
false;
00423
animatingBoolMutex.unlock();
00424
return;
00425 }
00426
00427
00428
Action* currAction =
delayedActionHead;
00429 delayedActionHead = delayedActionHead->
getNext();
00430
if(delayedActionHead == NULL)
00431
delayedActionTail = NULL;
00432
00433
queueMutex.unlock();
00434
00435
00436
if(currAction->
getImage() == NULL)
internalRemovePixmap();
00437
else internalSetPixmap( *currAction->
getImage() );
00438
00439
00440
delete currAction;
00441 }
00442 }
00443
00444 }
00445
00446 void ALabel::drawContents( QPainter* p )
00447 {
00448
00449 QLabel::drawContents(p);
00450
00451
00452
if(!
animating &&
imageShown &&
drawHoverOverImage)
00453 {
00454 QRect r = style().itemRect( p, contentsRect(), alignment(), isEnabled(), pixmap(), text());
00455
00456
int minDim = r.width();
00457
if(r.height() < minDim)
00458 minDim = r.height();
00459
if(minDim >
hoverOverImage->width())
00460 {
00461 r.setLeft( r.right() -
hoverOverImage->width() );
00462 r.setBottom( r.top() +
hoverOverImage->height() );
00463
hoverOverRect = r;
00464 p->drawPixmap( r, *
hoverOverImage);
00465 }
00466
else
00467 {
00468 QImage resizedImage =
hoverOverImage->convertToImage().scale(minDim, minDim);
00469 QPixmap resizedPixmap(resizedImage);
00470 r.setLeft( r.right() - resizedPixmap.width() );
00471 r.setBottom( r.top() + resizedPixmap.height() );
00472
hoverOverRect = r;
00473 p->drawPixmap( r, resizedPixmap);
00474 }
00475 }
00476 }
00477
00478 void ALabel::enterEvent( QEvent*)
00479 {
00480
if(
hoverOverImage)
00481 {
00482
drawHoverOverImage =
true;
00483 repaint(
false );
00484 }
00485 }
00486
00487 void ALabel::leaveEvent( QEvent*)
00488 {
00489
if(
hoverOverImage)
00490 {
00491
drawHoverOverImage =
false;
00492 repaint(
false);
00493 }
00494 }
00495
00496 void ALabel::mousePressEvent( QMouseEvent* )
00497 { emit
mousePress(); }
00498
00499 void ALabel::mouseReleaseEvent( QMouseEvent* e)
00500 {
00501
00502
if(
hoverOverImage == NULL )
return;
00503
00504 QPainter* p =
new QPainter();
00505 QRect r = style().itemRect( p, contentsRect(), alignment(), isEnabled(), pixmap(), text());
00506
delete p;
00507
int minDim = r.width();
00508
if(r.height() < minDim)
00509 minDim = r.height();
00510
if(minDim >
hoverOverImage->width())
00511 {
00512 r.setLeft( r.right() -
hoverOverImage->width() );
00513 r.setBottom( r.top() +
hoverOverImage->height() );
00514 }
00515
else
00516 {
00517 QImage resizedImage =
hoverOverImage->convertToImage().scale(minDim, minDim);
00518 QPixmap resizedPixmap(resizedImage);
00519 r.setLeft( r.right() - resizedPixmap.width() );
00520 r.setBottom( r.top() + resizedPixmap.height() );
00521 }
00522
00523
if(r.contains( e->pos() ) )
00524 {
00525
removePixmap();
00526 emit
mouseRelease();
00527 }
00528 }
00529
00530 void ALabel::mouseDoubleClickEvent( QMouseEvent* )
00531 { emit
mouseDoubleClick(); }
00532
00533 void ALabel::mouseMoveEvent( QMouseEvent* e)
00534 {
00535
00536
if( !
drawHoverOverImage )
00537
return;
00538
00539
00540
if( !
handCursorShown &&
hoverOverRect.contains( e->x(), e->y() ) )
00541 {
00542 setCursor( QCursor( Qt::PointingHandCursor ) );
00543
handCursorShown =
true;
00544
return;
00545 }
00546
00547
00548
if(
handCursorShown && !
hoverOverRect.contains( e->x(), e->y() ) )
00549 {
00550 setCursor( QCursor( Qt::ArrowCursor ) );
00551
handCursorShown =
false;
00552
return;
00553 }
00554 }
00555
00556 void ALabel::appendJob(QPixmap* pix)
00557 {
00558
Action* newAct =
new Action(pix);
00559
if(
delayedActionHead == NULL)
00560
delayedActionHead = newAct;
00561
else
00562
delayedActionTail->
setNext( newAct );
00563
00564
delayedActionTail = newAct;
00565 }
00566
00567 void ALabel::cleanStack()
00568 {
00569
00570
if(
delayedActionHead == NULL)
00571
return;
00572
00573
00574
if(
pixStore == NULL)
00575 {
00576
Action* currAction =
delayedActionHead;
00577
while(currAction != NULL && currAction->
getImage() == NULL)
00578 {
00579
Action* next = currAction->
getNext();
00580
delete currAction;
00581 currAction = next;
00582 }
00583
00584 delayedActionHead = currAction;
00585
if(currAction == NULL)
00586
delayedActionTail = NULL;
00587 }
00588
00589
00590
if(
delayedActionHead ==
delayedActionTail)
00591
return;
00592
00593
00594
if(
delayedActionTail->
getImage() != NULL)
00595 {
00596
Action* temp =
delayedActionHead;
00597 delayedActionHead =
delayedActionTail;
00598
while(temp != delayedActionHead)
00599 {
00600
Action* next = temp->
getNext();
00601
delete temp;
00602 temp = next;
00603 }
00604
return;
00605 }
00606
00607
00608
if(
pixStore == NULL)
00609 {
00610
Action* temp =
delayedActionHead;
00611
while(temp != NULL)
00612 {
00613
Action* next = temp->
getNext();
00614
delete temp;
00615 temp = next;
00616 }
00617 delayedActionHead = NULL;
00618
delayedActionTail = NULL;
00619
return;
00620 }
00621
00622
else
00623 {
00624
Action* temp =
delayedActionHead;
00625
while(temp !=
delayedActionTail)
00626 {
00627
Action* next = temp->
getNext();
00628
delete temp;
00629 temp = next;
00630 }
00631 delayedActionHead =
delayedActionTail;
00632
return;
00633 }
00634 }
00635
00636 Action::Action(QPixmap* image)
00637 {
00638 this->image = image;
00639
next = NULL;
00640 }
00641
00642 Action::~Action()
00643 {
00644
delete image;
00645
image = NULL;
00646 }
00647
00648 Action*
Action::getNext()
00649 {
return next; }
00650
00651 void Action::setNext(
Action* next)
00652 { this->next = next; }
00653
00654 QPixmap*
Action::getImage()
00655 {
return image; }
00656