AlbumShaper  1.0a3
presentationWidget.cpp
Go to the documentation of this file.
1 //==============================================
2 // copyright : (C) 2003-2005 by Will Stokes
3 //==============================================
4 // This program is free software; you can redistribute it
5 // and/or modify it under the terms of the GNU General
6 // Public License as published by the Free Software
7 // Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //==============================================
10 
11 //Systemwide includes
12 #include <qapplication.h>
13 #include <qpainter.h>
14 #include <qfont.h>
15 #include <qtimer.h>
16 #include <qcursor.h>
17 #include <qpopupmenu.h>
18 #include <qiconset.h>
19 #include <qdir.h>
20 
21 //Projectwide includes
22 #include "presentationWidget.h"
23 #include "../../config.h"
24 #include "../../backend/album.h"
25 #include "../../backend/subalbum.h"
26 #include "../../backend/photo.h"
27 #include "../../backend/tools/imageTools.h"
28 
29 #define USE_ANIMATION true
30 #define HIDE_MOUSE_DELAY 5000
31 #define TEXT_MARGIN 4
32 
33 #include <iostream>
34 using namespace std;
35 //==============================================
36 SlideshowWidget::SlideshowWidget( QWidget* parent, const char* name, WFlags f ) : QWidget(parent,name,f)
37 {
38  //to prevent flicker, never erase to a background color
39  setBackgroundMode( Qt::NoBackground);
40 
41  //set pointers to null
42  curAlbum = NULL;
43  curCollection = NULL;
44  collectionNum = -1;
45  curPhoto = NULL;
46  photoNum = -1;
47 
48  //no photo loaded yet
49  photoLoaded = false;
50 
51  //not animating by default
52  animating = false;
53 
54  //default animation method is immediate
55  type = IMMEDIATE;
56 
57  //set cur and prev pointers to the two scaled images. these
58  //pointers will be exchanged when loading new images
61 
62  //set delay defaults
63  initDelay = 3; //3
64  accel = 0.1; // 0.7
65  minDelay = 1; //0.01
66 
67  //setup autoplay defaults, autoPlay should be set
68  //to true/false every time we begin a new slideshow
69  autoPlayDelay = 4;
70  autoPlay = true;
71  displayAutoPlayDelay = false;
72 
73  displayDebugMessages = false;
74  //---------------
75  //create timer objects and setup signals
76  animatingTimer = new QTimer();
77  connect(animatingTimer, SIGNAL(timeout()), this, SLOT(animate()) );
78 
79  autoPlayTimer = new QTimer();
80  connect(autoPlayTimer, SIGNAL(timeout()), this, SLOT(advancePhoto()) );
81 
82  mouseCursorTimer = new QTimer();
83  connect(mouseCursorTimer, SIGNAL(timeout()), this, SLOT(hideMouse()) );
84  //---------------
85  //ensure pixmap are same size as screen
86  QDesktopWidget *desktop = QApplication::desktop();
87  screenWidth = desktop->screenGeometry().width();
88  screenHeight = desktop->screenGeometry().height();
92  screenBuffer.fill( black );
93 
96 
97  //load speed icons
98  speed1.load( QString(IMAGE_PATH)+"miscImages/cheetah.png" );
99  speed2.load( QString(IMAGE_PATH)+"miscImages/rabbit.png" );
100  speed4.load( QString(IMAGE_PATH)+"miscImages/turtle.png" );
101  speed8.load( QString(IMAGE_PATH)+"miscImages/snail.png" );
102 
103  //load play and pause control interfaces
104  playInterface.load( QString(IMAGE_PATH)+"buttonIcons/playPresentation.png" );
105  pauseInterface.load( QString(IMAGE_PATH)+"buttonIcons/pausePresentation.png" );
106  interfaceAlphaMask = pauseInterface.createAlphaMask();
107 
108  //by default no context menu object exists
109  contextMenuShown = false;
110  contextMenuHidingBool = false;
111 
112  //set widget to accept keyboard and mouse focus
113  setFocusPolicy(QWidget::StrongFocus);
114 }
115 //==============================================
117 {
118  //stop auto-advance, animation, and hiding mouse cursor timers
119  autoPlayTimer->stop();
120  animatingTimer->stop();
121  mouseCursorTimer->stop();
122 
123  //set the photo loaded bool to false to
124  //force loading the first photo the next time
125  //we start a presentation
126  photoLoaded = false;
127 
128  //restore the mouse cursor if it was hidden
129  if(!mouseShown)
130  {
131  qApp->restoreOverrideCursor();
132  mouseShown = true;
133  }
134 
135  //emit exiting signal indicating to hide
136  //this widget and show normal widgets again
137  emit endSlideshow();
138 }
139 //==============================================
141 {
142  if(contextMenuShown)
143  {
144  e->ignore();
145  return;
146  }
147 
148  switch( e->key() )
149  {
150  case Qt::Key_Escape:
151  stop();
152  break;
153  case Qt::Key_Return:
154  toggleAutoPlay();
155  break;
156  case Qt::Key_Plus:
157  case Qt::Key_Equal:
158  //if control is pressed increase font size
159  if(e->state() & Qt::ControlButton )
161  else
162  speedUp();
163  break;
164  case Qt::Key_Minus:
165  case Qt::Key_Underscore:
166  //if control is pressed decrease font size
167  if(e->state() & Qt::ControlButton )
169  else
170  slowDown();
171  break;
172  case Qt::Key_Left:
173  backupPhoto();
174  break;
175  case Qt::Key_Right:
176  advancePhoto();
177  break;
178  case Qt::Key_Up:
180  break;
181  case Qt::Key_Down:
183  break;
184  case Qt::Key_Home:
186  break;
187  case Qt::Key_End:
188  skipToLastPhoto();
189  break;
190  case Qt::Key_D:
192  refreshScreen();
193  break;
194  default:
195  e->ignore();
196  }
197 }
198 //==============================================
200 {
201  //if not the left mouse button ignore
202  if(e->button() != Qt::LeftButton)
203  return;
204 
205  //if mouse is shown so is the control interface, check to see if
206  //user clicked one of the interface buttons, if not
207  //not advance to next photo as normal
208  if( mouseShown )
209  {
210  bool buttonClicked = false;
211  int x, y, w, h;
212  w = pauseInterface.width();
213  h = pauseInterface.height();
214  x = ( screenWidth - w ) / 2;
215  y = screenHeight - h - TEXT_MARGIN;
216 
217  //check if button pressed, must be within interface
218  //region and a non-transparent pixel
219  if(e->pos().x() >= x && e->pos().y() >= y &&
220  e->pos().x() <= x+w && e->pos().y() <= y+h &&
221  interfaceAlphaMask.pixel(e->pos().x() - x, e->pos().y() - y) != 0)
222  {
223  buttonClicked = true;
224 
225  //restart the countdown for hiding the mouse and interface
226  mouseCursorTimer->stop();
227  mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE );
228 
229  int xMid = x + (w/2);
230  int yMid = y + (h/2);
231  int dx = e->pos().x() - xMid;
232  int dy = e->pos().y() - yMid;
233  int distSqrd = dx*dx + dy*dy;
234  //center play/pause button is 55 pixels in radius
235  if(distSqrd <= 3025)
236  toggleAutoPlay();
237  //else one of the other buttons has been pressed
238  else
239  {
240  if(e->pos().x() < xMid)
241  {
242  //top left is prev photo button
243  if(e->pos().y() < yMid)
244  backupPhoto();
245  //bottom left is prev collection button
246  else
248  }
249  else
250  {
251  //top right is next photo button
252  if(e->pos().y() < yMid)
253  advancePhoto();
254  //bottom right is next collection button
255  else
257  }
258  }
259  }
260 
261  }
262 }
263 //==============================================
265 {
266  //mouse move events often are triggered when we are exiting
267  //don't restart hiding mouse in these scenarios
268  if(!photoLoaded)
269  return;
270 
271  mouseCursorTimer->stop();
272 
273  //restore the mouse cursor
274  //hide again if inactive for three seconds
275  //if mouse not already shown repaint
276  if(!mouseShown)
277  {
278  qApp->restoreOverrideCursor();
279  mouseShown = true;
281  }
282 
283  mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE );
284 }
285 //==============================================
286 void SlideshowWidget::contextMenuEvent ( QContextMenuEvent * e )
287 {
288  //disable hiding the mouse cursor until the context menu is destroyed
289  mouseCursorTimer->stop();
290 
291  //disable autoPlay temporarily while context menu is open, drop shadows look horrid if
292  //photo scrolls while menu is up anyways
293  autoPlayTimer->stop();
294 
295  QPopupMenu contextMenu(this);
296  contextMenuShown = true;
297  connect( &contextMenu, SIGNAL( aboutToHide() ), this, SLOT( contextMenuHiding() ) );
298 
299  if(autoPlay)
300  contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/pause.png") ),
301  tr("Pause"), this, SLOT(toggleAutoPlay()), Key_Return );
302  else
303  contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/play.png") ),
304  tr("Play"), this, SLOT(toggleAutoPlay()), Key_Return );
305 
306  int speedUpID = contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/speedUp.png") ),
307  tr("Speed Up"), this, SLOT(speedUp()), Key_Plus );
308  int slowDownID = contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/slowDown.png") ),
309  tr("Slow Down"), this, SLOT(slowDown()), Key_Minus );
310 
311  //if not currently playing disable speeding up/slowing down options
312  if(!autoPlay)
313  {
314  contextMenu.setItemEnabled( speedUpID, false );
315  contextMenu.setItemEnabled( slowDownID, false );
316  }
317 
318  QPopupMenu navigateMenu(&contextMenu);
319  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/backupPhoto.png") ),
320  tr("Backup Photo"), this, SLOT(backupPhoto()), Key_Left );
321  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/advancePhoto.png") ),
322  tr("Advance Photo"), this, SLOT(advancePhoto()), Key_Right );
323  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/skipToFirstPhoto.png") ),
324  tr("Skip to First Photo"), this, SLOT(skipToFirstPhoto()), Key_Home );
325  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/skipToLastPhoto.png") ),
326  tr("Skip to Last Photo"), this, SLOT(skipToLastPhoto()), Key_End );
327  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/backupCollection.png") ),
328  tr("Backup Collection"), this, SLOT(backupCollection()), Key_Up );
329  navigateMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/advanceCollection.png") ),
330  tr("Advance Collection"), this, SLOT(advanceCollection()), Key_Down );
331  contextMenu.insertItem( tr("Navigate"), &navigateMenu );
332 
333  contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/increaseTextSize.png") ),
334  tr("Increase Text Size"), this, SLOT(increaseTextSize()), CTRL+Key_Plus );
335  contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/decreaseTextSize.png") ),
336  tr("Decrease Text Size"), this, SLOT(decreaseTextSize()), CTRL+Key_Minus );
337 
338  contextMenu.insertItem( QIconSet( QPixmap(QString(IMAGE_PATH)+"menuIcons/exit.png") ),
339  tr("Exit"), this, SLOT(stop()), Key_Escape );
340 
341  contextMenu.exec( QPoint(e->globalX(), e->globalY()) );
342  contextMenuShown = false;
343 }
344 //==============================================
346 {
347  contextMenuHidingBool = true;
348 
349  //start back up timer for hiding the mouse cursor
350  mouseCursorTimer->start( (int)HIDE_MOUSE_DELAY, TRUE );
351 
352  //if autoPlay is enabled start that timer back up too
353  if(autoPlay)
354  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
355 }
356 //==============================================
358 {
359  if(autoPlay)
360  {
361  autoPlayTimer->stop();
362  autoPlay = false;
363  refreshScreen();
364  }
365  else
366  {
367  displayAutoPlayDelay = true;
368  autoPlay = true;
369  refreshScreen();
370  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
371  }
372 }
373 //==============================================
375 {
376  qApp->setOverrideCursor( QCursor(Qt::BlankCursor));
377  mouseShown = false;
378  refreshScreen();
379 }
380 //==============================================
381 void SlideshowWidget::paintEvent( QPaintEvent * )
382 {
383  //blit the screen buffer to the screen
384  bitBlt( this, 0, 0, &screenBuffer,
385  0, 0, screenBuffer.width(), screenBuffer.height(),
386  CopyROP, true );
387 }
388 //==============================================
390 {
391  //exchange prev and curr pointers
392  QImage* tmp = prevImage;
394  currImage = tmp;
395 
396  //scale full size image to fit screen
399  photoLoaded = true;
400 }
401 //==============================================
403 {
404  QString tempString = "";
405  int x, y;
406 
407  paintBufferCurr->fill(black);
408  QPainter p;
409  //------------------------------
410  //paint photo
411  p.begin( paintBufferCurr );
412  p.drawImage( (paintBufferCurr->width() - currImage->width() ) / 2,
413  (paintBufferCurr->height() - currImage->height() ) / 2,
414  *currImage );
415  //------------------------------
416  //setup font stuff for writing text
417  p.setPen(QColor("black"));
418  QFont f( "times", fontSize, QFont::Bold );
419  QFontMetrics fm( f );
420  p.setFont( f );
421  //------------------------------
422  //paint description
423  tempString = curPhoto->getDescription();
424  if(tempString.stripWhiteSpace().length() > 0)
425  {
426  x = TEXT_MARGIN;
427  y = screenHeight - TEXT_MARGIN - fm.height() - 2*TL_TextBorder.height();
428  //-------
429  //top left corner
430  p.drawImage( x, y, TL_TextBorder );
431 
432  //top edge
433  p.drawImage( QRect( x + TL_TextBorder.width(), y,
434  fm.width(tempString), TL_TextBorder.height() ),
435  Top_TextBorder );
436 
437  //top right corner
438  p.drawImage( x + TL_TextBorder.width() + fm.width(tempString),
439  y, TR_TextBorder );
440  //-------
441  //left edge
442  p.drawImage( QRect( x,
443  y + TL_TextBorder.height(),
444  TL_TextBorder.width(), fm.height() ),
445  Left_TextBorder );
446 
447  //right edge
448  p.drawImage( QRect( x + TL_TextBorder.width() + fm.width(tempString),
449  y + TL_TextBorder.height(),
450  TL_TextBorder.width(), fm.height() ),
452  //-------
453  //bottom left corner
454  p.drawImage( x,
455  y + TL_TextBorder.height() + fm.height(), BL_TextBorder );
456 
457  //bottom edge
458  p.drawImage( QRect( x + TL_TextBorder.width(),
459  y + TL_TextBorder.height() + fm.height(),
460  fm.width(tempString), TL_TextBorder.height() ),
462 
463  //bottom right corner
464  p.drawImage( x + TL_TextBorder.width() + fm.width(tempString),
465  y + TL_TextBorder.height() + fm.height(), BR_TextBorder );
466  //-------
467  p.fillRect( x + TL_TextBorder.width(), y + TL_TextBorder.height(),
468  fm.width(tempString), fm.height(), QBrush(QColor("white")) );
469  p.drawText( x + TL_TextBorder.width(), y + TL_TextBorder.height() + fm.ascent(), tempString );
470  }
471  //------------------------------
472  p.end();
473 }
474 //==============================================
475 void SlideshowWidget::beginSlideshow(Album* albm, Subalbum* startCollection, Photo* startPhoto)
476 {
477  autoPlay = true;
478  autoPlayDelay = 4;
479  displayAutoPlayDelay = true;
480  displayDebugMessages = false;
481  fontSize = 24;
482 
483  //store album handle and show cover page
484  curAlbum = albm;
485 
486  //determine presentation resources path
487  QString presentationResourcesPath;
488  QDir tempDir( THEMES_PATH );
489 
490  //if theme installed on system using its resources
491  if( tempDir.exists( THEMES_PATH + albm->getTheme()) )
492  {
493  presentationResourcesPath = THEMES_PATH + albm->getTheme() + "/misc_resources/";
494  }
495  //else try to load resources from the saved album path, this is necessary
496  //when viewing albums on machines that do not have the used theme installed
497  else
498  {
499  presentationResourcesPath = albm->getSaveLocation() + "/misc_resources/";
500  }
501 
502  //load text border images
503  Top_TextBorder.load(presentationResourcesPath + "Top_TextBorder.png" );
504  Bottom_TextBorder.load(presentationResourcesPath + "Bottom_TextBorder.png" );
505  Left_TextBorder.load(presentationResourcesPath + "Left_TextBorder.png" );
506  Right_TextBorder.load(presentationResourcesPath + "Right_TextBorder.png" );
507  TL_TextBorder.load(presentationResourcesPath + "TL_TextBorder.png" );
508  TR_TextBorder.load(presentationResourcesPath + "TR_TextBorder.png" );
509  BL_TextBorder.load(presentationResourcesPath + "BL_TextBorder.png" );
510  BR_TextBorder.load(presentationResourcesPath + "BR_TextBorder.png" );
511 
512  qApp->setOverrideCursor( QCursor(Qt::BlankCursor));
513  mouseShown = false;
514  setMouseTracking(true);
515 /* showCoverPage();*/
516 
517  //if collection and photo pointers are not null go immediately to specified collection/photo
518  if(startCollection != NULL && startPhoto != NULL)
519  {
520  //set photo and collection pointers
521  curPhoto = startPhoto;
522  curCollection = startCollection;
523 
524  //set photo and collection count #'s
525  collectionNum = 1;
526  Subalbum* tmpCollection = albm->getFirstSubalbum();
527  while(tmpCollection != NULL && tmpCollection != curCollection)
528  {
529  tmpCollection = tmpCollection->getNext();
530  collectionNum++;
531  }
532  photoNum = 1;
533  Photo* tmpPhoto = curCollection->getFirst();
534  while(tmpPhoto != NULL && tmpPhoto!= curPhoto)
535  {
536  tmpPhoto = tmpPhoto->getNext();
537  photoNum++;
538  }
539 
540  //load photo and display
541  loadPhoto();
542  refreshScreen();
543 
544  //start auto-advance counter
545  if(autoPlay)
546  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
547  }
548  //otherwise show album cover page
549  else { showCoverPage(); }
550 }
551 //==============================================
553 {
554  //for now just bring up first collection
555  collectionNum = 1;
557 }
558 //==============================================
560 {
561  //set subalbum pointer
562  curCollection = subalbum;
563 
564  //for now load up first photo
566  photoNum = 1;
567 
568  loadPhoto();
569  refreshScreen();
570  if(autoPlay)
571  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
572 }
573 //==============================================
575 {
576  if(autoPlay && autoPlayDelay > 1)
577  {
578  autoPlayTimer->stop();
580  displayAutoPlayDelay = true;
581  refreshScreen();
582  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
583  }
584 }
585 //==============================================
587 {
588  if(autoPlay && autoPlayDelay < 8)
589  {
590  autoPlayTimer->stop();
592  displayAutoPlayDelay = true;
593  refreshScreen();
594  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
595  }
596 }
597 //==============================================
599 {
600  fontSize++;
601  refreshScreen();
602 }
603 //==============================================
605 {
606  fontSize--;
607  refreshScreen();
608 }
609 //==============================================
611 {
612  //bail if currently animating
613  animatingMutex.lock();
614  if(animating)
615  {
616  animatingMutex.unlock();
617  return;
618  }
619 
620  //stop autoPlay timer so next advance only occur after delay after advance is complete
621  autoPlayTimer->stop();
622 
623  animating = true;
624  if(USE_ANIMATION)
625  type = SCROLL_LEFT;
626  else
627  type = IMMEDIATE;
628  animatingMutex.unlock();
629 
630  if(curPhoto->getNext() == NULL)
631  { advanceCollection(); }
632  else
633  {
634  //load and display new photo
636  photoNum++;
637  loadPhoto();
638  exchangePhotos();
639  }
640 }
641 //==============================================
643 {
644  //bail if currently animating
645  animatingMutex.lock();
646  if(animating)
647  {
648  animatingMutex.unlock();
649  return;
650  }
651 
652  animating = true;
653  if(USE_ANIMATION)
654  type = SCROLL_RIGHT;
655  else
656  type = IMMEDIATE;
657  animatingMutex.unlock();
658 
659  if(curPhoto->getPrev() == NULL)
660  { backupCollection(); }
661  else
662  {
663  //load and display new photo
665  photoNum--;
666  loadPhoto();
667  exchangePhotos();
668 }
669 }
670 //==============================================
672 {
673  //bail if already at first photo in collection
675  return;
676 
677  //bail if currently animating
678  animatingMutex.lock();
679  if(animating)
680  {
681  animatingMutex.unlock();
682  return;
683  }
684 
685  animating = true;
686  if(USE_ANIMATION)
687  type = SCROLL_RIGHT;
688  else
689  type = IMMEDIATE;
690  animatingMutex.unlock();
691 
693  photoNum = 1;
694  //load and display new photo
695  loadPhoto();
696  exchangePhotos();
697 }
698 //==============================================
700 {
701  //bail if already at last photo in collection
702  if(curPhoto == curCollection->getLast())
703  return;
704 
705  //bail if currently animating
706  animatingMutex.lock();
707  if(animating)
708  {
709  animatingMutex.unlock();
710  return;
711  }
712 
713  animating = true;
714  if(USE_ANIMATION)
715  type = SCROLL_LEFT;
716  else
717  type = IMMEDIATE;
718  animatingMutex.unlock();
719 
722 
723  //load and display new photo
724  loadPhoto();
725  exchangePhotos();
726 }
727 //==============================================
729 {
730  if(USE_ANIMATION)
731  {
732  if(curCollection->getNext() == NULL &&
734  type = SCROLL_RIGHT;
735  else
736  type = SCROLL_UP;
737  }
738  else
739  type = IMMEDIATE;
740 
741  //keep advancing collections until we find one with a photo in it
742  curPhoto = NULL;
743  while(curPhoto == NULL)
744  {
746  collectionNum++;
747  if(!curCollection)
748  {
750  collectionNum = 1;
751  }
752 
754  }
755  photoNum = 1;
756 
757  //load and display new photo
758  loadPhoto();
759  exchangePhotos();
760 }
761 //==============================================
763 {
764  if(USE_ANIMATION)
765  {
766  if(curCollection->getPrev() == NULL &&
768  type = SCROLL_RIGHT;
769  else
770  type = SCROLL_DOWN;
771  }
772  else
773  type = IMMEDIATE;
774 
775  //keep backing up collections until we find one with a photo in it
776  curPhoto = NULL;
777  while(curPhoto == NULL)
778  {
780  collectionNum--;
781  if(!curCollection)
782  {
785  }
786 
788  }
790 
791  //load and display new photo
792  loadPhoto();
793  exchangePhotos();
794 }
795 //==============================================
797 {
798  //---------------------------------
799  //determine new number of columns to be shown
800 
801  //determine # of ms that have passed since last redraw
802  currentTime.start();
803  double ms = lastTime.msecsTo(currentTime);
804 
805  //determine increment
806  int inc = (int)(ms/delay);
807 
808  //if increment is not zero then update last time
809  if(inc != 0)
810  {
812  }
813 
814  //update number of columns shown
815  step+=inc;
816 
817  //boundary conditions
818  if( step > screenWidth && (type == SCROLL_LEFT || type == SCROLL_RIGHT) )
819  step = screenWidth;
820  if( step > screenHeight && (type == SCROLL_UP || type == SCROLL_DOWN) )
821  step = screenHeight;
822 
823  //if step changed then redraw
824  if(step != lastStep)
825  {
826  if(type == SCROLL_LEFT)
827  {
828  bitBlt( &screenBuffer, 0, 0,
830  step, 0,
831  paintBufferPrev->width() - step, paintBufferPrev->height(),
832  CopyROP, true );
833  bitBlt( &screenBuffer, paintBufferCurr->width() - step, 0,
835  0, 0, step, paintBufferCurr->height(),
836  CopyROP, true );
837  }
838  else if(type == SCROLL_RIGHT)
839  {
840  bitBlt( &screenBuffer, step, 0,
842  0, 0,
843  paintBufferPrev->width() - step, paintBufferPrev->height(),
844  CopyROP, true );
845  bitBlt( &screenBuffer, 0, 0,
847  paintBufferCurr->width() - step, 0, step, paintBufferCurr->height(),
848  CopyROP, true );
849  }
850  else if(type == SCROLL_UP)
851  {
852  bitBlt( &screenBuffer, 0, 0,
854  0, step,
855  paintBufferPrev->width(), paintBufferPrev->height() - step,
856  CopyROP, true );
857  bitBlt( &screenBuffer, 0, paintBufferCurr->height() - step,
859  0, 0, paintBufferCurr->width(), step,
860  CopyROP, true );
861  }
862  else if(type == SCROLL_DOWN)
863  {
864  bitBlt( &screenBuffer, 0, step,
866  0, 0,
867  paintBufferPrev->width(), paintBufferPrev->height() - step,
868  CopyROP, true );
869  bitBlt( &screenBuffer, 0, 0,
871  0, paintBufferCurr->height() - step, paintBufferCurr->width(), step,
872  CopyROP, true );
873  }
874 
875  //paint overlaid controls
877 
878  //blit to screen
879  repaint(false);
880 
881  lastStep = step;
882 
883  //not done animating, reiterate
884  if(
885  (
886  step < screenWidth &&
887  (type == SCROLL_LEFT || type == SCROLL_RIGHT)
888  ) ||
889  (
890  step < screenHeight &&
891  (type == SCROLL_UP || type == SCROLL_DOWN)
892  )
893  )
894  {
895  //update speed
896  delay = delay * accel;
897  if(delay < minDelay) delay = minDelay ;
898 
899  //restart timer
900  animatingTimer->start( (int)delay, TRUE );
901  }
902  //done animating....
903  else
904  {
905  animating = false;
906 
907  //if using debug messages use refreshScreen method which actually displays these.
908  //such messages are laid on time and thus not shown when transitioning
910  refreshScreen();
911 
912  //if autoplay is enabled restart timer
913  if(autoPlay)
914  autoPlayTimer->start( (int)1000*autoPlayDelay, TRUE );
915  }
916  }
917  else
918  {
919  //update speed
920  delay = delay * accel;
921  if(delay < minDelay) delay = minDelay;
922 
923  //restart timer
924  animatingTimer->start( (int)delay, TRUE );
925  }
926  //---------------------------------------
927 }
928 //==============================================
930 {
931  //if transition is set to immediate then just show new photo
932  if(type == IMMEDIATE)
933  {
934  refreshScreen();
935  animating = false;
936  return;
937  }
938 
939  //setup step counter
940  lastStep = 0;
941  step = 0;
942 
943  //set initial delay/speed
944  delay = initDelay;
945 
946  //exchange buffers
947  QPixmap* temp = paintBufferCurr;
949  paintBufferPrev = temp;
950 
951  //paint new image to curr buffer
952  showPhoto();
953 
954  //find current time, used to decide how many new columns to reveal in first iteration
955  lastTime.start();
956 
957  //begin animation
958  animate();
959 }
960 //==============================================
962 {
963  //paint current photo to paintBufferCurr
964  showPhoto();
965 
966  //blit to screen buffer
967  bitBlt( &screenBuffer, 0, 0,
969  0, 0, paintBufferCurr->width(), paintBufferCurr->height(),
970  CopyROP, true );
971 
972  //paint overlaid controls
974 }
975 //==============================================
977 {
978  QString tempString = "";
979  int x, y;
980 
981  //setup painter to screen buffer for laying on top all top level widgets
982  QPainter p;
983  p.begin( &screenBuffer );
984  //------------------------------
985  //setup font stuff for writing text
986  QFont f( "times", fontSize, QFont::Bold );
987  QFontMetrics fm( f );
988  p.setFont( f );
989  //------------------------------
990  //paint autoPlay delay
992  {
993  //get handle on right speed icon
994  QImage* speedIcon;
995  if(autoPlayDelay == 1) speedIcon = &speed1;
996  else if(autoPlayDelay == 2) speedIcon = &speed2;
997  else if(autoPlayDelay == 4) speedIcon = &speed4;
998  else speedIcon = &speed8;
999 
1000  int maxWidth = speed1.width();
1001  if(speed2.width() > maxWidth) maxWidth = speed2.width();
1002  if(speed4.width() > maxWidth) maxWidth = speed4.width();
1003  if(speed8.width() > maxWidth) maxWidth = speed8.width();
1004 
1005  int maxHeight = speed1.height();
1006  if(speed2.height() > maxHeight) maxHeight = speed2.height();
1007  if(speed4.height() > maxHeight) maxHeight = speed4.height();
1008  if(speed8.height() > maxHeight) maxHeight = speed8.height();
1009 
1010  x = screenWidth - TEXT_MARGIN - speedIcon->width() - (maxWidth - speedIcon->width())/2;
1011  y = screenHeight - TEXT_MARGIN - speedIcon->height() - (maxHeight - speedIcon->height())/2;
1012 
1013  p.drawImage( x, y, *speedIcon );
1014  displayAutoPlayDelay = false;
1015  }
1016  //------------------------------
1017  //if debugging enabled paint such messages
1019  {
1020  //before debugging message set color to green
1021  p.setPen(QColor("green"));
1022  //------------------------------
1023  //paint collection number
1024  tempString = QString("(Collection %1 / %2)").arg(collectionNum).arg(curAlbum->getNumSubalbums());
1025  x = 0;
1026  y = 0;
1027  p.fillRect( x, y, fm.width(tempString), fm.height(), QBrush(QColor("black")) );
1028  p.drawText( x, y + fm.ascent(), tempString );
1029  //------------------------------
1030  //paint photo number
1031  tempString = QString("(Photo %1 / %2)").arg(photoNum).arg(curCollection->getNumPhotos());
1032  x = screenWidth - fm.width(tempString);
1033  y = 0;
1034  p.fillRect( x, y, fm.width(tempString), fm.height(), QBrush(QColor("black")) );
1035  p.drawText(x, y + fm.ascent(), tempString );
1036  }
1037  //------------------------------
1038  //if the mouse is shown paint the control interface
1039  if(mouseShown)
1040  {
1041  QImage* shownInterface;
1042  if(autoPlay)
1043  shownInterface = &pauseInterface;
1044  else
1045  shownInterface = &playInterface;
1046 
1047  x = ( screenWidth - shownInterface->width() ) / 2;
1048  y = screenHeight - shownInterface->height() - TEXT_MARGIN;
1049  p.drawImage( x, y, *shownInterface );
1050 
1051  //paint collection # and photo #
1052  f.setPointSize( 14 );
1053  fm = QFontMetrics( f );
1054  tempString = QString("%1 / %2").arg(photoNum).arg(curCollection->getNumPhotos());
1055  x = x + (shownInterface->width() / 2) - (fm.width(tempString) / 2);
1056  y = y + 104;
1057  p.setFont( f );
1058  p.setPen(QColor("white"));
1059  p.drawText( x, y, tempString );
1060  }
1061  //------------------------------
1062  //ender painter and flast to screen
1063  p.end();
1064  repaint(false);
1065 }
1066 //==============================================
1068 //==============================================
1070 //==============================================
1071 
ANIMATION_TYPE type
QString getImageFilename()
Gets the image filename.
Definition: photo.cpp:192
A photo consists of a full size image, a smaller slide show image, a very small thumbnail image...
Definition: photo.h:44
#define TEXT_MARGIN
int getNumSubalbums()
Returns number of subalbums.
Definition: album.cpp:144
QString getSaveLocation()
Returns the current save location of all images.
Definition: album.cpp:141
Photo * getNext()
Returns next photo pointer.
Definition: photo.cpp:225
Subalbum * curCollection
QString IMAGE_PATH
Definition: config.cpp:18
SlideshowWidget(QWidget *parent=0, const char *name=0, WFlags f=0)
void mouseMoveEvent(QMouseEvent *e)
void showCollectionPage(Subalbum *subalbum)
A subalbum contains photos.
Definition: subalbum.h:48
Photo * getCurPhoto()
returns a pointer to the currently visible photo
#define USE_ANIMATION
int getNumPhotos()
Returns the number of photos in the subalbum.
Definition: subalbum.cpp:104
Subalbum * getCurCollection()
returns a pointer to the currently visible collection
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
Definition: imageTools.cpp:157
void beginSlideshow(Album *albm, Subalbum *startCollection=NULL, Photo *startPhoto=NULL)
Photo * getFirst()
Returns first photo in subalbum.
Definition: subalbum.cpp:100
Subalbum * getFirstSubalbum()
Returns a pointer to the first Subalbum.
Definition: album.cpp:135
void contextMenuEvent(QContextMenuEvent *e)
Subalbum * getLastSubalbum()
Returns a pointer to the last Subalbum.
Definition: album.cpp:136
An album contains Subalbums.
Definition: album.h:52
Subalbum * getNext()
Returns pointer to next subalbum.
Definition: subalbum.cpp:98
void keyPressEvent(QKeyEvent *e)
QString getDescription()
Gets the description.
Definition: photo.cpp:208
#define HIDE_MOUSE_DELAY
QString getTheme()
Returns currently selected theme.
Definition: album.cpp:143
void mousePressEvent(QMouseEvent *e)
Photo * getPrev()
Returns the previous photo pointer.
Definition: photo.cpp:224
void paintEvent(QPaintEvent *)
Subalbum * getPrev()
Returns pointer to prev subalbum.
Definition: subalbum.cpp:97
QString THEMES_PATH
Definition: config.cpp:21
Photo * getLast()
Returns last photo in subalbum.
Definition: subalbum.cpp:101