splitViewInterface.cpp

Go to the documentation of this file.
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 <qpainter.h>
00013 #include <qcursor.h>
00014 
00015 //Projectwide includes
00016 #include "splitViewInterface.h"
00017 #include "../cursors.h"
00018 #include "../../backend/tools/imageTools.h"
00019 
00020 #define TEXT_BACKGROUND_MARGIN 2
00021 #define TEXT_INSET 4
00022 
00023 //a mouse press within DRAG_THRESHOLD will move split point
00024 #define DRAG_THRESHOLD 8
00025 
00026 //==============================================
00027 SplitViewInterface::SplitViewInterface( QWidget *parent, const char* name ) : 
00028                                         QWidget (parent, name )
00029 {                  
00030   //setup split point                                          
00031   dragOffset = 0.5;                                          
00032   mouseMode = NO_EFFECT_ON_SPLIT;  
00033   currentMouseShape = NO_EFFECT_ON_SPLIT;
00034   
00035   //set default mode to adjusted image
00036   previewMode = SPLIT_VIEW;
00037   
00038   //don't force draw labels by default. this is useful when
00039   //the user pressed the Ctrl button or other key to toggle between opposite views
00040   //and drop down menu for choosing display type disagrees with actuall image being shown.
00041   forceDrawLabel = false;
00042   
00043   //setup strings and fonts
00044   originalString = QString( tr("Original") );
00045   adjustedString = QString( tr("Adjusted") );          
00046   
00047   textFont = this->font();
00048   textFont.setPointSize( textFont.pointSize() + 7 );  
00049   
00050   //watch mouse movements in order to drag selection
00051   //watch mouse movements in order to move split point between adjusted and original image
00052   setMouseTracking(true);
00053   
00054   //accept focus when clicked on
00055   setFocusPolicy( QWidget::ClickFocus );
00056 }
00057 //==============================================
00058 void SplitViewInterface::paintEvent(QPaintEvent *e)
00059 { 
00060   //if orig image not setup yet then return immediately
00061   if(origImage.isNull()) { return; }
00062 
00063   //if viewing adjusted or split view and adjusted image is null bail  
00064   if( 
00065       (previewMode == ADJUSTED_IMAGE || previewMode == SPLIT_VIEW ) &&
00066       adjustedImage.isNull() 
00067     )
00068   { return; }
00069   
00070   //create buffer to draw in
00071   QPixmap buffer( size() );
00072   
00073   //create a painter pointing to the buffer
00074   QPainter bufferPainter( &buffer );
00075   
00076   //turn off clipping to make painting operations faster
00077   bufferPainter.setClipping(false);
00078 
00079   //initialize buffer with background brush
00080   bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
00081 
00082   //setup pen color
00083   QPen pen;
00084   pen.setStyle( Qt::SolidLine );
00085   pen.setColor( white );
00086   pen.setWidth( 2 );
00087   bufferPainter.setPen( pen);  
00088 
00089   int xOffset = (width() - origImage.width()) / 2;
00090   int yOffset = (height() - origImage.height()) / 2;
00091 
00092   //setup font metrics
00093   bufferPainter.setFont( textFont );
00094   QFontMetrics fm( textFont );
00095 
00096   //paint the adjusted image
00097   if(previewMode == ADJUSTED_IMAGE)
00098   {
00099     bufferPainter.drawImage( QPoint(xOffset, yOffset), adjustedImage );
00100 
00101     //"Adjusted" label
00102     if(forceDrawLabel)
00103     {
00104       int x = xOffset + (origImage.width()-fm.width(adjustedString))/2;
00105       int y = yOffset + fm.ascent() + TEXT_INSET;
00106     
00107       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00108                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00109                                     fm.width(adjustedString) + 2*TEXT_BACKGROUND_MARGIN, 
00110                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00111                               QBrush(darkGray) );    
00112       bufferPainter.drawText( x, y,
00113                               adjustedString );    
00114     }
00115   }
00116   //paint the original image
00117   else if(previewMode == ORIGINAL_IMAGE)
00118   {
00119     bufferPainter.drawImage( QPoint(xOffset, yOffset), origImage );
00120 
00121     //"Original" label
00122     if(forceDrawLabel)
00123     {
00124       int x = xOffset + (origImage.width()-fm.width(originalString))/2;
00125       int y = yOffset + fm.ascent() + TEXT_INSET;
00126     
00127       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00128                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00129                                     fm.width(originalString) + 2*TEXT_BACKGROUND_MARGIN, 
00130                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00131                               QBrush(darkGray) );    
00132       bufferPainter.drawText( x, y,
00133                               originalString );    
00134     }
00135   }
00136   //if using split view also draw line down center and original image on left
00137   else if(previewMode == SPLIT_VIEW ||
00138           previewMode == INV_SPLIT_VIEW )
00139   {
00140     //determine what left/right or top/bottom strings are
00141     QString label1, label2;
00142     if(previewMode == SPLIT_VIEW)
00143     {
00144       label1 = originalString;
00145       label2 = adjustedString;
00146     }
00147     else
00148     {
00149       label2 = originalString;
00150       label1 = adjustedString;
00151     }
00152     
00153     //find split point in screen coordinates
00154     int halfWay = worldToDisplay( dragOffset );
00155     
00156     //paint the original image
00157     bufferPainter.drawImage( QPoint(xOffset, yOffset), origImage );
00158 
00159     //-------
00160     if(origImage.width() > origImage.height() )
00161     {    
00162       //paint the adjusted image
00163       if(previewMode == SPLIT_VIEW)
00164       {
00165         bufferPainter.drawImage( xOffset + halfWay, 
00166                                  yOffset,
00167                                  adjustedImage,
00168                                  halfWay,0,
00169                                  origImage.width() - halfWay,
00170                                  origImage.height() );  
00171       }
00172       else
00173       {
00174         bufferPainter.drawImage( xOffset, 
00175                                  yOffset,
00176                                  adjustedImage,
00177                                  0,0,
00178                                  halfWay,
00179                                  origImage.height() );  
00180       }
00181 
00182       
00183       //paint white line
00184       bufferPainter.drawLine( xOffset + halfWay,
00185                               yOffset,
00186                               xOffset + halfWay,
00187                               yOffset + origImage.height() );
00188 
00189       //Left label
00190       int x = xOffset + (halfWay-fm.width(label1))/2;
00191       int y = yOffset + fm.ascent() + TEXT_INSET;
00192       
00193       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00194                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00195                                     fm.width(label1) + 2*TEXT_BACKGROUND_MARGIN, 
00196                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00197                               QBrush(darkGray) );    
00198       bufferPainter.drawText( x, y,
00199                               label1 );    
00200 
00201       //Right label
00202       x = xOffset + halfWay + (origImage.width() - halfWay - fm.width(label2))/2;
00203       
00204       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00205                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00206                                     fm.width(label2) + 2*TEXT_BACKGROUND_MARGIN, 
00207                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00208                               QBrush(darkGray) );    
00209       bufferPainter.drawText( x, y,
00210                               label2 );
00211     }
00212     //-------
00213     else
00214     {
00215       //paint the adjusted image
00216       if(previewMode == SPLIT_VIEW)
00217       {
00218         bufferPainter.drawImage( xOffset, 
00219                                  yOffset + halfWay,
00220                                  adjustedImage,
00221                                  0,halfWay,
00222                                  origImage.width(),
00223                                  origImage.height()-halfWay );  
00224       }
00225       else
00226       {
00227         bufferPainter.drawImage( xOffset, 
00228                                  yOffset,
00229                                  adjustedImage,
00230                                  0,0,
00231                                  origImage.width(),
00232                                  halfWay );  
00233       }
00234       
00235       //paint white line
00236       bufferPainter.drawLine( xOffset,
00237                               yOffset + halfWay,
00238                               xOffset + origImage.width(),
00239                               yOffset + halfWay );
00240 
00241       //Top label
00242       int x = xOffset + (origImage.width()-fm.width(label1))/2;
00243       int y = yOffset + fm.ascent() + TEXT_INSET;
00244       
00245       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00246                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00247                                     fm.width(label1) + 2*TEXT_BACKGROUND_MARGIN, 
00248                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00249                               QBrush(darkGray) );    
00250       bufferPainter.drawText( x, y,
00251                               label1 );    
00252       
00253       //Bottom label
00254       x = xOffset + (origImage.width()-fm.width(label2))/2;
00255       y = yOffset + halfWay + fm.height();
00256       
00257       bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN, 
00258                                     y - TEXT_BACKGROUND_MARGIN - fm.ascent(), 
00259                                     fm.width(label2) + 2*TEXT_BACKGROUND_MARGIN, 
00260                                     fm.height() + 2*TEXT_BACKGROUND_MARGIN),
00261                               QBrush(darkGray) );    
00262       bufferPainter.drawText( x, y,
00263                               label2 );
00264     }
00265     //-------    
00266   }
00267 
00268   //end painter  
00269   bufferPainter.end();
00270   
00271   //blit buffer to screen
00272   bitBlt( this,
00273           e->rect().x(), e->rect().y(),
00274           &buffer, 
00275           e->rect().x(), e->rect().y(),
00276           e->rect().width(), e->rect().height() );
00277 }
00278 //==============================================
00279 void SplitViewInterface::setPreviewMode( PREVIEW_MODE mode, bool forceDrawLabel )
00280 {
00281   //set mode and repaint
00282   previewMode = mode;
00283   this->forceDrawLabel = forceDrawLabel;
00284   repaint(false);
00285 }
00286 //==============================================
00287 bool SplitViewInterface::nearSplitPoint( QPoint p )
00288 {
00289   //always false if not in split view mode
00290   if( previewMode != SPLIT_VIEW )
00291     return false;
00292   
00293   //compute painting offset and get important mouse coordinate
00294   int paintingOffset;
00295   int mousePos;
00296   if(origImage.width() > origImage.height())
00297   {
00298     paintingOffset = (width() - origImage.width()) / 2;
00299     mousePos = p.x();
00300   }
00301   else
00302   {
00303     paintingOffset = (height() - origImage.height()) / 2;
00304     mousePos = p.y();
00305   }
00306   
00307   //convert drag offset to display coordinates
00308   int displayCoor = worldToDisplay( dragOffset) + paintingOffset;
00309   
00310   //check if within threshold of split point
00311   return ( mousePos > displayCoor - DRAG_THRESHOLD &&
00312            mousePos < displayCoor + DRAG_THRESHOLD);
00313 }
00314 //==============================================
00315 void SplitViewInterface::mousePressEvent( QMouseEvent *e)
00316 { 
00317   //if within threshold of split point enter drag split mode
00318   if( nearSplitPoint(e->pos()) )  
00319     mouseMode = DRAG_SPLIT;
00320 }
00321 //==============================================
00322 void SplitViewInterface::mouseMoveEvent( QMouseEvent *e)
00323 {
00324   //if not dragging split point update mosue cursor
00325   if(mouseMode == NO_EFFECT_ON_SPLIT)
00326   {
00327     if( !nearSplitPoint(e->pos()) && currentMouseShape == DRAG_SPLIT )
00328     { 
00329       currentMouseShape = NO_EFFECT_ON_SPLIT;
00330       setCursor( Qt::ArrowCursor ); 
00331     }
00332     else if( nearSplitPoint(e->pos()) && currentMouseShape == NO_EFFECT_ON_SPLIT )
00333     {
00334       currentMouseShape = DRAG_SPLIT;
00335       if( origImage.width() > origImage.height() )
00336       {
00337         setCursor( getCursor(MOVE_HOR_CURSOR) );
00338       }
00339       else
00340       {
00341         setCursor( getCursor(MOVE_VERT_CURSOR) );
00342       }
00343     }
00344 
00345     return;
00346   }
00347   
00348   //compute painting offset, get important mouse
00349   //coordinate and clamp to valid range
00350   QFontMetrics fm( textFont );
00351   int paintingOffset;
00352   int mousePos;
00353   if(origImage.width() > origImage.height())
00354   {
00355     paintingOffset = (width() - origImage.width()) / 2;
00356     mousePos = e->pos().x();
00357     mousePos = QMAX( mousePos, paintingOffset + 4*TEXT_BACKGROUND_MARGIN + fm.width(originalString) );
00358     mousePos = QMIN( mousePos, paintingOffset + origImage.width() - 
00359                      fm.width(adjustedString) - 2*TEXT_BACKGROUND_MARGIN - 2*TEXT_INSET);
00360   }
00361   else
00362   {
00363     paintingOffset = (height() - origImage.height()) / 2;
00364     mousePos = e->pos().y();
00365     mousePos = QMAX( mousePos, paintingOffset + 4*TEXT_BACKGROUND_MARGIN + fm.height() );
00366     mousePos = QMIN( mousePos, paintingOffset + origImage.height() - 
00367                      fm.height() - 2*TEXT_BACKGROUND_MARGIN - 2*TEXT_INSET);
00368   }
00369   
00370   //update location of split point and repaint
00371   dragOffset = displayToWorld(mousePos - paintingOffset);   
00372   repaint(false);  
00373 }
00374 //==============================================
00375 void SplitViewInterface::mouseReleaseEvent( QMouseEvent *e)
00376 {
00377   //disable dragging
00378   mouseMode = NO_EFFECT_ON_SPLIT;  
00379 
00380   //update mouse cursor if necessary
00381   if( !nearSplitPoint(e->pos()) && currentMouseShape == DRAG_SPLIT )
00382   { 
00383     currentMouseShape = NO_EFFECT_ON_SPLIT;
00384     setCursor( Qt::ArrowCursor ); 
00385   }  
00386 }
00387 //==============================================
00388 double SplitViewInterface::displayToWorld( int coordinate )
00389 {
00390   if( origImage.width() > origImage.height() )
00391   { return ((double) (coordinate+1))/origImage.width(); }
00392   else
00393   { return ((double) (coordinate+1))/origImage.height(); }
00394 }
00395 //==============================================
00396 int SplitViewInterface::worldToDisplay( double coordinate )
00397 {
00398   if( origImage.width() > origImage.height() )
00399   { return (int) (coordinate*(origImage.width() -1) ); }
00400   else
00401   { return (int) (coordinate*(origImage.height()-1) ); }
00402 }
00403 //==============================================
00404 QSize SplitViewInterface::minimumSizeHint() const
00405 {
00406   QFontMetrics fm( textFont );
00407   int w = 5*TEXT_BACKGROUND_MARGIN + fm.width(originalString) + fm.width(adjustedString);
00408   int h = 2*TEXT_BACKGROUND_MARGIN + fm.height(); 
00409   return QSize( w, h );
00410 }
00411 //==============================================
00412 QImage& SplitViewInterface::getOrigImage()
00413 { return origImage; }
00414 //==============================================
00415 void SplitViewInterface::setImages( QImage origImage, 
00416                                     QImage adjustedImage )
00417 {
00418   this->origImage = origImage;
00419   this->adjustedImage = adjustedImage;
00420   repaint(false);
00421 }
00422 //==============================================
00423 void SplitViewInterface::setAdjustedImage( QImage adjustedImage )
00424 {
00425   this->adjustedImage = adjustedImage;
00426   repaint(false);
00427 }
00428 //==============================================
00429 

Generated on Wed Jan 24 05:38:28 2007 for AlbumShaper by  doxygen 1.5.1