/***************************************************************************
* Copyright ( C ) 2004 by Enrico Ros < eros . kde @ email . it > *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// qt/kde includes
# include <tqtimer.h>
# include <tqimage.h>
# include <tqpainter.h>
# include <tqapplication.h>
# include <tqdesktopwidget.h>
# include <tqtooltip.h>
# include <kaccel.h>
# include <kactioncollection.h>
# include <kapplication.h>
# include <kcursor.h>
# include <ktoolbar.h>
# include <kdebug.h>
# include <klocale.h>
# include <kiconloader.h>
# include <kimageeffect.h>
# include <kmessagebox.h>
# include <twin.h>
// system includes
# include <stdlib.h>
# include <math.h>
// local includes
# include "presentationwidget.h"
# include "pagepainter.h"
# include "core/generator.h"
# include "core/page.h"
# include "core/link.h"
# include "conf/settings.h"
// comment this to disable the top-right progress indicator
# define ENABLE_PROGRESS_OVERLAY
// a frame contains a pointer to the page object, its tqgeometry and the
// transition effect to the next frame
struct PresentationFrame
{
const KPDFPage * page ;
TQRect tqgeometry ;
} ;
PresentationWidget : : PresentationWidget ( TQWidget * parent , KPDFDocument * doc )
: TQDialog ( parent , " presentationWidget " , true , WDestructiveClose | WStyle_NoBorder ) ,
m_pressedLink ( 0 ) , m_handCursor ( false ) , m_document ( doc ) , m_frameIndex ( - 1 )
{
// set look and tqgeometry
setBackgroundMode ( TQt : : NoBackground ) ;
m_width = - 1 ;
m_accel = new KAccel ( this , TQT_TQOBJECT ( this ) , " presentationmode-accel " ) ;
// show widget and take control
showFullScreen ( ) ;
// misc stuff
setMouseTracking ( true ) ;
m_transitionTimer = new TQTimer ( this ) ;
connect ( m_transitionTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotTransitionStep ( ) ) ) ;
m_overlayHideTimer = new TQTimer ( this ) ;
connect ( m_overlayHideTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotHideOverlay ( ) ) ) ;
m_nextPageTimer = new TQTimer ( this ) ;
connect ( m_nextPageTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotNextPage ( ) ) ) ;
// handle cursor appearance as specified in configuration
if ( KpdfSettings : : slidesCursor ( ) = = KpdfSettings : : EnumSlidesCursor : : HiddenDelay )
{
KCursor : : setAutoHideCursor ( this , true ) ;
KCursor : : setHideCursorDelay ( 3000 ) ;
}
else if ( KpdfSettings : : slidesCursor ( ) = = KpdfSettings : : EnumSlidesCursor : : Hidden )
{
setCursor ( KCursor : : blankCursor ( ) ) ;
}
}
PresentationWidget : : ~ PresentationWidget ( )
{
// remove this widget from document observer
m_document - > removeObserver ( this ) ;
// delete frames
TQValueVector < PresentationFrame * > : : iterator fIt = m_frames . begin ( ) , fEnd = m_frames . end ( ) ;
for ( ; fIt ! = fEnd ; + + fIt )
delete * fIt ;
}
void PresentationWidget : : setupActions ( KActionCollection * ac )
{
m_accel - > insert ( " previous_page " , ac - > action ( " previous_page " ) - > shortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotPrevPage ( ) ) , false , true ) ;
m_accel - > insert ( " next_page " , ac - > action ( " next_page " ) - > shortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotNextPage ( ) ) , false , true ) ;
m_accel - > insert ( " first_page " , ac - > action ( " first_page " ) - > shortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotFirstPage ( ) ) , false , true ) ;
m_accel - > insert ( " last_page " , ac - > action ( " last_page " ) - > shortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotLastPage ( ) ) , false , true ) ;
m_accel - > insert ( " presentation " , ac - > action ( " presentation " ) - > shortcut ( ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( close ( ) ) , false , true ) ;
}
void PresentationWidget : : notifySetup ( const TQValueVector < KPDFPage * > & pageSet , bool /*documentChanged*/ )
{
// delete previous frames (if any (shouldn't be))
TQValueVector < PresentationFrame * > : : iterator fIt = m_frames . begin ( ) , fEnd = m_frames . end ( ) ;
for ( ; fIt ! = fEnd ; + + fIt )
delete * fIt ;
if ( ! m_frames . isEmpty ( ) )
kdWarning ( ) < < " Frames setup changed while a Presentation is in progress. " < < endl ;
m_frames . clear ( ) ;
// create the new frames
TQValueVector < KPDFPage * > : : const_iterator setIt = pageSet . begin ( ) , setEnd = pageSet . end ( ) ;
float screenRatio = ( float ) m_height / ( float ) m_width ;
for ( ; setIt ! = setEnd ; + + setIt )
{
PresentationFrame * frame = new PresentationFrame ( ) ;
frame - > page = * setIt ;
// calculate frame tqgeometry keeping constant aspect ratio
float pageRatio = frame - > page - > ratio ( ) ;
int pageWidth = m_width ,
pageHeight = m_height ;
if ( pageRatio > screenRatio )
pageWidth = ( int ) ( ( float ) pageHeight / pageRatio ) ;
else
pageHeight = ( int ) ( ( float ) pageWidth * pageRatio ) ;
frame - > tqgeometry . setRect ( ( m_width - pageWidth ) / 2 ,
( m_height - pageHeight ) / 2 ,
pageWidth , pageHeight ) ;
// add the frame to the vector
m_frames . push_back ( frame ) ;
}
// get metadata from the document
m_metaStrings . clear ( ) ;
const DocumentInfo * info = m_document - > documentInfo ( ) ;
if ( info )
{
if ( ! info - > get ( " title " ) . isNull ( ) )
m_metaStrings + = i18n ( " Title: %1 " ) . tqarg ( info - > get ( " title " ) ) ;
if ( ! info - > get ( " author " ) . isNull ( ) )
m_metaStrings + = i18n ( " Author: %1 " ) . tqarg ( info - > get ( " author " ) ) ;
}
m_metaStrings + = i18n ( " Pages: %1 " ) . tqarg ( m_document - > pages ( ) ) ;
m_metaStrings + = i18n ( " Click to begin " ) ;
}
void PresentationWidget : : notifyViewportChanged ( bool /*smoothMove*/ )
{
// discard notifications if displaying the summary
if ( m_frameIndex = = - 1 & & KpdfSettings : : slidesShowSummary ( ) )
return ;
// display the current page
changePage ( m_document - > viewport ( ) . pageNumber ) ;
// auto advance to the next page if set
if ( KpdfSettings : : slidesAdvance ( ) )
m_nextPageTimer - > start ( KpdfSettings : : slidesAdvanceTime ( ) * 1000 ) ;
}
void PresentationWidget : : notifyPageChanged ( int pageNumber , int changedFlags )
{
// check if it's the last requested pixmap. if so update the widget.
if ( ( changedFlags & DocumentObserver : : Pixmap ) & & pageNumber = = m_frameIndex )
generatePage ( ) ;
}
bool PresentationWidget : : canUnloadPixmap ( int pageNumber )
{
// can unload all pixmaps except for the currently visible one
return pageNumber ! = m_frameIndex ;
}
// <widget events>
/* This hack was here to fix 103718 but it's no longer necessary on KDE 3.5 and Lubos asked me to remove it
bool PresentationWidget : : event ( TQEvent * e )
{
if ( e - > type ( ) = = TQEvent : : WindowDeactivate ) KWin : : clearState ( winId ( ) , NET : : StaysOnTop ) ;
else if ( e - > type ( ) = = TQEvent : : WindowActivate ) KWin : : setState ( winId ( ) , NET : : StaysOnTop ) ;
return TQDialog : : event ( e ) ;
}
*/
void PresentationWidget : : keyPressEvent ( TQKeyEvent * e )
{
if ( m_width = = - 1 ) return ;
if ( e - > key ( ) = = Key_Left | | e - > key ( ) = = Key_Backspace | | e - > key ( ) = = Key_Prior )
slotPrevPage ( ) ;
else if ( e - > key ( ) = = Key_Right | | e - > key ( ) = = Key_Space | | e - > key ( ) = = Key_Next )
slotNextPage ( ) ;
else if ( e - > key ( ) = = Key_Home )
slotFirstPage ( ) ;
else if ( e - > key ( ) = = Key_End )
slotLastPage ( ) ;
else if ( e - > key ( ) = = Key_Escape )
{
if ( m_topBar - > isShown ( ) )
m_topBar - > hide ( ) ;
else
close ( ) ;
}
}
void PresentationWidget : : wheelEvent ( TQWheelEvent * e )
{
// performance note: don't remove the clipping
int div = e - > delta ( ) / 120 ;
if ( div > 0 )
{
if ( div > 3 )
div = 3 ;
while ( div - - )
slotPrevPage ( ) ;
}
else if ( div < 0 )
{
if ( div < - 3 )
div = - 3 ;
while ( div + + )
slotNextPage ( ) ;
}
}
void PresentationWidget : : mousePressEvent ( TQMouseEvent * e )
{
// pressing left button
if ( e - > button ( ) = = Qt : : LeftButton )
{
// if pressing on a link, skip other checks
if ( ( m_pressedLink = getLink ( e - > x ( ) , e - > y ( ) ) ) )
return ;
// handle clicking on top-right overlay
if ( m_overlayGeometry . contains ( e - > pos ( ) ) )
{
overlayClick ( e - > pos ( ) ) ;
return ;
}
// if no other actions, go to next page
slotNextPage ( ) ;
}
// pressing right button
else if ( e - > button ( ) = = Qt : : RightButton )
slotPrevPage ( ) ;
}
void PresentationWidget : : mouseReleaseEvent ( TQMouseEvent * e )
{
// if releasing on the same link we pressed over, execute it
if ( m_pressedLink & & e - > button ( ) = = Qt : : LeftButton )
{
const KPDFLink * link = getLink ( e - > x ( ) , e - > y ( ) ) ;
if ( link = = m_pressedLink )
m_document - > processLink ( link ) ;
m_pressedLink = 0 ;
}
}
void PresentationWidget : : mouseMoveEvent ( TQMouseEvent * e )
{
// safety check
if ( m_width = = - 1 )
return ;
// update cursor and tooltip if hovering a link
if ( KpdfSettings : : slidesCursor ( ) ! = KpdfSettings : : EnumSlidesCursor : : Hidden )
testCursorOnLink ( e - > x ( ) , e - > y ( ) ) ;
if ( m_topBar - > isShown ( ) )
{
// hide a shown bar when exiting the area
if ( e - > y ( ) > ( m_topBar - > height ( ) + 1 ) )
m_topBar - > hide ( ) ;
}
else
{
// show the bar if reaching top 2 pixels
if ( e - > y ( ) < = ( tqgeometry ( ) . top ( ) + 1 ) )
m_topBar - > show ( ) ;
// handle "dragging the wheel" if clicking on its tqgeometry
else if ( e - > state ( ) = = Qt : : LeftButton & & m_overlayGeometry . contains ( e - > pos ( ) ) )
overlayClick ( e - > pos ( ) ) ;
}
}
void PresentationWidget : : paintEvent ( TQPaintEvent * pe )
{
if ( m_width = = - 1 )
{
TQRect d = KGlobalSettings : : desktopGeometry ( this ) ;
m_width = d . width ( ) ;
m_height = d . height ( ) ;
// create top toolbar
m_topBar = new KToolBar ( this , " presentationBar " ) ;
m_topBar - > setIconSize ( 32 ) ;
m_topBar - > setMovingEnabled ( false ) ;
m_topBar - > insertButton ( TQApplication : : reverseLayout ( ) ? " 1rightarrow " : " 1leftarrow " , 2 , TQT_SIGNAL ( clicked ( ) ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotPrevPage ( ) ) ) ;
m_topBar - > insertButton ( TQApplication : : reverseLayout ( ) ? " 1leftarrow " : " 1rightarrow " , 3 , TQT_SIGNAL ( clicked ( ) ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( slotNextPage ( ) ) ) ;
m_topBar - > insertButton ( " exit " , 1 , TQT_SIGNAL ( clicked ( ) ) , TQT_TQOBJECT ( this ) , TQT_SLOT ( close ( ) ) ) ;
m_topBar - > setGeometry ( 0 , 0 , m_width , 32 + 10 ) ;
m_topBar - > alignItemRight ( 1 ) ;
m_topBar - > hide ( ) ;
// change topbar background color
TQPalette p = m_topBar - > tqpalette ( ) ;
p . setColor ( TQPalette : : Active , TQColorGroup : : Button , TQt : : gray ) ;
p . setColor ( TQPalette : : Active , TQColorGroup : : Background , TQt : : darkGray ) ;
m_topBar - > setPalette ( p ) ;
// register this observer in document. events will come immediately
m_document - > addObserver ( this ) ;
// show summary if requested
if ( KpdfSettings : : slidesShowSummary ( ) )
generatePage ( ) ;
KMessageBox : : information ( this , i18n ( " There are two ways of exiting presentation mode, you can press either ESC key or click with the quit button that appears when placing the mouse in the top-right corner. Of course you can cycle windows (Alt+TAB by default) " ) , TQString ( ) , " presentationInfo " ) ;
}
// check painting rect consistancy
TQRect r = pe - > rect ( ) . intersect ( tqgeometry ( ) ) ;
if ( r . isNull ( ) | | m_lastRenderedPixmap . isNull ( ) )
return ;
// blit the pixmap to the screen
TQMemArray < TQRect > allRects = TQRegion ( pe - > region ( ) ) . tqrects ( ) ;
uint numRects = allRects . count ( ) ;
for ( uint i = 0 ; i < numRects ; i + + )
{
const TQRect & r = allRects [ i ] ;
if ( ! r . isValid ( ) )
continue ;
# ifdef ENABLE_PROGRESS_OVERLAY
if ( KpdfSettings : : slidesShowProgress ( ) & & r . intersects ( m_overlayGeometry ) )
{
// backbuffer the overlay operation
TQPixmap backPixmap ( r . size ( ) ) ;
TQPainter pixPainter ( & backPixmap ) ;
// first draw the background on the backbuffer
pixPainter . drawPixmap ( TQPoint ( 0 , 0 ) , m_lastRenderedPixmap , r ) ;
// then blend the overlay (a piece of) over the background
TQRect ovr = m_overlayGeometry . intersect ( r ) ;
pixPainter . drawPixmap ( ovr . left ( ) - r . left ( ) , ovr . top ( ) - r . top ( ) ,
m_lastRenderedOverlay , ovr . left ( ) - m_overlayGeometry . left ( ) ,
ovr . top ( ) - m_overlayGeometry . top ( ) , ovr . width ( ) , ovr . height ( ) ) ;
// finally blit the pixmap to the screen
pixPainter . end ( ) ;
bitBlt ( this , r . topLeft ( ) , & backPixmap , backPixmap . rect ( ) ) ;
} else
# endif
// copy the rendered pixmap to the screen
bitBlt ( this , r . topLeft ( ) , & m_lastRenderedPixmap , r ) ;
}
}
// </widget events>
const KPDFLink * PresentationWidget : : getLink ( int x , int y , TQRect * tqgeometry ) const
{
// no links on invalid pages
if ( tqgeometry & & ! tqgeometry - > isNull ( ) )
tqgeometry - > setRect ( 0 , 0 , - 1 , - 1 ) ;
if ( m_frameIndex < 0 | | m_frameIndex > = ( int ) m_frames . size ( ) )
return 0 ;
// get frame, page and tqgeometry
const PresentationFrame * frame = m_frames [ m_frameIndex ] ;
const KPDFPage * page = frame - > page ;
const TQRect & frameGeometry = frame - > tqgeometry ;
// compute normalized x and y
double nx = ( double ) ( x - frameGeometry . left ( ) ) / ( double ) frameGeometry . width ( ) ;
double ny = ( double ) ( y - frameGeometry . top ( ) ) / ( double ) frameGeometry . height ( ) ;
// no links outside the pages
if ( nx < 0 | | nx > 1 | | ny < 0 | | ny > 1 )
return 0 ;
// check if 1) there is an object and 2) it's a link
const ObjectRect * object = page - > hasObject ( ObjectRect : : Link , nx , ny ) ;
if ( ! object )
return 0 ;
// compute link tqgeometry if destination rect present
if ( tqgeometry )
{
* tqgeometry = object - > tqgeometry ( frameGeometry . width ( ) , frameGeometry . height ( ) ) ;
tqgeometry - > moveBy ( frameGeometry . left ( ) , frameGeometry . top ( ) ) ;
}
// return the link pointer
return ( KPDFLink * ) object - > pointer ( ) ;
}
void PresentationWidget : : testCursorOnLink ( int x , int y )
{
// get rect
TQRect linkRect ;
const KPDFLink * link = getLink ( x , y , & linkRect ) ;
// only react on changes (in/out from a link)
if ( ( link & & ! m_handCursor ) | | ( ! link & & m_handCursor ) )
{
// change cursor tqshape
m_handCursor = link ! = 0 ;
setCursor ( m_handCursor ? KCursor : : handCursor ( ) : KCursor : : arrowCursor ( ) ) ;
// set tooltip over link's rect
TQString tip = link ? link - > linkTip ( ) : TQString ( ) ;
if ( m_handCursor & & ! tip . isEmpty ( ) )
TQToolTip : : add ( this , linkRect , tip ) ;
}
}
void PresentationWidget : : overlayClick ( const TQPoint & position )
{
// clicking the progress indicator
int xPos = position . x ( ) - m_overlayGeometry . x ( ) - m_overlayGeometry . width ( ) / 2 ,
yPos = m_overlayGeometry . height ( ) / 2 - position . y ( ) ;
if ( ! xPos & & ! yPos )
return ;
// compute angle relative to indicator (note coord transformation)
float angle = 0.5 + 0.5 * atan2 ( - xPos , - yPos ) / M_PI ;
int pageIndex = ( int ) ( angle * ( m_frames . count ( ) - 1 ) + 0.5 ) ;
// go to selected page
changePage ( pageIndex ) ;
}
void PresentationWidget : : changePage ( int newPage )
{
if ( m_frameIndex = = newPage )
return ;
// check if pixmap exists or else request it
m_frameIndex = newPage ;
PresentationFrame * frame = m_frames [ m_frameIndex ] ;
int pixW = frame - > tqgeometry . width ( ) ;
int pixH = frame - > tqgeometry . height ( ) ;
// if pixmap not inside the KPDFPage we request it and wait for
// notifyPixmapChanged call or else we can proceed to pixmap generation
if ( ! frame - > page - > hasPixmap ( PRESENTATION_ID , pixW , pixH ) )
{
// operation will take long: set busy cursor
TQApplication : : setOverrideCursor ( KCursor : : workingCursor ( ) ) ;
// request the pixmap
TQValueList < PixmapRequest * > requests ;
requests . push_back ( new PixmapRequest ( PRESENTATION_ID , m_frameIndex , pixW , pixH , PRESENTATION_PRIO ) ) ;
// restore cursor
TQApplication : : restoreOverrideCursor ( ) ;
// ask for next and previous page if not in low memory usage setting
if ( KpdfSettings : : memoryLevel ( ) ! = KpdfSettings : : EnumMemoryLevel : : Low & & KpdfSettings : : enableThreading ( ) ) {
if ( newPage + 1 < ( int ) m_document - > pages ( ) )
{
PresentationFrame * nextFrame = m_frames [ newPage + 1 ] ;
pixW = nextFrame - > tqgeometry . width ( ) ;
pixH = nextFrame - > tqgeometry . height ( ) ;
if ( ! nextFrame - > page - > hasPixmap ( PRESENTATION_ID , pixW , pixH ) )
requests . push_back ( new PixmapRequest ( PRESENTATION_ID , newPage + 1 , pixW , pixH , PRESENTATION_PRELOAD_PRIO , true ) ) ;
}
if ( newPage - 1 > = 0 )
{
PresentationFrame * prevFrame = m_frames [ newPage - 1 ] ;
pixW = prevFrame - > tqgeometry . width ( ) ;
pixH = prevFrame - > tqgeometry . height ( ) ;
if ( ! prevFrame - > page - > hasPixmap ( PRESENTATION_ID , pixW , pixH ) )
requests . push_back ( new PixmapRequest ( PRESENTATION_ID , newPage - 1 , pixW , pixH , PRESENTATION_PRELOAD_PRIO , true ) ) ;
}
}
m_document - > requestPixmaps ( requests ) ;
}
else
{
// make the background pixmap
generatePage ( ) ;
}
// set a new viewport in document if page number differs
if ( m_frameIndex ! = - 1 & & m_frameIndex ! = m_document - > viewport ( ) . pageNumber )
m_document - > setViewportPage ( m_frameIndex , PRESENTATION_ID ) ;
}
void PresentationWidget : : generatePage ( )
{
if ( m_lastRenderedPixmap . isNull ( ) )
m_lastRenderedPixmap . resize ( m_width , m_height ) ;
// opens the painter over the pixmap
TQPainter pixmapPainter ;
pixmapPainter . begin ( & m_lastRenderedPixmap ) ;
// generate welcome page
if ( m_frameIndex = = - 1 )
generateIntroPage ( pixmapPainter ) ;
// generate a normal pixmap with extended margin filling
if ( m_frameIndex > = 0 & & m_frameIndex < ( int ) m_document - > pages ( ) )
generateContentsPage ( m_frameIndex , pixmapPainter ) ;
pixmapPainter . end ( ) ;
// generate the top-right corner overlay
# ifdef ENABLE_PROGRESS_OVERLAY
if ( KpdfSettings : : slidesShowProgress ( ) & & m_frameIndex ! = - 1 )
generateOverlay ( ) ;
# endif
// start transition on pages that have one
const KPDFPageTransition * transition = m_frameIndex ! = - 1 ?
m_frames [ m_frameIndex ] - > page - > getTransition ( ) : 0 ;
if ( transition )
initTransition ( transition ) ;
else {
KPDFPageTransition trans = defaultTransition ( ) ;
initTransition ( & trans ) ;
}
// update cursor + tooltip
if ( KpdfSettings : : slidesCursor ( ) ! = KpdfSettings : : EnumSlidesCursor : : Hidden )
{
TQPoint p = mapFromGlobal ( TQCursor : : pos ( ) ) ;
testCursorOnLink ( p . x ( ) , p . y ( ) ) ;
}
}
void PresentationWidget : : generateIntroPage ( TQPainter & p )
{
// use a vertical gray gradient background
int blend1 = m_height / 10 ,
blend2 = 9 * m_height / 10 ;
int baseTint = TQt : : gray . red ( ) ;
for ( int i = 0 ; i < m_height ; i + + )
{
int k = baseTint ;
if ( i < blend1 )
k - = ( int ) ( baseTint * ( i - blend1 ) * ( i - blend1 ) / ( float ) ( blend1 * blend1 ) ) ;
if ( i > blend2 )
k + = ( int ) ( ( 255 - baseTint ) * ( i - blend2 ) * ( i - blend2 ) / ( float ) ( blend1 * blend1 ) ) ;
p . fillRect ( 0 , i , m_width , 1 , TQColor ( k , k , k ) ) ;
}
// draw kpdf logo in the four corners
TQPixmap logo = DesktopIcon ( " kpdf " , 64 ) ;
if ( ! logo . isNull ( ) )
{
p . drawPixmap ( 5 , 5 , logo ) ;
p . drawPixmap ( m_width - 5 - logo . width ( ) , 5 , logo ) ;
p . drawPixmap ( m_width - 5 - logo . width ( ) , m_height - 5 - logo . height ( ) , logo ) ;
p . drawPixmap ( 5 , m_height - 5 - logo . height ( ) , logo ) ;
}
// draw metadata text (the last line is 'click to begin')
int strNum = m_metaStrings . count ( ) ,
strHeight = m_height / ( strNum + 4 ) ,
fontHeight = 2 * strHeight / 3 ;
TQFont font ( p . font ( ) ) ;
font . setPixelSize ( fontHeight ) ;
TQFontMetrics metrics ( font ) ;
for ( int i = 0 ; i < strNum ; i + + )
{
// set a font to fit text width
float wScale = ( float ) metrics . boundingRect ( m_metaStrings [ i ] ) . width ( ) / ( float ) m_width ;
TQFont f ( font ) ;
if ( wScale > 1.0 )
f . setPixelSize ( ( int ) ( ( float ) fontHeight / ( float ) wScale ) ) ;
p . setFont ( f ) ;
// text shadow
p . setPen ( TQt : : darkGray ) ;
p . drawText ( 2 , m_height / 4 + strHeight * i + 2 , m_width , strHeight ,
AlignHCenter | AlignVCenter , m_metaStrings [ i ] ) ;
// text body
p . setPen ( 128 + ( 127 * i ) / strNum ) ;
p . drawText ( 0 , m_height / 4 + strHeight * i , m_width , strHeight ,
AlignHCenter | AlignVCenter , m_metaStrings [ i ] ) ;
}
}
void PresentationWidget : : generateContentsPage ( int pageNum , TQPainter & p )
{
PresentationFrame * frame = m_frames [ pageNum ] ;
// translate painter and contents rect
TQRect geom ( frame - > tqgeometry ) ;
p . translate ( geom . left ( ) , geom . top ( ) ) ;
geom . moveBy ( - geom . left ( ) , - geom . top ( ) ) ;
// draw the page using the shared PagePainter class
int flags = PagePainter : : Accessibility ;
PagePainter : : paintPageOnPainter ( frame - > page , PRESENTATION_ID , flags ,
& p , geom , geom . width ( ) , geom . height ( ) ) ;
// restore painter
p . translate ( - frame - > tqgeometry . left ( ) , - frame - > tqgeometry . top ( ) ) ;
// fill unpainted areas with background color
TQRegion unpainted ( TQRect ( 0 , 0 , m_width , m_height ) ) ;
TQMemArray < TQRect > rects = TQRegion ( unpainted . subtract ( frame - > tqgeometry ) ) . tqrects ( ) ;
for ( uint i = 0 ; i < rects . count ( ) ; i + + )
{
const TQRect & r = rects [ i ] ;
p . fillRect ( r , KpdfSettings : : slidesBackgroundColor ( ) ) ;
}
}
// from Arthur - TQt4 - (is defined elsewhere as 'qt_div_255' to not break final compilation)
inline int qt_div255 ( int x ) { return ( x + ( x > > 8 ) + 0x80 ) > > 8 ; }
void PresentationWidget : : generateOverlay ( )
{
# ifdef ENABLE_PROGRESS_OVERLAY
// calculate overlay tqgeometry and resize pixmap if needed
int side = m_width / 16 ;
m_overlayGeometry . setRect ( m_width - side - 4 , 4 , side , side ) ;
if ( m_lastRenderedOverlay . width ( ) ! = side )
m_lastRenderedOverlay . resize ( side , side ) ;
// note: to get a sort of antialiasing, we render the pixmap double sized
// and the resulting image is smoothly scaled down. So here we open a
// painter on the double sized pixmap.
side * = 2 ;
TQPixmap doublePixmap ( side , side ) ;
doublePixmap . fill ( TQt : : black ) ;
TQPainter pixmapPainter ( & doublePixmap ) ;
// draw PIE SLICES in blue levels (the levels will then be the alpha component)
int pages = m_document - > pages ( ) ;
if ( pages > 28 )
{ // draw continuous slices
int degrees = ( int ) ( 360 * ( float ) ( m_frameIndex + 1 ) / ( float ) pages ) ;
pixmapPainter . setPen ( 0x05 ) ;
pixmapPainter . setBrush ( TQBrush ( 0x40 ) ) ;
pixmapPainter . drawPie ( 2 , 2 , side - 4 , side - 4 , 90 * 16 , ( 360 - degrees ) * 16 ) ;
pixmapPainter . setPen ( 0x40 ) ;
pixmapPainter . setBrush ( TQBrush ( 0xF0 ) ) ;
pixmapPainter . drawPie ( 2 , 2 , side - 4 , side - 4 , 90 * 16 , - degrees * 16 ) ;
}
else
{ // draw discrete slices
float oldCoord = - 90 ;
for ( int i = 0 ; i < pages ; i + + )
{
float newCoord = - 90 + 360 * ( float ) ( i + 1 ) / ( float ) pages ;
pixmapPainter . setPen ( i < = m_frameIndex ? 0x40 : 0x05 ) ;
pixmapPainter . setBrush ( TQBrush ( i < = m_frameIndex ? 0xF0 : 0x40 ) ) ;
pixmapPainter . drawPie ( 2 , 2 , side - 4 , side - 4 ,
( int ) ( - 16 * ( oldCoord + 1 ) ) , ( int ) ( - 16 * ( newCoord - ( oldCoord + 2 ) ) ) ) ;
oldCoord = newCoord ;
}
}
int circleOut = side / 4 ;
pixmapPainter . setPen ( TQt : : black ) ;
pixmapPainter . setBrush ( TQBrush ( TQt : : black ) ) ;
pixmapPainter . drawEllipse ( circleOut , circleOut , side - 2 * circleOut , side - 2 * circleOut ) ;
// draw TEXT using maximum opacity
TQFont f ( pixmapPainter . font ( ) ) ;
f . setPixelSize ( side / 4 ) ;
pixmapPainter . setFont ( f ) ;
pixmapPainter . setPen ( 0xFF ) ;
// use a little offset to prettify output
pixmapPainter . drawText ( 2 , 2 , side , side , TQt : : AlignCenter , TQString : : number ( m_frameIndex + 1 ) ) ;
// end drawing pixmap and halve image
pixmapPainter . end ( ) ;
TQImage image ( doublePixmap . convertToImage ( ) . smoothScale ( side / 2 , side / 2 ) ) ;
image . setAlphaBuffer ( true ) ;
// draw circular shadow using the same technique
doublePixmap . fill ( TQt : : black ) ;
pixmapPainter . begin ( & doublePixmap ) ;
pixmapPainter . setPen ( 0x40 ) ;
pixmapPainter . setBrush ( TQBrush ( 0x80 ) ) ;
pixmapPainter . drawEllipse ( 0 , 0 , side , side ) ;
pixmapPainter . end ( ) ;
TQImage shadow ( doublePixmap . convertToImage ( ) . smoothScale ( side / 2 , side / 2 ) ) ;
// generate a 2 colors pixmap using mixing shadow (made with highlight color)
// and image (made with highlightedText color)
TQColor color = tqpalette ( ) . active ( ) . highlightedText ( ) ;
int red = color . red ( ) , green = color . green ( ) , blue = color . blue ( ) ;
color = tqpalette ( ) . active ( ) . highlight ( ) ;
int sRed = color . red ( ) , sGreen = color . green ( ) , sBlue = color . blue ( ) ;
// pointers
unsigned int * data = ( unsigned int * ) image . bits ( ) ,
* shadowData = ( unsigned int * ) shadow . bits ( ) ,
pixels = image . width ( ) * image . height ( ) ;
// cache data (reduce computation time to 26%!)
int c1 = - 1 , c2 = - 1 , cR = 0 , cG = 0 , cB = 0 , cA = 0 ;
// foreach pixel
for ( unsigned int i = 0 ; i < pixels ; + + i )
{
// alpha for shadow and image
int shadowAlpha = shadowData [ i ] & 0xFF ,
srcAlpha = data [ i ] & 0xFF ;
// cache values
if ( srcAlpha ! = c1 | | shadowAlpha ! = c2 )
{
c1 = srcAlpha ;
c2 = shadowAlpha ;
// fuse color components and alpha value of image over shadow
data [ i ] = tqRgba (
cR = qt_div255 ( srcAlpha * red + ( 255 - srcAlpha ) * sRed ) ,
cG = qt_div255 ( srcAlpha * green + ( 255 - srcAlpha ) * sGreen ) ,
cB = qt_div255 ( srcAlpha * blue + ( 255 - srcAlpha ) * sBlue ) ,
cA = qt_div255 ( srcAlpha * srcAlpha + ( 255 - srcAlpha ) * shadowAlpha )
) ;
}
else
data [ i ] = tqRgba ( cR , cG , cB , cA ) ;
}
m_lastRenderedOverlay . convertFromImage ( image ) ;
// start the autohide timer
tqrepaint ( m_overlayGeometry , false /*clear*/ ) ; // toggle with next line
//update( m_overlayGeometry );
m_overlayHideTimer - > start ( 2500 , true ) ;
# endif
}
void PresentationWidget : : slotNextPage ( )
{
// loop when configured
if ( m_frameIndex = = ( int ) m_frames . count ( ) - 1 & & KpdfSettings : : slidesLoop ( ) )
m_frameIndex = - 1 ;
if ( m_frameIndex < ( int ) m_frames . count ( ) - 1 )
{
// go to next page
changePage ( m_frameIndex + 1 ) ;
// auto advance to the next page if set
if ( KpdfSettings : : slidesAdvance ( ) )
m_nextPageTimer - > start ( KpdfSettings : : slidesAdvanceTime ( ) * 1000 ) ;
}
else
{
# ifdef ENABLE_PROGRESS_OVERLAY
if ( KpdfSettings : : slidesShowProgress ( ) )
generateOverlay ( ) ;
# endif
if ( m_transitionTimer - > isActive ( ) )
{
m_transitionTimer - > stop ( ) ;
update ( ) ;
}
}
// we need the setFocus() call here to let KCursor::autoHide() work correctly
setFocus ( ) ;
}
void PresentationWidget : : slotPrevPage ( )
{
if ( m_frameIndex > 0 )
{
// go to previous page
changePage ( m_frameIndex - 1 ) ;
// auto advance to the next page if set
if ( KpdfSettings : : slidesAdvance ( ) )
m_nextPageTimer - > start ( KpdfSettings : : slidesAdvanceTime ( ) * 1000 ) ;
}
else
{
# ifdef ENABLE_PROGRESS_OVERLAY
if ( KpdfSettings : : slidesShowProgress ( ) )
generateOverlay ( ) ;
# endif
if ( m_transitionTimer - > isActive ( ) )
{
m_transitionTimer - > stop ( ) ;
update ( ) ;
}
}
}
void PresentationWidget : : slotFirstPage ( )
{
changePage ( 0 ) ;
}
void PresentationWidget : : slotLastPage ( )
{
changePage ( ( int ) m_frames . count ( ) - 1 ) ;
}
void PresentationWidget : : slotHideOverlay ( )
{
TQRect geom ( m_overlayGeometry ) ;
m_overlayGeometry . setCoords ( 0 , 0 , - 1 , - 1 ) ;
update ( geom ) ;
}
void PresentationWidget : : slotTransitionStep ( )
{
if ( m_transitionRects . empty ( ) )
{
// it's better to fix the transition to cover the whole screen than
// enabling the following line that wastes cpu for nothing
//update();
return ;
}
for ( int i = 0 ; i < m_transitionMul & & ! m_transitionRects . empty ( ) ; i + + )
{
update ( m_transitionRects . first ( ) ) ;
m_transitionRects . pop_front ( ) ;
}
m_transitionTimer - > start ( m_transitionDelay , true ) ;
}
const KPDFPageTransition PresentationWidget : : defaultTransition ( ) const
{
return defaultTransition ( KpdfSettings : : slidesTransition ( ) ) ;
}
const KPDFPageTransition PresentationWidget : : defaultTransition ( int type ) const
{
switch ( type )
{
case KpdfSettings : : EnumSlidesTransition : : BlindsHorizontal :
{
KPDFPageTransition transition ( KPDFPageTransition : : Blinds ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Horizontal ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : BlindsVertical :
{
KPDFPageTransition transition ( KPDFPageTransition : : Blinds ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Vertical ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : BoxIn :
{
KPDFPageTransition transition ( KPDFPageTransition : : Box ) ;
transition . setDirection ( KPDFPageTransition : : Inward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : BoxOut :
{
KPDFPageTransition transition ( KPDFPageTransition : : Box ) ;
transition . setDirection ( KPDFPageTransition : : Outward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : Dissolve :
{
return KPDFPageTransition ( KPDFPageTransition : : Dissolve ) ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : GlitterDown :
{
KPDFPageTransition transition ( KPDFPageTransition : : Glitter ) ;
transition . setAngle ( 270 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : GlitterRight :
{
KPDFPageTransition transition ( KPDFPageTransition : : Glitter ) ;
transition . setAngle ( 0 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : GlitterRightDown :
{
KPDFPageTransition transition ( KPDFPageTransition : : Glitter ) ;
transition . setAngle ( 315 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : Random :
{
return defaultTransition ( KApplication : : random ( ) % 18 ) ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : SplitHorizontalIn :
{
KPDFPageTransition transition ( KPDFPageTransition : : Split ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Horizontal ) ;
transition . setDirection ( KPDFPageTransition : : Inward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : SplitHorizontalOut :
{
KPDFPageTransition transition ( KPDFPageTransition : : Split ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Horizontal ) ;
transition . setDirection ( KPDFPageTransition : : Outward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : SplitVerticalIn :
{
KPDFPageTransition transition ( KPDFPageTransition : : Split ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Vertical ) ;
transition . setDirection ( KPDFPageTransition : : Inward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : SplitVerticalOut :
{
KPDFPageTransition transition ( KPDFPageTransition : : Split ) ;
transition . tqsetAlignment ( KPDFPageTransition : : Vertical ) ;
transition . setDirection ( KPDFPageTransition : : Outward ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : WipeDown :
{
KPDFPageTransition transition ( KPDFPageTransition : : Wipe ) ;
transition . setAngle ( 270 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : WipeRight :
{
KPDFPageTransition transition ( KPDFPageTransition : : Wipe ) ;
transition . setAngle ( 0 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : WipeLeft :
{
KPDFPageTransition transition ( KPDFPageTransition : : Wipe ) ;
transition . setAngle ( 180 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : WipeUp :
{
KPDFPageTransition transition ( KPDFPageTransition : : Wipe ) ;
transition . setAngle ( 90 ) ;
return transition ;
break ;
}
case KpdfSettings : : EnumSlidesTransition : : Replace :
default :
return KPDFPageTransition ( KPDFPageTransition : : Replace ) ;
break ;
}
}
/** ONLY the TRANSITIONS GENERATION function from here on **/
void PresentationWidget : : initTransition ( const KPDFPageTransition * transition )
{
// if it's just a 'replace' transition, tqrepaint the screen
if ( transition - > type ( ) = = KPDFPageTransition : : Replace )
{
update ( ) ;
return ;
}
const bool isInward = transition - > direction ( ) = = KPDFPageTransition : : Inward ;
const bool isHorizontal = transition - > tqalignment ( ) = = KPDFPageTransition : : Horizontal ;
const float totalTime = transition - > duration ( ) ;
m_transitionRects . clear ( ) ;
switch ( transition - > type ( ) )
{
// split: horizontal / vertical and inward / outward
case KPDFPageTransition : : Split :
{
const int steps = isHorizontal ? 100 : 75 ;
if ( isHorizontal )
{
if ( isInward )
{
int xPosition = 0 ;
for ( int i = 0 ; i < steps ; i + + )
{
int xNext = ( ( i + 1 ) * m_width ) / ( 2 * steps ) ;
m_transitionRects . push_back ( TQRect ( xPosition , 0 , xNext - xPosition , m_height ) ) ;
m_transitionRects . push_back ( TQRect ( m_width - xNext , 0 , xNext - xPosition , m_height ) ) ;
xPosition = xNext ;
}
}
else
{
int xPosition = m_width / 2 ;
for ( int i = 0 ; i < steps ; i + + )
{
int xNext = ( ( steps - ( i + 1 ) ) * m_width ) / ( 2 * steps ) ;
m_transitionRects . push_back ( TQRect ( xNext , 0 , xPosition - xNext , m_height ) ) ;
m_transitionRects . push_back ( TQRect ( m_width - xPosition , 0 , xPosition - xNext , m_height ) ) ;
xPosition = xNext ;
}
}
}
else
{
if ( isInward )
{
int yPosition = 0 ;
for ( int i = 0 ; i < steps ; i + + )
{
int yNext = ( ( i + 1 ) * m_height ) / ( 2 * steps ) ;
m_transitionRects . push_back ( TQRect ( 0 , yPosition , m_width , yNext - yPosition ) ) ;
m_transitionRects . push_back ( TQRect ( 0 , m_height - yNext , m_width , yNext - yPosition ) ) ;
yPosition = yNext ;
}
}
else
{
int yPosition = m_height / 2 ;
for ( int i = 0 ; i < steps ; i + + )
{
int yNext = ( ( steps - ( i + 1 ) ) * m_height ) / ( 2 * steps ) ;
m_transitionRects . push_back ( TQRect ( 0 , yNext , m_width , yPosition - yNext ) ) ;
m_transitionRects . push_back ( TQRect ( 0 , m_height - yPosition , m_width , yPosition - yNext ) ) ;
yPosition = yNext ;
}
}
}
m_transitionMul = 2 ;
m_transitionDelay = ( int ) ( ( totalTime * 1000 ) / steps ) ;
} break ;
// blinds: horizontal(l-to-r) / vertical(t-to-b)
case KPDFPageTransition : : Blinds :
{
const int blinds = isHorizontal ? 8 : 6 ;
const int steps = m_width / ( 4 * blinds ) ;
if ( isHorizontal )
{
int xPosition [ 8 ] ;
for ( int b = 0 ; b < blinds ; b + + )
xPosition [ b ] = ( b * m_width ) / blinds ;
for ( int i = 0 ; i < steps ; i + + )
{
int stepOffset = ( int ) ( ( ( float ) i * ( float ) m_width ) / ( ( float ) blinds * ( float ) steps ) ) ;
for ( int b = 0 ; b < blinds ; b + + )
{
m_transitionRects . push_back ( TQRect ( xPosition [ b ] , 0 , stepOffset , m_height ) ) ;
xPosition [ b ] = stepOffset + ( b * m_width ) / blinds ;
}
}
}
else
{
int yPosition [ 6 ] ;
for ( int b = 0 ; b < blinds ; b + + )
yPosition [ b ] = ( b * m_height ) / blinds ;
for ( int i = 0 ; i < steps ; i + + )
{
int stepOffset = ( int ) ( ( ( float ) i * ( float ) m_height ) / ( ( float ) blinds * ( float ) steps ) ) ;
for ( int b = 0 ; b < blinds ; b + + )
{
m_transitionRects . push_back ( TQRect ( 0 , yPosition [ b ] , m_width , stepOffset ) ) ;
yPosition [ b ] = stepOffset + ( b * m_height ) / blinds ;
}
}
}
m_transitionMul = blinds ;
m_transitionDelay = ( int ) ( ( totalTime * 1000 ) / steps ) ;
} break ;
// box: inward / outward
case KPDFPageTransition : : Box :
{
const int steps = m_width / 10 ;
if ( isInward )
{
int L = 0 , T = 0 , R = m_width , B = m_height ;
for ( int i = 0 ; i < steps ; i + + )
{
// compure shrinked box coords
int newL = ( ( i + 1 ) * m_width ) / ( 2 * steps ) ;
int newT = ( ( i + 1 ) * m_height ) / ( 2 * steps ) ;
int newR = m_width - newL ;
int newB = m_height - newT ;
// add left, right, topcenter, bottomcenter rects
m_transitionRects . push_back ( TQRect ( L , T , newL - L , B - T ) ) ;
m_transitionRects . push_back ( TQRect ( newR , T , R - newR , B - T ) ) ;
m_transitionRects . push_back ( TQRect ( newL , T , newR - newL , newT - T ) ) ;
m_transitionRects . push_back ( TQRect ( newL , newB , newR - newL , B - newB ) ) ;
L = newL ; T = newT ; R = newR , B = newB ;
}
}
else
{
int L = m_width / 2 , T = m_height / 2 , R = L , B = T ;
for ( int i = 0 ; i < steps ; i + + )
{
// compure shrinked box coords
int newL = ( ( steps - ( i + 1 ) ) * m_width ) / ( 2 * steps ) ;
int newT = ( ( steps - ( i + 1 ) ) * m_height ) / ( 2 * steps ) ;
int newR = m_width - newL ;
int newB = m_height - newT ;
// add left, right, topcenter, bottomcenter rects
m_transitionRects . push_back ( TQRect ( newL , newT , L - newL , newB - newT ) ) ;
m_transitionRects . push_back ( TQRect ( R , newT , newR - R , newB - newT ) ) ;
m_transitionRects . push_back ( TQRect ( L , newT , R - L , T - newT ) ) ;
m_transitionRects . push_back ( TQRect ( L , B , R - L , newB - B ) ) ;
L = newL ; T = newT ; R = newR , B = newB ;
}
}
m_transitionMul = 4 ;
m_transitionDelay = ( int ) ( ( totalTime * 1000 ) / steps ) ;
} break ;
// wipe: implemented for 4 canonical angles
case KPDFPageTransition : : Wipe :
{
const int angle = transition - > angle ( ) ;
const int steps = ( angle = = 0 ) | | ( angle = = 180 ) ? m_width / 8 : m_height / 8 ;
if ( angle = = 0 )
{
int xPosition = 0 ;
for ( int i = 0 ; i < steps ; i + + )
{
int xNext = ( ( i + 1 ) * m_width ) / steps ;
m_transitionRects . push_back ( TQRect ( xPosition , 0 , xNext - xPosition , m_height ) ) ;
xPosition = xNext ;
}
}
else if ( angle = = 90 )
{
int yPosition = m_height ;
for ( int i = 0 ; i < steps ; i + + )
{
int yNext = ( ( steps - ( i + 1 ) ) * m_height ) / steps ;
m_transitionRects . push_back ( TQRect ( 0 , yNext , m_width , yPosition - yNext ) ) ;
yPosition = yNext ;
}
}
else if ( angle = = 180 )
{
int xPosition = m_width ;
for ( int i = 0 ; i < steps ; i + + )
{
int xNext = ( ( steps - ( i + 1 ) ) * m_width ) / steps ;
m_transitionRects . push_back ( TQRect ( xNext , 0 , xPosition - xNext , m_height ) ) ;
xPosition = xNext ;
}
}
else if ( angle = = 270 )
{
int yPosition = 0 ;
for ( int i = 0 ; i < steps ; i + + )
{
int yNext = ( ( i + 1 ) * m_height ) / steps ;
m_transitionRects . push_back ( TQRect ( 0 , yPosition , m_width , yNext - yPosition ) ) ;
yPosition = yNext ;
}
}
else
{
update ( ) ;
return ;
}
m_transitionMul = 1 ;
m_transitionDelay = ( int ) ( ( totalTime * 1000 ) / steps ) ;
} break ;
// dissolve: replace 'random' rects
case KPDFPageTransition : : Dissolve :
{
const int gridXsteps = 50 ;
const int gridYsteps = 38 ;
const int steps = gridXsteps * gridYsteps ;
int oldX = 0 ;
int oldY = 0 ;
// create a grid of gridXstep by gridYstep TQRects
for ( int y = 0 ; y < gridYsteps ; y + + )
{
int newY = ( int ) ( m_height * ( ( float ) ( y + 1 ) / ( float ) gridYsteps ) ) ;
for ( int x = 0 ; x < gridXsteps ; x + + )
{
int newX = ( int ) ( m_width * ( ( float ) ( x + 1 ) / ( float ) gridXsteps ) ) ;
m_transitionRects . push_back ( TQRect ( oldX , oldY , newX - oldX , newY - oldY ) ) ;
oldX = newX ;
}
oldX = 0 ;
oldY = newY ;
}
// randomize the grid
for ( int i = 0 ; i < steps ; i + + )
{
int n1 = ( int ) ( steps * drand48 ( ) ) ;
int n2 = ( int ) ( steps * drand48 ( ) ) ;
// swap items if index differs
if ( n1 ! = n2 )
{
TQRect r = m_transitionRects [ n2 ] ;
m_transitionRects [ n2 ] = m_transitionRects [ n1 ] ;
m_transitionRects [ n1 ] = r ;
}
}
// set global transition parameters
m_transitionMul = 40 ;
m_transitionDelay = ( int ) ( ( m_transitionMul * 1000 * totalTime ) / steps ) ;
} break ;
// glitter: similar to dissolve but has a direction
case KPDFPageTransition : : Glitter :
{
const int gridXsteps = 50 ;
const int gridYsteps = 38 ;
const int steps = gridXsteps * gridYsteps ;
const int angle = transition - > angle ( ) ;
// generate boxes using a given direction
if ( angle = = 90 )
{
int yPosition = m_height ;
for ( int i = 0 ; i < gridYsteps ; i + + )
{
int yNext = ( ( gridYsteps - ( i + 1 ) ) * m_height ) / gridYsteps ;
int xPosition = 0 ;
for ( int j = 0 ; j < gridXsteps ; j + + )
{
int xNext = ( ( j + 1 ) * m_width ) / gridXsteps ;
m_transitionRects . push_back ( TQRect ( xPosition , yNext , xNext - xPosition , yPosition - yNext ) ) ;
xPosition = xNext ;
}
yPosition = yNext ;
}
}
else if ( angle = = 180 )
{
int xPosition = m_width ;
for ( int i = 0 ; i < gridXsteps ; i + + )
{
int xNext = ( ( gridXsteps - ( i + 1 ) ) * m_width ) / gridXsteps ;
int yPosition = 0 ;
for ( int j = 0 ; j < gridYsteps ; j + + )
{
int yNext = ( ( j + 1 ) * m_height ) / gridYsteps ;
m_transitionRects . push_back ( TQRect ( xNext , yPosition , xPosition - xNext , yNext - yPosition ) ) ;
yPosition = yNext ;
}
xPosition = xNext ;
}
}
else if ( angle = = 270 )
{
int yPosition = 0 ;
for ( int i = 0 ; i < gridYsteps ; i + + )
{
int yNext = ( ( i + 1 ) * m_height ) / gridYsteps ;
int xPosition = 0 ;
for ( int j = 0 ; j < gridXsteps ; j + + )
{
int xNext = ( ( j + 1 ) * m_width ) / gridXsteps ;
m_transitionRects . push_back ( TQRect ( xPosition , yPosition , xNext - xPosition , yNext - yPosition ) ) ;
xPosition = xNext ;
}
yPosition = yNext ;
}
}
else // if angle is 0 or 315
{
int xPosition = 0 ;
for ( int i = 0 ; i < gridXsteps ; i + + )
{
int xNext = ( ( i + 1 ) * m_width ) / gridXsteps ;
int yPosition = 0 ;
for ( int j = 0 ; j < gridYsteps ; j + + )
{
int yNext = ( ( j + 1 ) * m_height ) / gridYsteps ;
m_transitionRects . push_back ( TQRect ( xPosition , yPosition , xNext - xPosition , yNext - yPosition ) ) ;
yPosition = yNext ;
}
xPosition = xNext ;
}
}
// add a 'glitter' (1 over 10 pieces is randomized)
int randomSteps = steps / 20 ;
for ( int i = 0 ; i < randomSteps ; i + + )
{
int n1 = ( int ) ( steps * drand48 ( ) ) ;
int n2 = ( int ) ( steps * drand48 ( ) ) ;
// swap items if index differs
if ( n1 ! = n2 )
{
TQRect r = m_transitionRects [ n2 ] ;
m_transitionRects [ n2 ] = m_transitionRects [ n1 ] ;
m_transitionRects [ n1 ] = r ;
}
}
// set global transition parameters
m_transitionMul = ( angle = = 90 ) | | ( angle = = 270 ) ? gridYsteps : gridXsteps ;
m_transitionMul / = 2 ;
m_transitionDelay = ( int ) ( ( m_transitionMul * 1000 * totalTime ) / steps ) ;
} break ;
// implement missing transitions (a binary raster engine needed here)
case KPDFPageTransition : : Fly :
case KPDFPageTransition : : Push :
case KPDFPageTransition : : Cover :
case KPDFPageTransition : : Uncover :
case KPDFPageTransition : : Fade :
default :
update ( ) ;
return ;
}
// send the first start to the timer
m_transitionTimer - > start ( 0 , true ) ;
}
# include "presentationwidget.moc"