AlbumShaper
1.0a3
|
00001 //============================================== 00002 // copyright : (C) 2003-2005 by Will Stokes 00003 //============================================== 00004 // This program is free software; you can redistribute it 00005 // and/or modify it under the terms of the GNU General 00006 // Public License as published by the Free Software 00007 // Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 //============================================== 00010 00011 //Systemwide includes 00012 #include <qapplication.h> 00013 #include <qpainter.h> 00014 #include <qfont.h> 00015 #include <qtimer.h> 00016 #include <qcursor.h> 00017 #include <qpopupmenu.h> 00018 #include <qiconset.h> 00019 #include <qdir.h> 00020 00021 //Projectwide includes 00022 #include "presentationWidget.h" 00023 #include "../../config.h" 00024 #include "../../backend/album.h" 00025 #include "../../backend/subalbum.h" 00026 #include "../../backend/photo.h" 00027 #include "../../backend/tools/imageTools.h" 00028 00029 #define USE_ANIMATION true 00030 #define HIDE_MOUSE_DELAY 5000 00031 #define TEXT_MARGIN 4 00032 00033 #include <iostream> 00034 using namespace std; 00035 //============================================== 00036 SlideshowWidget::SlideshowWidget( QWidget* parent, const char* name, WFlags f ) : QWidget(parent,name,f) 00037 { 00038 //to prevent flicker, never erase to a background color 00039 setBackgroundMode( Qt::NoBackground); 00040 00041 //set pointers to null 00042 curAlbum = NULL; 00043 curCollection = NULL; 00044 collectionNum = -1; 00045 curPhoto = NULL; 00046 photoNum = -1; 00047 00048 //no photo loaded yet 00049 photoLoaded = false; 00050 00051 //not animating by default 00052 animating = false; 00053 00054 //default animation method is immediate 00055 type = IMMEDIATE; 00056 00057 //set cur and prev pointers to the two scaled images. these 00058 //pointers will be exchanged when loading new images 00059 currImage = &scaledImage1; 00060 prevImage = &scaledImage2; 00061 00062 //set delay defaults 00063 initDelay = 3; //3 00064 accel = 0.1; // 0.7 00065 minDelay = 1; //0.01 00066 00067 //setup autoplay defaults, autoPlay should be set 00068 //to true/false every time we begin a new slideshow 00069 autoPlayDelay = 4; 00070 autoPlay = true; 00071 displayAutoPlayDelay = false; 00072 00073 displayDebugMessages = false; 00074 //--------------- 00075 //create timer objects and setup signals 00076 animatingTimer = new QTimer(); 00077 connect(animatingTimer, SIGNAL(timeout()), this, SLOT(animate()) ); 00078 00079 autoPlayTimer = new QTimer(); 00080 connect(autoPlayTimer, SIGNAL(timeout()), this, SLOT(advancePhoto()) ); 00081 00082 mouseCursorTimer = new QTimer(); 00083 connect(mouseCursorTimer, SIGNAL(timeout()), this, SLOT(hideMouse()) ); 00084 //--------------- 00085 //ensure pixmap are same size as screen 00086 QDesktopWidget *desktop = QApplication::desktop(); 00087 screenWidth = desktop->screenGeometry().width(); 00088 screenHeight = desktop->screenGeometry().height(); 00089 paintBuffer1.resize( screenWidth, screenHeight ); 00090 paintBuffer2.resize( screenWidth, screenHeight ); 00091 screenBuffer.resize( screenWidth, screenHeight ); 00092 screenBuffer.fill( black ); 00093 00094 paintBufferPrev = &paintBuffer1; 00095 paintBufferCurr = &paintBuffer2; 00096 00097 //load speed icons 00098 speed1.load( QString(IMAGE_PATH)+"miscImages/cheetah.png" ); 00099 speed2.load( QString(IMAGE_PATH)+"miscImages/rabbit.png" ); 00100 speed4.load( QString(IMAGE_PATH)+"miscImages/turtle.png" ); 00101 speed8.load( QString(IMAGE_PATH)+"miscImages/snail.png" ); 00102 00103 //load play and pause control interfaces 00104 playInterface.load( QString(IMAGE_PATH)+"buttonIcons/playPresentation.png" ); 00105 pauseInterface.load( QString(IMAGE_PATH)+"buttonIcons/pausePresentation.png" ); 00106 interfaceAlphaMask = pauseInterface.createAlphaMask(); 00107 00108 //by default no context menu object exists 00109 contextMenuShown = false; 00110 contextMenuHidingBool = false; 00111 00112 //set widget to accept keyboard and mouse focus 00113 setFocusPolicy(QWidget::StrongFocus); 00114 } 00115 //============================================== 00116 void SlideshowWidget::stop() 00117 { 00118 //stop auto-advance, animation, and hiding mouse cursor timers 00119 autoPlayTimer->stop(); 00120 animatingTimer->stop(); 00121 mouseCursorTimer->stop(); 00122 00123 //set the photo loaded bool to false to 00124 //force loading the first photo the next time 00125 //we start a presentation 00126 photoLoaded = false; 00127 00128 //restore the mouse cursor if it was hidden 00129 if(!mouseShown) 00130 { 00131 qApp->restoreOverrideCursor(); 00132 mouseShown = true; 00133 } 00134 00135 //emit exiting signal indicating to hide 00136 //this widget and show normal widgets again 00137 emit endSlideshow(); 00138 } 00139 //============================================== 00140 void SlideshowWidget::keyPressEvent(QKeyEvent *e) 00141 { 00142 if(contextMenuShown) 00143 { 00144 e->ignore(); 00145 return; 00146 } 00147 00148 switch( e->key() ) 00149 { 00150 case Qt::Key_Escape: 00151 stop(); 00152 break; 00153 case Qt::Key_Return: 00154 toggleAutoPlay(); 00155 break; 00156 case Qt::Key_Plus: 00157 case Qt::Key_Equal: 00158 //if control is pressed increase font size 00159 if(e->state() & Qt::ControlButton ) 00160 increaseTextSize(); 00161 else 00162 speedUp(); 00163 break; 00164 case Qt::Key_Minus: 00165 case Qt::Key_Underscore: 00166 //if control is pressed decrease font size 00167 if(e->state() & Qt::ControlButton ) 00168 decreaseTextSize(); 00169 else 00170 slowDown(); 00171 break; 00172 case Qt::Key_Left: 00173 backupPhoto(); 00174 break; 00175 case Qt::Key_Right: 00176 advancePhoto(); 00177 break; 00178 case Qt::Key_Up: 00179 backupCollection(); 00180 break; 00181 case Qt::Key_Down: 00182 advanceCollection(); 00183 break; 00184 case Qt::Key_Home: 00185 skipToFirstPhoto(); 00186 break; 00187 case Qt::Key_End: 00188 skipToLastPhoto(); 00189 break; 00190 case Qt::Key_D: 00191 displayDebugMessages = !displayDebugMessages; 00192 refreshScreen(); 00193 break; 00194 default: 00195 e->ignore(); 00196 } 00197 } 00198 //============================================== 00199 void SlideshowWidget::mousePressEvent(QMouseEvent *e) 00200 { 00201 //if not the left mouse button ignore 00202 if(e->button() != Qt::LeftButton) 00203 return; 00204 00205 //if mouse is shown so is the control interface, check to see if 00206 //user clicked one of the interface buttons, if not 00207 //not advance to next photo as normal 00208 if( mouseShown ) 00209 { 00210 bool buttonClicked = false; 00211 int x, y, w, h; 00212 w = pauseInterface.width(); 00213 h = pauseInterface.height(); 00214 x = ( screenWidth - w ) / 2; 00215 y = screenHeight - h - TEXT_MARGIN; 00216 00217 //check if button pressed, must be within interface 00218 //region and a non-transparent pixel 00219 if(e->pos().x() >= x && e->pos().y() >= y && 00220 e->pos().x() <= x+w && e->pos().y() <= y+h && 00221 interfaceAlphaMask.pixel(e->pos().x() - x, e->pos().y() - y) != 0) 00222 { 00223 buttonClicked = true; 00224 00225 //restart the countdown for hiding the mouse and interface 00226 mouseCursorTimer->stop(); 00227 mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE ); 00228 00229 int xMid = x + (w/2); 00230 int yMid = y + (h/2); 00231 int dx = e->pos().x() - xMid; 00232 int dy = e->pos().y() - yMid; 00233 int distSqrd = dx*dx + dy*dy; 00234 //center play/pause button is 55 pixels in radius 00235 if(distSqrd <= 3025) 00236 toggleAutoPlay(); 00237 //else one of the other buttons has been pressed 00238 else 00239 { 00240 if(e->pos().x() < xMid) 00241 { 00242 //top left is prev photo button 00243 if(e->pos().y() < yMid) 00244 backupPhoto(); 00245 //bottom left is prev collection button 00246 else 00247 backupCollection(); 00248 } 00249 else 00250 { 00251 //top right is next photo button 00252 if(e->pos().y() < yMid) 00253 advancePhoto(); 00254 //bottom right is next collection button 00255 else 00256 advanceCollection(); 00257 } 00258 } 00259 } 00260 00261 } 00262 } 00263 //============================================== 00264 void SlideshowWidget::mouseMoveEvent(QMouseEvent *) 00265 { 00266 //mouse move events often are triggered when we are exiting 00267 //don't restart hiding mouse in these scenarios 00268 if(!photoLoaded) 00269 return; 00270 00271 mouseCursorTimer->stop(); 00272 00273 //restore the mouse cursor 00274 //hide again if inactive for three seconds 00275 //if mouse not already shown repaint 00276 if(!mouseShown) 00277 { 00278 qApp->restoreOverrideCursor(); 00279 mouseShown = true; 00280 paintOverlaidControls(); 00281 } 00282 00283 mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE ); 00284 } 00285 //============================================== 00286 void SlideshowWidget::contextMenuEvent ( QContextMenuEvent * e ) 00287 { 00288 //disable hiding the mouse cursor until the context menu is destroyed 00289 mouseCursorTimer->stop(); 00290 00291 //disable autoPlay temporarily while context menu is open, drop shadows look horrid if 00292 //photo scrolls while menu is up anyways 00293 autoPlayTimer->stop(); 00294 00295 QPopupMenu contextMenu(this); 00296 contextMenuShown = true; 00297 connect( &contextMenu, SIGNAL( aboutToHide() ), this, SLOT( contextMenuHiding() ) ); 00298 00299 if(autoPlay) 00300 contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/pause.png") ), 00301 tr("Pause"), this, SLOT(toggleAutoPlay()), Key_Return ); 00302 else 00303 contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/play.png") ), 00304 tr("Play"), this, SLOT(toggleAutoPlay()), Key_Return ); 00305 00306 int speedUpID = contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/speedUp.png") ), 00307 tr("Speed Up"), this, SLOT(speedUp()), Key_Plus ); 00308 int slowDownID = contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/slowDown.png") ), 00309 tr("Slow Down"), this, SLOT(slowDown()), Key_Minus ); 00310 00311 //if not currently playing disable speeding up/slowing down options 00312 if(!autoPlay) 00313 { 00314 contextMenu.setItemEnabled( speedUpID, false ); 00315 contextMenu.setItemEnabled( slowDownID, false ); 00316 } 00317 00318 QPopupMenu navigateMenu(&contextMenu); 00319 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/backupPhoto.png") ), 00320 tr("Backup Photo"), this, SLOT(backupPhoto()), Key_Left ); 00321 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/advancePhoto.png") ), 00322 tr("Advance Photo"), this, SLOT(advancePhoto()), Key_Right ); 00323 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/skipToFirstPhoto.png") ), 00324 tr("Skip to First Photo"), this, SLOT(skipToFirstPhoto()), Key_Home ); 00325 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/skipToLastPhoto.png") ), 00326 tr("Skip to Last Photo"), this, SLOT(skipToLastPhoto()), Key_End ); 00327 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/backupCollection.png") ), 00328 tr("Backup Collection"), this, SLOT(backupCollection()), Key_Up ); 00329 navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/advanceCollection.png") ), 00330 tr("Advance Collection"), this, SLOT(advanceCollection()), Key_Down ); 00331 contextMenu.insertItem( tr("Navigate"), &navigateMenu ); 00332 00333 contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/increaseTextSize.png") ), 00334 tr("Increase Text Size"), this, SLOT(increaseTextSize()), CTRL+Key_Plus ); 00335 contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/decreaseTextSize.png") ), 00336 tr("Decrease Text Size"), this, SLOT(decreaseTextSize()), CTRL+Key_Minus ); 00337 00338 contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/exit.png") ), 00339 tr("Exit"), this, SLOT(stop()), Key_Escape ); 00340 00341 contextMenu.exec( QPoint(e->globalX(), e->globalY()) ); 00342 contextMenuShown = false; 00343 } 00344 //============================================== 00345 void SlideshowWidget::contextMenuHiding() 00346 { 00347 contextMenuHidingBool = true; 00348 00349 //start back up timer for hiding the mouse cursor 00350 mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE ); 00351 00352 //if autoPlay is enabled start that timer back up too 00353 if(autoPlay) 00354 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00355 } 00356 //============================================== 00357 void SlideshowWidget::toggleAutoPlay() 00358 { 00359 if(autoPlay) 00360 { 00361 autoPlayTimer->stop(); 00362 autoPlay = false; 00363 refreshScreen(); 00364 } 00365 else 00366 { 00367 displayAutoPlayDelay = true; 00368 autoPlay = true; 00369 refreshScreen(); 00370 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00371 } 00372 } 00373 //============================================== 00374 void SlideshowWidget::hideMouse() 00375 { 00376 qApp->setOverrideCursor( QCursor(Qt::BlankCursor)); 00377 mouseShown = false; 00378 refreshScreen(); 00379 } 00380 //============================================== 00381 void SlideshowWidget::paintEvent( QPaintEvent * ) 00382 { 00383 //blit the screen buffer to the screen 00384 bitBlt( this, 0, 0, &screenBuffer, 00385 0, 0, screenBuffer.width(), screenBuffer.height(), 00386 CopyROP, true ); 00387 } 00388 //============================================== 00389 void SlideshowWidget::loadPhoto() 00390 { 00391 //exchange prev and curr pointers 00392 QImage* tmp = prevImage; 00393 prevImage = currImage; 00394 currImage = tmp; 00395 00396 //scale full size image to fit screen 00397 scaleImage( curPhoto->getImageFilename(),*currImage, 00398 screenWidth, screenHeight ); 00399 photoLoaded = true; 00400 } 00401 //============================================== 00402 void SlideshowWidget::showPhoto() 00403 { 00404 QString tempString = ""; 00405 int x, y; 00406 00407 paintBufferCurr->fill(black); 00408 QPainter p; 00409 //------------------------------ 00410 //paint photo 00411 p.begin( paintBufferCurr ); 00412 p.drawImage( (paintBufferCurr->width() - currImage->width() ) / 2, 00413 (paintBufferCurr->height() - currImage->height() ) / 2, 00414 *currImage ); 00415 //------------------------------ 00416 //setup font stuff for writing text 00417 p.setPen(QColor("black")); 00418 QFont f( "times", fontSize, QFont::Bold ); 00419 QFontMetrics fm( f ); 00420 p.setFont( f ); 00421 //------------------------------ 00422 //paint description 00423 tempString = curPhoto->getDescription(); 00424 if(tempString.stripWhiteSpace().length() > 0) 00425 { 00426 x = TEXT_MARGIN; 00427 y = screenHeight - TEXT_MARGIN - fm.height() - 2*TL_TextBorder.height(); 00428 //------- 00429 //top left corner 00430 p.drawImage( x, y, TL_TextBorder ); 00431 00432 //top edge 00433 p.drawImage( QRect( x + TL_TextBorder.width(), y, 00434 fm.width(tempString), TL_TextBorder.height() ), 00435 Top_TextBorder ); 00436 00437 //top right corner 00438 p.drawImage( x + TL_TextBorder.width() + fm.width(tempString), 00439 y, TR_TextBorder ); 00440 //------- 00441 //left edge 00442 p.drawImage( QRect( x, 00443 y + TL_TextBorder.height(), 00444 TL_TextBorder.width(), fm.height() ), 00445 Left_TextBorder ); 00446 00447 //right edge 00448 p.drawImage( QRect( x + TL_TextBorder.width() + fm.width(tempString), 00449 y + TL_TextBorder.height(), 00450 TL_TextBorder.width(), fm.height() ), 00451 Right_TextBorder ); 00452 //------- 00453 //bottom left corner 00454 p.drawImage( x, 00455 y + TL_TextBorder.height() + fm.height(), BL_TextBorder ); 00456 00457 //bottom edge 00458 p.drawImage( QRect( x + TL_TextBorder.width(), 00459 y + TL_TextBorder.height() + fm.height(), 00460 fm.width(tempString), TL_TextBorder.height() ), 00461 Bottom_TextBorder ); 00462 00463 //bottom right corner 00464 p.drawImage( x + TL_TextBorder.width() + fm.width(tempString), 00465 y + TL_TextBorder.height() + fm.height(), BR_TextBorder ); 00466 //------- 00467 p.fillRect( x + TL_TextBorder.width(), y + TL_TextBorder.height(), 00468 fm.width(tempString), fm.height(), QBrush(QColor("white")) ); 00469 p.drawText( x + TL_TextBorder.width(), y + TL_TextBorder.height() + fm.ascent(), tempString ); 00470 } 00471 //------------------------------ 00472 p.end(); 00473 } 00474 //============================================== 00475 void SlideshowWidget::beginSlideshow(Album* albm, Subalbum* startCollection, Photo* startPhoto) 00476 { 00477 autoPlay = true; 00478 autoPlayDelay = 4; 00479 displayAutoPlayDelay = true; 00480 displayDebugMessages = false; 00481 fontSize = 24; 00482 00483 //store album handle and show cover page 00484 curAlbum = albm; 00485 00486 //determine presentation resources path 00487 QString presentationResourcesPath; 00488 QDir tempDir( THEMES_PATH ); 00489 00490 //if theme installed on system using its resources 00491 if( tempDir.exists( THEMES_PATH + albm->getTheme()) ) 00492 { 00493 presentationResourcesPath = THEMES_PATH + albm->getTheme() + "/misc_resources/"; 00494 } 00495 //else try to load resources from the saved album path, this is necessary 00496 //when viewing albums on machines that do not have the used theme installed 00497 else 00498 { 00499 presentationResourcesPath = albm->getSaveLocation() + "/misc_resources/"; 00500 } 00501 00502 //load text border images 00503 Top_TextBorder.load(presentationResourcesPath + "Top_TextBorder.png" ); 00504 Bottom_TextBorder.load(presentationResourcesPath + "Bottom_TextBorder.png" ); 00505 Left_TextBorder.load(presentationResourcesPath + "Left_TextBorder.png" ); 00506 Right_TextBorder.load(presentationResourcesPath + "Right_TextBorder.png" ); 00507 TL_TextBorder.load(presentationResourcesPath + "TL_TextBorder.png" ); 00508 TR_TextBorder.load(presentationResourcesPath + "TR_TextBorder.png" ); 00509 BL_TextBorder.load(presentationResourcesPath + "BL_TextBorder.png" ); 00510 BR_TextBorder.load(presentationResourcesPath + "BR_TextBorder.png" ); 00511 00512 qApp->setOverrideCursor( QCursor(Qt::BlankCursor)); 00513 mouseShown = false; 00514 setMouseTracking(true); 00515 /* showCoverPage();*/ 00516 00517 //if collection and photo pointers are not null go immediately to specified collection/photo 00518 if(startCollection != NULL && startPhoto != NULL) 00519 { 00520 //set photo and collection pointers 00521 curPhoto = startPhoto; 00522 curCollection = startCollection; 00523 00524 //set photo and collection count #'s 00525 collectionNum = 1; 00526 Subalbum* tmpCollection = albm->getFirstSubalbum(); 00527 while(tmpCollection != NULL && tmpCollection != curCollection) 00528 { 00529 tmpCollection = tmpCollection->getNext(); 00530 collectionNum++; 00531 } 00532 photoNum = 1; 00533 Photo* tmpPhoto = curCollection->getFirst(); 00534 while(tmpPhoto != NULL && tmpPhoto!= curPhoto) 00535 { 00536 tmpPhoto = tmpPhoto->getNext(); 00537 photoNum++; 00538 } 00539 00540 //load photo and display 00541 loadPhoto(); 00542 refreshScreen(); 00543 00544 //start auto-advance counter 00545 if(autoPlay) 00546 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00547 } 00548 //otherwise show album cover page 00549 else { showCoverPage(); } 00550 } 00551 //============================================== 00552 void SlideshowWidget::showCoverPage() 00553 { 00554 //for now just bring up first collection 00555 collectionNum = 1; 00556 showCollectionPage(curAlbum->getFirstSubalbum() ); 00557 } 00558 //============================================== 00559 void SlideshowWidget::showCollectionPage(Subalbum* subalbum) 00560 { 00561 //set subalbum pointer 00562 curCollection = subalbum; 00563 00564 //for now load up first photo 00565 curPhoto = curCollection->getFirst(); 00566 photoNum = 1; 00567 00568 loadPhoto(); 00569 refreshScreen(); 00570 if(autoPlay) 00571 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00572 } 00573 //============================================== 00574 void SlideshowWidget::speedUp() 00575 { 00576 if(autoPlay && autoPlayDelay > 1) 00577 { 00578 autoPlayTimer->stop(); 00579 autoPlayDelay = autoPlayDelay / 2; 00580 displayAutoPlayDelay = true; 00581 refreshScreen(); 00582 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00583 } 00584 } 00585 //============================================== 00586 void SlideshowWidget::slowDown() 00587 { 00588 if(autoPlay && autoPlayDelay < 8) 00589 { 00590 autoPlayTimer->stop(); 00591 autoPlayDelay = autoPlayDelay * 2; 00592 displayAutoPlayDelay = true; 00593 refreshScreen(); 00594 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00595 } 00596 } 00597 //============================================== 00598 void SlideshowWidget::increaseTextSize() 00599 { 00600 fontSize++; 00601 refreshScreen(); 00602 } 00603 //============================================== 00604 void SlideshowWidget::decreaseTextSize() 00605 { 00606 fontSize--; 00607 refreshScreen(); 00608 } 00609 //============================================== 00610 void SlideshowWidget::advancePhoto() 00611 { 00612 //bail if currently animating 00613 animatingMutex.lock(); 00614 if(animating) 00615 { 00616 animatingMutex.unlock(); 00617 return; 00618 } 00619 00620 //stop autoPlay timer so next advance only occur after delay after advance is complete 00621 autoPlayTimer->stop(); 00622 00623 animating = true; 00624 if(USE_ANIMATION) 00625 type = SCROLL_LEFT; 00626 else 00627 type = IMMEDIATE; 00628 animatingMutex.unlock(); 00629 00630 if(curPhoto->getNext() == NULL) 00631 { advanceCollection(); } 00632 else 00633 { 00634 //load and display new photo 00635 curPhoto = curPhoto->getNext(); 00636 photoNum++; 00637 loadPhoto(); 00638 exchangePhotos(); 00639 } 00640 } 00641 //============================================== 00642 void SlideshowWidget::backupPhoto() 00643 { 00644 //bail if currently animating 00645 animatingMutex.lock(); 00646 if(animating) 00647 { 00648 animatingMutex.unlock(); 00649 return; 00650 } 00651 00652 animating = true; 00653 if(USE_ANIMATION) 00654 type = SCROLL_RIGHT; 00655 else 00656 type = IMMEDIATE; 00657 animatingMutex.unlock(); 00658 00659 if(curPhoto->getPrev() == NULL) 00660 { backupCollection(); } 00661 else 00662 { 00663 //load and display new photo 00664 curPhoto = curPhoto->getPrev(); 00665 photoNum--; 00666 loadPhoto(); 00667 exchangePhotos(); 00668 } 00669 } 00670 //============================================== 00671 void SlideshowWidget::skipToFirstPhoto() 00672 { 00673 //bail if already at first photo in collection 00674 if(curPhoto == curCollection->getFirst()) 00675 return; 00676 00677 //bail if currently animating 00678 animatingMutex.lock(); 00679 if(animating) 00680 { 00681 animatingMutex.unlock(); 00682 return; 00683 } 00684 00685 animating = true; 00686 if(USE_ANIMATION) 00687 type = SCROLL_RIGHT; 00688 else 00689 type = IMMEDIATE; 00690 animatingMutex.unlock(); 00691 00692 curPhoto = curCollection->getFirst(); 00693 photoNum = 1; 00694 //load and display new photo 00695 loadPhoto(); 00696 exchangePhotos(); 00697 } 00698 //============================================== 00699 void SlideshowWidget::skipToLastPhoto() 00700 { 00701 //bail if already at last photo in collection 00702 if(curPhoto == curCollection->getLast()) 00703 return; 00704 00705 //bail if currently animating 00706 animatingMutex.lock(); 00707 if(animating) 00708 { 00709 animatingMutex.unlock(); 00710 return; 00711 } 00712 00713 animating = true; 00714 if(USE_ANIMATION) 00715 type = SCROLL_LEFT; 00716 else 00717 type = IMMEDIATE; 00718 animatingMutex.unlock(); 00719 00720 curPhoto = curCollection->getLast(); 00721 photoNum = curCollection->getNumPhotos(); 00722 00723 //load and display new photo 00724 loadPhoto(); 00725 exchangePhotos(); 00726 } 00727 //============================================== 00728 void SlideshowWidget::advanceCollection() 00729 { 00730 if(USE_ANIMATION) 00731 { 00732 if(curCollection->getNext() == NULL && 00733 curCollection == curAlbum->getFirstSubalbum() ) 00734 type = SCROLL_RIGHT; 00735 else 00736 type = SCROLL_UP; 00737 } 00738 else 00739 type = IMMEDIATE; 00740 00741 //keep advancing collections until we find one with a photo in it 00742 curPhoto = NULL; 00743 while(curPhoto == NULL) 00744 { 00745 curCollection = curCollection->getNext(); 00746 collectionNum++; 00747 if(!curCollection) 00748 { 00749 curCollection = curAlbum->getFirstSubalbum(); 00750 collectionNum = 1; 00751 } 00752 00753 curPhoto = curCollection->getFirst(); 00754 } 00755 photoNum = 1; 00756 00757 //load and display new photo 00758 loadPhoto(); 00759 exchangePhotos(); 00760 } 00761 //============================================== 00762 void SlideshowWidget::backupCollection() 00763 { 00764 if(USE_ANIMATION) 00765 { 00766 if(curCollection->getPrev() == NULL && 00767 curCollection == curAlbum->getLastSubalbum() ) 00768 type = SCROLL_RIGHT; 00769 else 00770 type = SCROLL_DOWN; 00771 } 00772 else 00773 type = IMMEDIATE; 00774 00775 //keep backing up collections until we find one with a photo in it 00776 curPhoto = NULL; 00777 while(curPhoto == NULL) 00778 { 00779 curCollection = curCollection->getPrev(); 00780 collectionNum--; 00781 if(!curCollection) 00782 { 00783 curCollection = curAlbum->getLastSubalbum(); 00784 collectionNum = curAlbum->getNumSubalbums(); 00785 } 00786 00787 curPhoto = curCollection->getLast(); 00788 } 00789 photoNum = curCollection->getNumPhotos(); 00790 00791 //load and display new photo 00792 loadPhoto(); 00793 exchangePhotos(); 00794 } 00795 //============================================== 00796 void SlideshowWidget::animate() 00797 { 00798 //--------------------------------- 00799 //determine new number of columns to be shown 00800 00801 //determine # of ms that have passed since last redraw 00802 currentTime.start(); 00803 double ms = lastTime.msecsTo(currentTime); 00804 00805 //determine increment 00806 int inc = (int)(ms/delay); 00807 00808 //if increment is not zero then update last time 00809 if(inc != 0) 00810 { 00811 lastTime = currentTime; 00812 } 00813 00814 //update number of columns shown 00815 step+=inc; 00816 00817 //boundary conditions 00818 if( step > screenWidth && (type == SCROLL_LEFT || type == SCROLL_RIGHT) ) 00819 step = screenWidth; 00820 if( step > screenHeight && (type == SCROLL_UP || type == SCROLL_DOWN) ) 00821 step = screenHeight; 00822 00823 //if step changed then redraw 00824 if(step != lastStep) 00825 { 00826 if(type == SCROLL_LEFT) 00827 { 00828 bitBlt( &screenBuffer, 0, 0, 00829 paintBufferPrev, 00830 step, 0, 00831 paintBufferPrev->width() - step, paintBufferPrev->height(), 00832 CopyROP, true ); 00833 bitBlt( &screenBuffer, paintBufferCurr->width() - step, 0, 00834 paintBufferCurr, 00835 0, 0, step, paintBufferCurr->height(), 00836 CopyROP, true ); 00837 } 00838 else if(type == SCROLL_RIGHT) 00839 { 00840 bitBlt( &screenBuffer, step, 0, 00841 paintBufferPrev, 00842 0, 0, 00843 paintBufferPrev->width() - step, paintBufferPrev->height(), 00844 CopyROP, true ); 00845 bitBlt( &screenBuffer, 0, 0, 00846 paintBufferCurr, 00847 paintBufferCurr->width() - step, 0, step, paintBufferCurr->height(), 00848 CopyROP, true ); 00849 } 00850 else if(type == SCROLL_UP) 00851 { 00852 bitBlt( &screenBuffer, 0, 0, 00853 paintBufferPrev, 00854 0, step, 00855 paintBufferPrev->width(), paintBufferPrev->height() - step, 00856 CopyROP, true ); 00857 bitBlt( &screenBuffer, 0, paintBufferCurr->height() - step, 00858 paintBufferCurr, 00859 0, 0, paintBufferCurr->width(), step, 00860 CopyROP, true ); 00861 } 00862 else if(type == SCROLL_DOWN) 00863 { 00864 bitBlt( &screenBuffer, 0, step, 00865 paintBufferPrev, 00866 0, 0, 00867 paintBufferPrev->width(), paintBufferPrev->height() - step, 00868 CopyROP, true ); 00869 bitBlt( &screenBuffer, 0, 0, 00870 paintBufferCurr, 00871 0, paintBufferCurr->height() - step, paintBufferCurr->width(), step, 00872 CopyROP, true ); 00873 } 00874 00875 //paint overlaid controls 00876 paintOverlaidControls(); 00877 00878 //blit to screen 00879 repaint(false); 00880 00881 lastStep = step; 00882 00883 //not done animating, reiterate 00884 if( 00885 ( 00886 step < screenWidth && 00887 (type == SCROLL_LEFT || type == SCROLL_RIGHT) 00888 ) || 00889 ( 00890 step < screenHeight && 00891 (type == SCROLL_UP || type == SCROLL_DOWN) 00892 ) 00893 ) 00894 { 00895 //update speed 00896 delay = delay * accel; 00897 if(delay < minDelay) delay = minDelay ; 00898 00899 //restart timer 00900 animatingTimer->start( (int)delay, TRUE ); 00901 } 00902 //done animating.... 00903 else 00904 { 00905 animating = false; 00906 00907 //if using debug messages use refreshScreen method which actually displays these. 00908 //such messages are laid on time and thus not shown when transitioning 00909 if(displayDebugMessages) 00910 refreshScreen(); 00911 00912 //if autoplay is enabled restart timer 00913 if(autoPlay) 00914 autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE ); 00915 } 00916 } 00917 else 00918 { 00919 //update speed 00920 delay = delay * accel; 00921 if(delay < minDelay) delay = minDelay; 00922 00923 //restart timer 00924 animatingTimer->start( (int)delay, TRUE ); 00925 } 00926 //--------------------------------------- 00927 } 00928 //============================================== 00929 void SlideshowWidget::exchangePhotos() 00930 { 00931 //if transition is set to immediate then just show new photo 00932 if(type == IMMEDIATE) 00933 { 00934 refreshScreen(); 00935 animating = false; 00936 return; 00937 } 00938 00939 //setup step counter 00940 lastStep = 0; 00941 step = 0; 00942 00943 //set initial delay/speed 00944 delay = initDelay; 00945 00946 //exchange buffers 00947 QPixmap* temp = paintBufferCurr; 00948 paintBufferCurr = paintBufferPrev; 00949 paintBufferPrev = temp; 00950 00951 //paint new image to curr buffer 00952 showPhoto(); 00953 00954 //find current time, used to decide how many new columns to reveal in first iteration 00955 lastTime.start(); 00956 00957 //begin animation 00958 animate(); 00959 } 00960 //============================================== 00961 void SlideshowWidget::refreshScreen() 00962 { 00963 //paint current photo to paintBufferCurr 00964 showPhoto(); 00965 00966 //blit to screen buffer 00967 bitBlt( &screenBuffer, 0, 0, 00968 paintBufferCurr, 00969 0, 0, paintBufferCurr->width(), paintBufferCurr->height(), 00970 CopyROP, true ); 00971 00972 //paint overlaid controls 00973 paintOverlaidControls(); 00974 } 00975 //============================================== 00976 void SlideshowWidget::paintOverlaidControls() 00977 { 00978 QString tempString = ""; 00979 int x, y; 00980 00981 //setup painter to screen buffer for laying on top all top level widgets 00982 QPainter p; 00983 p.begin( &screenBuffer ); 00984 //------------------------------ 00985 //setup font stuff for writing text 00986 QFont f( "times", fontSize, QFont::Bold ); 00987 QFontMetrics fm( f ); 00988 p.setFont( f ); 00989 //------------------------------ 00990 //paint autoPlay delay 00991 if(autoPlay && displayAutoPlayDelay) 00992 { 00993 //get handle on right speed icon 00994 QImage* speedIcon; 00995 if(autoPlayDelay == 1) speedIcon = &speed1; 00996 else if(autoPlayDelay == 2) speedIcon = &speed2; 00997 else if(autoPlayDelay == 4) speedIcon = &speed4; 00998 else speedIcon = &speed8; 00999 01000 int maxWidth = speed1.width(); 01001 if(speed2.width() > maxWidth) maxWidth = speed2.width(); 01002 if(speed4.width() > maxWidth) maxWidth = speed4.width(); 01003 if(speed8.width() > maxWidth) maxWidth = speed8.width(); 01004 01005 int maxHeight = speed1.height(); 01006 if(speed2.height() > maxHeight) maxHeight = speed2.height(); 01007 if(speed4.height() > maxHeight) maxHeight = speed4.height(); 01008 if(speed8.height() > maxHeight) maxHeight = speed8.height(); 01009 01010 x = screenWidth - TEXT_MARGIN - speedIcon->width() - (maxWidth - speedIcon->width())/2; 01011 y = screenHeight - TEXT_MARGIN - speedIcon->height() - (maxHeight - speedIcon->height())/2; 01012 01013 p.drawImage( x, y, *speedIcon ); 01014 displayAutoPlayDelay = false; 01015 } 01016 //------------------------------ 01017 //if debugging enabled paint such messages 01018 if(displayDebugMessages) 01019 { 01020 //before debugging message set color to green 01021 p.setPen(QColor("green")); 01022 //------------------------------ 01023 //paint collection number 01024 tempString = QString("(Collection %1 / %2)").arg(collectionNum).arg(curAlbum->getNumSubalbums()); 01025 x = 0; 01026 y = 0; 01027 p.fillRect( x, y, fm.width(tempString), fm.height(), QBrush(QColor("black")) ); 01028 p.drawText( x, y + fm.ascent(), tempString ); 01029 //------------------------------ 01030 //paint photo number 01031 tempString = QString("(Photo %1 / %2)").arg(photoNum).arg(curCollection->getNumPhotos()); 01032 x = screenWidth - fm.width(tempString); 01033 y = 0; 01034 p.fillRect( x, y, fm.width(tempString), fm.height(), QBrush(QColor("black")) ); 01035 p.drawText(x, y + fm.ascent(), tempString ); 01036 } 01037 //------------------------------ 01038 //if the mouse is shown paint the control interface 01039 if(mouseShown) 01040 { 01041 QImage* shownInterface; 01042 if(autoPlay) 01043 shownInterface = &pauseInterface; 01044 else 01045 shownInterface = &playInterface; 01046 01047 x = ( screenWidth - shownInterface->width() ) / 2; 01048 y = screenHeight - shownInterface->height() - TEXT_MARGIN; 01049 p.drawImage( x, y, *shownInterface ); 01050 01051 //paint collection # and photo # 01052 f.setPointSize( 14 ); 01053 fm = QFontMetrics( f ); 01054 tempString = QString("%1 / %2").arg(photoNum).arg(curCollection->getNumPhotos()); 01055 x = x + (shownInterface->width() / 2) - (fm.width(tempString) / 2); 01056 y = y + 104; 01057 p.setFont( f ); 01058 p.setPen(QColor("white")); 01059 p.drawText( x, y, tempString ); 01060 } 01061 //------------------------------ 01062 //ender painter and flast to screen 01063 p.end(); 01064 repaint(false); 01065 } 01066 //============================================== 01067 Subalbum* SlideshowWidget::getCurCollection() { return curCollection; } 01068 //============================================== 01069 Photo* SlideshowWidget::getCurPhoto() { return curPhoto; } 01070 //============================================== 01071