SelectionInterface Class Reference

Display widget for photos. Used by the PhotoEditWidget. More...

#include <selectionInterface.h>

Inheritance diagram for SelectionInterface:
[legend]
Collaboration diagram for SelectionInterface:
[legend]

List of all members.

Public Slots

void selectNone ()
 selects none of the image
void selectAll ()
 selects all of the image

Signals

void ctrlClick ()
 emitted when a user CTRL-clicks a selection indicating the selection needs to be rotated intelligently
void selectionChanged ()
 emitted when the user changed the selected region
void aspectRatioChanged ()
 emitted when the user changed the aspect ratio of the selected region
void lineSelected (QPoint p1, QPoint p2)
 emitted once line has been selected, on or the other points will be set to -1,-1 if the user escaped out the selected a line

Public Member Functions

 SelectionInterface (QWidget *parent=0, const char *name=0)
 Creates layout.
 ~SelectionInterface ()
 Deletes objects.
void setPhoto (QString imageFilename, bool resetSelection=true)
 Updates displayed photo.
void getSelection (QPoint &topLeft, QPoint &bottomRight)
 Returns the current selected coordinates (actual slideshow image space, aka not including buffered whitespace or widget offsets).
void setSelection (QPoint topLeft, QPoint bottomRight, double cropMaxDimen=-1.0)
 Sets the current selection cropMaxDimen specifies the idealized dimension in dominant direction in inches (eg 7").
bool selectionEmpty ()
 returns true if selection is empty
void getDisplaySize (int &width, int &height)
 returns the current photo display size (in screen pixels)
void enterDrawLineMode ()
 enter draw line mode - used for tilt correction

Protected Member Functions

QSize sizeHint ()
void paintEvent (QPaintEvent *e)
void mousePressEvent (QMouseEvent *e)
void mouseReleaseEvent (QMouseEvent *)
void mouseMoveEvent (QMouseEvent *e)
void resizeEvent (QResizeEvent *)
void keyPressEvent (QKeyEvent *e)
void keyReleaseEvent (QKeyEvent *e)

Private Member Functions

DRAG_MODE mouseActionByPosition (QPoint p)
 determine action based on mouse position
QPoint cropSelectedPoint (QPoint p)
 crops a selected point to within the photo
QPoint ConvertDisplayToImageCoordinate (QPoint p)
 converts a point from display coordinates to original image coordinates
QPoint ConvertImageToDisplayCoordinate (QPoint p)
 converts a point from original image coordinates to display coordinates
void constructDisplayImages ()
 construct scaled image and unselected images for drawing purposes
void updateCursorShape (QPoint p)
 update mouse cursor based on position over widget and selected region
bool scaleSelection (int delta)
 increase/decrease selection while maintaining aspect ratio by changing selected width by delta

Private Attributes

QImage fullScreenImage
 Full screen version of image.
QImage scaledImage
 Scaled image used for display purposes.
QImage unselectedScaledImage
 Grayscale version of scaled image, used for drawing non-selected regions.
QPoint mousePressPoint
 first corner of selection, where mouse first clicked
QPoint mouseDragPoint
 second corner of selection, where mouse moved to
QPoint cachedMousePosition
 cached mouse position, used to scale or drag around selection area
DRAG_MODE currentDragMode
 method of dragging out, either new selection or resizing selection corner or side
DRAG_MODE currentMouseShape
 current mouse shape.
QString origImageFilename
 original image filename
QSize origImageSize
 original image dimensions
bool SHIFT_Pressed
 state of SHIFT button, effects if mouse drags adjust or scale the current selection
bool CTRL_Pressed
 state of CTRL button, effects if mouse clicks rotate current selection
QPoint cachedSelctionCenter
 cache the aspect ratio when pressing the control buttion, this helps aleviate numerical error that builds up when scaling up and down selections
QSize cachedSelectionSize
double cropMaxDimen
 Current crop max dimension (in inches).


Detailed Description

Display widget for photos. Used by the PhotoEditWidget.

Definition at line 44 of file selectionInterface.h.


Constructor & Destructor Documentation

SelectionInterface::SelectionInterface ( QWidget parent = 0,
const char *  name = 0 
)

Creates layout.

Definition at line 41 of file selectionInterface.cpp.

References cachedMousePosition, cropMaxDimen, currentDragMode, currentMouseShape, mouseDragPoint, mousePressPoint, NO_EFFECT, selectAll(), and selectNone().

00041                                                                          : QWidget(parent,name)
00042 { 
00043   //avoid flicker when repainting
00044   setWFlags(WRepaintNoErase);
00045 
00046   //set default selection off screen
00047   mousePressPoint = QPoint(-1,-1);
00048   mouseDragPoint = QPoint(-1,-1);
00049   
00050   //by default mouse movement does not effect the current selection
00051   currentDragMode = NO_EFFECT;
00052   currentMouseShape = NO_EFFECT;
00053     
00054   QAccel *keyAccel = new QAccel( this );
00055   keyAccel->connectItem( keyAccel->insertItem( CTRL + Key_A),
00056                          this, SLOT(selectAll()) );
00057   keyAccel->connectItem( keyAccel->insertItem( CTRL + SHIFT + Key_A ),
00058                          this, SLOT(selectNone()) );
00059   
00060   //watch mouse movements in order to change mouse cursor
00061   setMouseTracking(true);
00062 
00063   //accept focus when clicked on
00064   setFocusPolicy( QWidget::ClickFocus );
00065   
00066   //initialize cached mouse position to be offscreen by default
00067   cachedMousePosition = QPoint(-1,-1);  
00068 
00069   //no crop size by default
00070   cropMaxDimen = -1.0;
00071 }

SelectionInterface::~SelectionInterface (  ) 

Deletes objects.

Definition at line 73 of file selectionInterface.cpp.

00073 { }


Member Function Documentation

void SelectionInterface::aspectRatioChanged (  )  [signal]

emitted when the user changed the aspect ratio of the selected region

Referenced by mouseMoveEvent(), mousePressEvent(), selectAll(), and selectNone().

void SelectionInterface::constructDisplayImages (  )  [private]

construct scaled image and unselected images for drawing purposes

Definition at line 117 of file selectionInterface.cpp.

References b, fullScreenImage, height, HSVtoRGB(), RGBtoHSV(), scaledImage, unselectedScaledImage, and width.

Referenced by resizeEvent(), and setPhoto().

00118 {  
00119   //rescale image to fit on screen
00120   scaledImage = fullScreenImage.scale( width(), height(), QImage::ScaleMin );     
00121   
00122   //construct an unselected scaled image
00123   unselectedScaledImage = scaledImage.copy();  
00124   int x, y;
00125   QRgb* rgb;
00126   uchar* scanLine;
00127   for( y=0; y<unselectedScaledImage.height(); y++)
00128   {   
00129     //iterate over each selected pixel in scanline
00130     scanLine = unselectedScaledImage.scanLine(y);
00131     for( x=0; x<unselectedScaledImage.width(); x++)
00132     {
00133       //compress dynamic range to 25% of original
00134       rgb = ((QRgb*)scanLine+x);
00135       
00136       double r = ((double)qRed(*rgb)   )/255.0;
00137       double g = ((double)qGreen(*rgb) )/255.0;
00138       double b = ((double)qBlue(*rgb)  )/255.0;
00139       
00140       //convert to hsv
00141       double h,s,v;
00142       RGBtoHSV(r,g,b,&h,&s,&v);
00143       
00144       //scale and clamp v
00145       v*=0.25;
00146       
00147       //convert adjusted color back to rgb colorspace and clamp
00148       HSVtoRGB( &r,&g,&b, h,s,v);         
00149       int rp = (int) QMIN( QMAX((r*255), 0), 255 );
00150       int gp = (int) QMIN( QMAX((g*255), 0), 255 );
00151       int bp = (int) QMIN( QMAX((b*255), 0), 255 );
00152       
00153       //set adjusted color value
00154       *rgb = qRgb(rp,gp,bp);          
00155     }
00156   }  
00157   
00158   
00159 }

QPoint SelectionInterface::ConvertDisplayToImageCoordinate ( QPoint  p  )  [private]

converts a point from display coordinates to original image coordinates

Definition at line 874 of file selectionInterface.cpp.

References height, origImageSize, scaledImage, and width.

Referenced by mouseMoveEvent(), mousePressEvent(), and mouseReleaseEvent().

00875 {  
00876   QPoint newPoint = p;
00877   
00878   //remove display offset
00879   int xOffset = (width() - scaledImage.width()   ) / 2;
00880   int yOffset = (height() - scaledImage.height() ) / 2;  
00881   newPoint.setX( newPoint.x() - xOffset );
00882   newPoint.setY( newPoint.y() - yOffset );
00883   
00884   //if coordinate is at max set new value explicitly to avoid roundoff error,
00885   //otherwise scale to full image dimensions
00886   if(newPoint.x() == scaledImage.width() - 1)
00887     newPoint.setX( origImageSize.width() - 1);
00888   else 
00889     newPoint.setX( (int) (0.5 + ((double)(newPoint.x() * (origImageSize.width()-1))) / (scaledImage.width()-1) ) );
00890   
00891   if(newPoint.y() == scaledImage.height() - 1)
00892     newPoint.setY( origImageSize.height() - 1);
00893   else 
00894     newPoint.setY( (int) (0.5 + ((double)(newPoint.y() * (origImageSize.height()-1))) / (scaledImage.height()-1) ) );
00895   
00896   //return point in image coordinates
00897   return newPoint;
00898 }

QPoint SelectionInterface::ConvertImageToDisplayCoordinate ( QPoint  p  )  [private]

converts a point from original image coordinates to display coordinates

Definition at line 900 of file selectionInterface.cpp.

References height, origImageSize, scaledImage, and width.

Referenced by enterDrawLineMode(), keyPressEvent(), keyReleaseEvent(), mouseActionByPosition(), mouseMoveEvent(), mouseReleaseEvent(), and paintEvent().

00901 {       
00902   QPoint newPoint = p;
00903   
00904   //if coordinate is at max set new value explicitly to avoid roundoff error,
00905   //otherwise scale to full image dimensions
00906   if(newPoint.x() == origImageSize.width() - 1)
00907     newPoint.setX( scaledImage.width() - 1);
00908   else 
00909     newPoint.setX( (newPoint.x() * (scaledImage.width()-1)) / (origImageSize.width()-1) );
00910   
00911   if(newPoint.y() == origImageSize.height() - 1)
00912     newPoint.setY( scaledImage.height() - 1);
00913   else 
00914     newPoint.setY( (newPoint.y() * (scaledImage.height()-1)) / (origImageSize.height()-1) );
00915   
00916   //add display offset
00917   int xOffset = (width() - scaledImage.width()   ) / 2;
00918   int yOffset = (height() - scaledImage.height() ) / 2;  
00919   newPoint.setX( newPoint.x() + xOffset );
00920   newPoint.setY( newPoint.y() + yOffset );
00921     
00922   //return point in image coordinates
00923   return newPoint;
00924 }

QPoint SelectionInterface::cropSelectedPoint ( QPoint  p  )  [private]

crops a selected point to within the photo

Definition at line 926 of file selectionInterface.cpp.

References height, scaledImage, and width.

Referenced by mouseMoveEvent().

00927 {    
00928   int xOffset = (width() - scaledImage.width()   ) / 2;
00929   int yOffset = (height() - scaledImage.height() ) / 2;
00930 
00931   QPoint croppedPoint;
00932   croppedPoint.setX( QMIN( QMAX(xOffset, p.x()), xOffset + scaledImage.width() - 1 ) );
00933   croppedPoint.setY( QMIN( QMAX(yOffset, p.y()), yOffset + scaledImage.height() - 1 ) );
00934   return croppedPoint;
00935 }

void SelectionInterface::ctrlClick (  )  [signal]

emitted when a user CTRL-clicks a selection indicating the selection needs to be rotated intelligently

Referenced by mousePressEvent().

void SelectionInterface::enterDrawLineMode (  ) 

enter draw line mode - used for tilt correction

Definition at line 1182 of file selectionInterface.cpp.

References cachedMousePosition, ConvertImageToDisplayCoordinate(), CTRL_Pressed, currentDragMode, DRAW_LINE, mouseDragPoint, mousePressPoint, SHIFT_Pressed, and updateCursorShape().

Referenced by EditingInterface::startCorrectTilt().

01183 {
01184   //set the current mode
01185   currentDragMode = DRAW_LINE;
01186 
01187   //during draw line mode ignore control and shift keys, they are only useful for adjusting
01188   //selections, not lines
01189   SHIFT_Pressed = false;
01190   CTRL_Pressed = false;
01191   
01192   //reset 1st point
01193   mousePressPoint = QPoint( -1, -1 );
01194   mouseDragPoint = QPoint( -1, -1 );
01195   
01196   //repaint and reset the mouse cursor
01197   updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01198   repaint(false);
01199 }

void SelectionInterface::getDisplaySize ( int &  width,
int &  height 
)

returns the current photo display size (in screen pixels)

Definition at line 1010 of file selectionInterface.cpp.

References scaledImage.

Referenced by EditingInterface::applyImageUpdate(), EditingInterface::revertCurrentPhoto(), EditingInterface::rotateFlip(), EditingInterface::setPhoto(), and EditingInterface::showNextPrevFirstLastPhoto().

01011 {
01012   width = scaledImage.width();
01013   height = scaledImage.height();  
01014 }

void SelectionInterface::getSelection ( QPoint &  topLeft,
QPoint &  bottomRight 
)

Returns the current selected coordinates (actual slideshow image space, aka not including buffered whitespace or widget offsets).

Definition at line 993 of file selectionInterface.cpp.

References mouseDragPoint, and mousePressPoint.

Referenced by EditingInterface::findSelection(), EditingInterface::rotateSelection(), and EditingInterface::selectAspectRatio().

00994 {
00995   //if none selected just return immediately
00996   if(mousePressPoint.x() == -1)
00997   {
00998     topLeft.setX(-1); topLeft.setY(-1);
00999     bottomRight.setX(-1); bottomRight.setY(-1);
01000     return;
01001   }
01002 
01003   //set coordinates based on raw selection  
01004   topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) );
01005   topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
01006   bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) );                
01007   bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) );                  
01008 }

void SelectionInterface::keyPressEvent ( QKeyEvent *  e  )  [protected]

Definition at line 1016 of file selectionInterface.cpp.

References bottomRight, cachedMousePosition, cachedSelctionCenter, ConvertImageToDisplayCoordinate(), CTRL_Pressed, currentDragMode, DRAW_LINE, lineSelected(), mouseDragPoint, mousePressPoint, NO_EFFECT, origImageSize, scaledImage, scaleSelection(), selectionChanged(), selectionEmpty(), selectNone(), SHIFT_Pressed, topLeft, and updateCursorShape().

01017 {
01018   //if currently drawing a line, allow the user
01019   //to escape the current acction by hiting escape, all other
01020   //key presses are ignored
01021   if( currentDragMode == DRAW_LINE )
01022   {
01023     if(e->key() == Qt::Key_Escape )
01024     {
01025       //reset mode, press and drag points so there is no selection, and mouse cursor
01026       currentDragMode = NO_EFFECT;
01027       selectNone();
01028       updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01029     
01030       //emit an invalid line
01031       emit lineSelected( QPoint(-1,-1), QPoint(-1,-1) );       
01032     }
01033 
01034     return; 
01035   }
01036   
01037   //if user pressed SHIFT button and selection non-empty 
01038   //then note state change, 
01039   //this will effect resizing selections during drag events
01040   if(e->key() == Qt::Key_Shift && !selectionEmpty() )
01041   {    
01042     SHIFT_Pressed = true;
01043     updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01044     return;
01045   }
01046 
01047   //if user pressed CTRL button and selection non-empty 
01048   //then note state change, 
01049   //this will effect mouse clicks by rotating the current selection
01050   if(e->key() == Qt::Key_Control && !selectionEmpty() && !SHIFT_Pressed )
01051   {    
01052     CTRL_Pressed = true;
01053     updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01054     return;
01055   }
01056     
01057   //ignore keypress if selection is empty
01058   if(mousePressPoint.x() == -1 ||
01059      mousePressPoint.x() - mouseDragPoint.x() == 0 ||
01060      mousePressPoint.y()  - mouseDragPoint.y() == 0)
01061   {
01062     e->ignore();
01063     return;
01064   }
01065 
01066   //ignore keypresses while mouse button is down since
01067   //intended behavious is unclear
01068   if( currentDragMode != NO_EFFECT )
01069   {
01070     e->ignore();
01071     return;
01072   }
01073   
01074   //-------  
01075   //if += / -_ keys are pressed scale selection
01076   if( e->key() == Qt::Key_Plus ||
01077       e->key() == Qt::Key_Equal ||
01078       e->key() == Qt::Key_Minus ||
01079       e->key() == Qt::Key_Underscore )
01080   {
01081     int delta = 2*QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
01082     
01083     delta = 1;
01084     
01085     //negate delta if decreasing size
01086     if( e->key() == Qt::Key_Minus ||
01087         e->key() == Qt::Key_Underscore )
01088       delta = -delta;
01089     
01090     if( scaleSelection( delta ) )
01091     {    
01092       //repaint the selection
01093       repaint(false);
01094       emit selectionChanged();
01095     }
01096     return;
01097   }
01098   //-------  
01099   
01100   //find topleft and bottom right of current selection
01101   QPoint topLeft, bottomRight;
01102   topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) );
01103   topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
01104   bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) );                
01105   bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) );                  
01106   
01107   //compute the number of pixels in the image correspond to one display pixel
01108   //this is the unit by which the selection will be moved
01109   int moveBy = 0;
01110   if( e->key() == Qt::Key_Left ||
01111       e->key() == Qt::Key_Right )
01112   {
01113     moveBy = QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
01114   }
01115   else
01116   {
01117     moveBy = QMAX( origImageSize.height(), scaledImage.height() ) / scaledImage.height();
01118   }
01119   
01120   //boundary checked moved by value. must be decalred outside switch statement below
01121   int dx = 0;
01122   int dy = 0;
01123   switch( e->key() )
01124   {
01125     case Qt::Key_Left:
01126       dx = QMAX( topLeft.x() - moveBy, 0) - topLeft.x();
01127       break;
01128     case Qt::Key_Right:
01129       dx = QMIN( bottomRight.x() + moveBy, origImageSize.width() - 1) - bottomRight.x();
01130       break;
01131     case Qt::Key_Up:
01132       dy = QMAX( topLeft.y() - moveBy, 0) - topLeft.y();
01133       break;
01134     case Qt::Key_Down:
01135       dy = QMIN( bottomRight.y() + moveBy, origImageSize.height() - 1) - bottomRight.y();
01136       break;
01137     default:
01138       e->ignore();
01139       return;
01140   }
01141   
01142   //shift by dx
01143   mousePressPoint.setX( mousePressPoint.x() + dx );
01144   mouseDragPoint.setX( mouseDragPoint.x() + dx );      
01145  
01146   //shift by dy
01147   mousePressPoint.setY( mousePressPoint.y() + dy );
01148   mouseDragPoint.setY( mouseDragPoint.y() + dy );      
01149 
01150   //recompute center
01151   cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
01152                                  ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
01153   
01154   //only bother with repaint and updating cursor shape if shift actually occured
01155   if(dx != 0 || dy != 0) 
01156   { 
01157     repaint(false);
01158     updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );  
01159   }
01160 }

void SelectionInterface::keyReleaseEvent ( QKeyEvent *  e  )  [protected]

Definition at line 1162 of file selectionInterface.cpp.

References cachedMousePosition, ConvertImageToDisplayCoordinate(), CTRL_Pressed, SHIFT_Pressed, and updateCursorShape().

01163 {
01164   //if user released SHIFT button then note state change, 
01165   //this will effect resizing selections during drag events
01166   if(e->key() == Qt::Key_Shift)
01167   {
01168     SHIFT_Pressed = false;
01169     updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01170   }
01171   //if user released CTRL button then note state change, 
01172   //this will effect mouse clicks
01173   else  if(e->key() == Qt::Key_Control)
01174   {
01175     CTRL_Pressed = false;
01176     updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
01177   }
01178   //unhandled key press: pass up the object tree
01179   else { e->ignore(); }
01180 }

void SelectionInterface::lineSelected ( QPoint  p1,
QPoint  p2 
) [signal]

emitted once line has been selected, on or the other points will be set to -1,-1 if the user escaped out the selected a line

Referenced by keyPressEvent(), and mouseReleaseEvent().

DRAG_MODE SelectionInterface::mouseActionByPosition ( QPoint  p  )  [private]

determine action based on mouse position

Definition at line 351 of file selectionInterface.cpp.

References bottomRight, ConvertImageToDisplayCoordinate(), DRAG_THRESHOLD, DRAW_SELECTION, height, mouseDragPoint, mousePressPoint, MOVE_BOTTOM_LEFT_CORNER, MOVE_BOTTOM_RIGHT_CORNER, MOVE_BOTTOM_SIDE, MOVE_LEFT_SIDE, MOVE_RIGHT_SIDE, MOVE_SELECTION, MOVE_THRESHOLD, MOVE_TOP_LEFT_CORNER, MOVE_TOP_RIGHT_CORNER, MOVE_TOP_SIDE, NO_EFFECT, origImageSize, SCALE_SELECTION, scaledImage, SHIFT_Pressed, topLeft, and width.

Referenced by mouseMoveEvent(), mousePressEvent(), and updateCursorShape().

00352 {   
00353   //If SHIFT_Pressed is set then scaling a selection
00354   if(SHIFT_Pressed) { return SCALE_SELECTION; }
00355   
00356   //construct topLeft and bottomRight points to make logic easier
00357   QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00358                   QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00359   QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00360                       QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
00361    
00362   //convert selelection bounary to display space since thresholds are all in display space
00363   topLeft = ConvertImageToDisplayCoordinate( topLeft );
00364   bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
00365     
00366   //compute selection center
00367   QPoint center( (topLeft.x() + bottomRight.x()) / 2,
00368                  (topLeft.y() + bottomRight.y()) / 2);
00369   
00370   //if pointer is not over image no effect will occur when clicking
00371   int xOffset = (width() - scaledImage.width()   ) / 2;
00372   int yOffset = (height() - scaledImage.height() ) / 2;  
00373   if(p.x() < xOffset || p.x() >= scaledImage.width() + xOffset ||
00374      p.y() < yOffset || p.y() >= scaledImage.height() + yOffset )
00375   { return NO_EFFECT; }
00376     
00377   //if either there is no selection or the entire image is selected, new
00378   //mouse clicks are interpreted as being for selecting new regions
00379   if( mousePressPoint.x() == -1 ||
00380       ( bottomRight.x() - topLeft.x() == origImageSize.width() - 1 &&
00381         bottomRight.y() - topLeft.y() == origImageSize.height() - 1 )
00382       )
00383   { return DRAW_SELECTION; }
00384   //move entire selection
00385   //mouse is within MOVE_THRESH of center and outside
00386   //DRAG_THRESH of any side
00387   else if( p.x() >= QMAX( center.x() - MOVE_THRESHOLD, topLeft.x() ) &&
00388            p.x() <= QMIN( center.x() + MOVE_THRESHOLD, bottomRight.x() ) &&
00389            p.y() >= QMAX( center.y() - MOVE_THRESHOLD, topLeft.y() ) &&
00390            p.y() <= QMIN( center.y() + MOVE_THRESHOLD, bottomRight.y() ) &&
00391            p.x() > topLeft.x() + DRAG_THRESHOLD &&
00392            p.x() < bottomRight.x() - DRAG_THRESHOLD &&
00393            p.y() > topLeft.y() + DRAG_THRESHOLD &&
00394            p.y() < bottomRight.y() - DRAG_THRESHOLD )
00395 { return MOVE_SELECTION; } 
00396   //drag top left
00397   else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
00398            QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD )  
00399   { return MOVE_TOP_LEFT_CORNER; }
00400   //drag top right    
00401   else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
00402            QABS(topLeft.y()     - p.y()) <= DRAG_THRESHOLD )  
00403   { return MOVE_TOP_RIGHT_CORNER; }
00404   //drag bottom left    
00405   else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
00406            QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )  
00407   { return MOVE_BOTTOM_LEFT_CORNER; }
00408   //drag bottom right
00409   else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
00410            QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )  
00411   { return MOVE_BOTTOM_RIGHT_CORNER; }
00412   //drag left
00413   else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
00414            p.y() >= topLeft.y() &&
00415            p.y() <= bottomRight.y() )
00416   { return MOVE_LEFT_SIDE; }
00417   //drag right
00418   else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
00419            p.y() >= topLeft.y() &&
00420            p.y() <= bottomRight.y() )
00421   { return MOVE_RIGHT_SIDE; }
00422   //drag top
00423   else if( QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD &&
00424            p.x() >= topLeft.x() &&
00425            p.x() <= bottomRight.x() )
00426   { return MOVE_TOP_SIDE; }
00427   //drag bottom
00428   else if( QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD &&
00429            p.x() >= topLeft.x() &&
00430            p.x() <= bottomRight.x() )
00431   { return MOVE_BOTTOM_SIDE; }
00432   //else new selection
00433   else { return DRAW_SELECTION; }
00434 }

void SelectionInterface::mouseMoveEvent ( QMouseEvent *  e  )  [protected]

Definition at line 651 of file selectionInterface.cpp.

References aspectRatioChanged(), bottomRight, cachedMousePosition, cachedSelctionCenter, cachedSelectionSize, ConvertDisplayToImageCoordinate(), ConvertImageToDisplayCoordinate(), cropMaxDimen, cropSelectedPoint(), CTRL_Pressed, currentDragMode, currentMouseShape, DRAW_LINE, DRAW_SELECTION, mouseActionByPosition(), mouseDragPoint, mousePressPoint, MOVE_BOTTOM_LEFT_CORNER, MOVE_BOTTOM_RIGHT_CORNER, MOVE_BOTTOM_SIDE, MOVE_LEFT_SIDE, MOVE_RIGHT_SIDE, MOVE_SELECTION, MOVE_TOP_LEFT_CORNER, MOVE_TOP_RIGHT_CORNER, MOVE_TOP_SIDE, NO_EFFECT, origImageSize, scaleSelection(), selectionChanged(), SHIFT_Pressed, topLeft, and updateCursorShape().

00652 {
00653   //if the SHIFT_Pressed state variable is true but SHIFT is now not pressed
00654   //reset bool and mouse cursor!
00655   if( SHIFT_Pressed && !(e->state() & Qt::ShiftButton) )
00656   {
00657     SHIFT_Pressed = false;
00658     updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) );   
00659   }
00660       
00661   //if the CTRL_Pressed state variable is true but CTRL is now not pressed
00662   //reset bool and mouse cursor!
00663   if( CTRL_Pressed && !(e->state() & Qt::ControlButton) )
00664   {
00665     CTRL_Pressed = false;
00666     updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) );   
00667   }  
00668   
00669   //if mouse not pressed update mouse cursor if 
00670   //mode will change if user presses mouse button
00671   if(currentDragMode == NO_EFFECT)
00672   {  
00673     //only update the mouse cursor shape if it will change
00674     if( mouseActionByPosition( e->pos() ) != currentMouseShape )
00675       updateCursorShape( e->pos() );
00676     
00677     cachedMousePosition = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );
00678   }
00679   //if currently in draw line mode update the selected line
00680   else if(currentDragMode == DRAW_LINE)
00681   {
00682     //if the 1st point hasn't been set yet do nothing
00683     if( mousePressPoint.x() == -1 )
00684       return;
00685     
00686     //1st point set, set 2nd point to current mouse position and redraw
00687     mouseDragPoint = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );
00688 
00689     //repaint the line
00690     repaint(false);
00691   }  
00692   //update selection rectangle or selected line
00693   else
00694   {     
00695     //get mouse position in original image coordinates
00696     QPoint p = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );
00697 
00698     //construct topLeft and bottomRight points to make logic easier
00699     QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00700                     QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00701     QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00702                         QMAX(mousePressPoint.y(), mouseDragPoint.y()) );     
00703     
00704     //if SHIFT pressed and both selction dimensions non-empty then scale selection
00705     if(SHIFT_Pressed && 
00706        bottomRight.x() > topLeft.x() && 
00707        bottomRight.y() > topLeft.y() )
00708     {
00709       //update width, prevent from growing beyond image boundaries
00710       int delta = p.x() - cachedMousePosition.x(); 
00711       if( !scaleSelection( delta ) )
00712       {
00713         //cache the current mouse position before returning without change
00714         cachedMousePosition = p;
00715         return;
00716       }
00717     }    
00718     //if draging the entire selection, update x and y coordinates for
00719     //both mousePress and mouseDrag points and update the dragSelectionPoint
00720     else if( currentDragMode == MOVE_SELECTION )
00721     {
00722       //compute offset
00723       QPoint offset( p.x() - cachedMousePosition.x(),
00724                      p.y() - cachedMousePosition.y() );
00725       
00726       //construct topLeft and bottomRight points to make logic easier
00727       QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00728                       QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00729       QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00730                           QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
00731       
00732       //clip offset so selected area is always within image boundaries
00733       
00734       //left
00735       if(offset.x() < 0 && topLeft.x() + offset.x() < 0 )
00736         offset.setX( -topLeft.x() );
00737       
00738       //right
00739       if(offset.x() > 0 && bottomRight.x() + offset.x() >= origImageSize.width() )
00740         offset.setX( origImageSize.width() - 1 - bottomRight.x() );          
00741       
00742       //top
00743       if(offset.y() < 0 && topLeft.y() + offset.y() < 0 )
00744         offset.setY( -topLeft.y() );
00745       
00746       //bottom
00747       if(offset.y() > 0 && bottomRight.y() + offset.y() >= origImageSize.height() )
00748         offset.setY( origImageSize.height() - 1 - bottomRight.y() );            
00749       
00750       //update press and drag points
00751       mousePressPoint+= offset;
00752       mouseDragPoint+= offset;      
00753       
00754       //recompute selection center
00755       cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00756                                      ( mouseDragPoint.y() + mousePressPoint.y() )/2 );          
00757     }        
00758     //if moving any corner or drawing the original selection, 
00759     //update x and y coords of drag point
00760     else if( currentDragMode == DRAW_SELECTION ||
00761              currentDragMode == MOVE_TOP_LEFT_CORNER ||
00762              currentDragMode == MOVE_TOP_RIGHT_CORNER ||
00763              currentDragMode == MOVE_BOTTOM_LEFT_CORNER ||
00764              currentDragMode == MOVE_BOTTOM_RIGHT_CORNER )
00765     {
00766       mouseDragPoint.setX( p.x() );
00767       mouseDragPoint.setY( p.y() );
00768       cropMaxDimen = -1.0;
00769       
00770       //cache selection size and center, necessary for computing next size
00771       cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
00772                                    QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
00773       cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00774                                      ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
00775       
00776       
00777       emit aspectRatioChanged();
00778     }
00779     //else if moving the left or right sides just update the x coordinate of 
00780     //the drag point
00781     else if( currentDragMode == MOVE_LEFT_SIDE ||
00782              currentDragMode == MOVE_RIGHT_SIDE )
00783     {
00784       mouseDragPoint.setX( p.x() );
00785       cropMaxDimen = -1.0;
00786       emit aspectRatioChanged();
00787       
00788       //cache selection size and center, necessary for computing next size
00789       cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
00790                                    QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);                                               
00791       cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00792                                      ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
00793     }
00794     //else if moving the top or bottom sides just update the x coordinate of 
00795     //the drag point
00796     else if( currentDragMode == MOVE_TOP_SIDE ||
00797              currentDragMode == MOVE_BOTTOM_SIDE )
00798     {
00799       mouseDragPoint.setY( p.y() );
00800       cropMaxDimen = -1.0;
00801       emit aspectRatioChanged();
00802       
00803       //cache selection size and center, necessary for computing next size
00804       cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
00805                                    QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);                                               
00806       cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00807                                      ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
00808       
00809     }    
00810     
00811     //cache current mouse position
00812     cachedMousePosition = p;
00813 
00814     //repaint the selection
00815     repaint(false);
00816     emit selectionChanged();
00817 
00818     //only update the mouse cursor shape if it will change
00819     if( mouseActionByPosition( e->pos() ) != currentMouseShape )
00820       updateCursorShape( e->pos() );
00821   }
00822 }

void SelectionInterface::mousePressEvent ( QMouseEvent *  e  )  [protected]

Definition at line 436 of file selectionInterface.cpp.

References aspectRatioChanged(), bottomRight, ConvertDisplayToImageCoordinate(), cropMaxDimen, CTRL_Pressed, ctrlClick(), currentDragMode, DRAW_LINE, DRAW_SELECTION, mouseActionByPosition(), mouseDragPoint, mousePressPoint, MOVE_BOTTOM_LEFT_CORNER, MOVE_BOTTOM_RIGHT_CORNER, MOVE_BOTTOM_SIDE, MOVE_LEFT_SIDE, MOVE_RIGHT_SIDE, MOVE_SELECTION, MOVE_TOP_LEFT_CORNER, MOVE_TOP_RIGHT_CORNER, MOVE_TOP_SIDE, selectionChanged(), and topLeft.

00437 {        
00438   //If CTRL pressed then emit ctrlClick event
00439   if( CTRL_Pressed) 
00440   {    
00441     emit ctrlClick();
00442     return;
00443   }
00444   
00445   //get mouse position in original image coordinates
00446   QPoint p = ConvertDisplayToImageCoordinate( e->pos() );
00447 
00448   //in draw line mode a mouse press has not immediate effect, 
00449   //mouse release is how a point is finally selected
00450   if( currentDragMode == DRAW_LINE )
00451   { return; }
00452   
00453   //construct topLeft and bottomRight points to make logic easier
00454   QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00455                   QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00456   QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00457                       QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
00458 
00459   //determine action mouse click will cause
00460   currentDragMode = mouseActionByPosition(e->pos());
00461 
00462   switch(currentDragMode)
00463   {
00464     case DRAW_SELECTION:
00465       mousePressPoint = p;
00466       mouseDragPoint = p;
00467       cropMaxDimen = -1.0;
00468       emit aspectRatioChanged();
00469       break;
00470     case MOVE_SELECTION:
00471       //nothing done until mouse moves
00472       break;
00473     case MOVE_TOP_LEFT_CORNER:
00474       mousePressPoint = bottomRight;
00475       mouseDragPoint = topLeft;
00476       break;
00477     case MOVE_BOTTOM_RIGHT_CORNER:
00478       mousePressPoint = topLeft;
00479       mouseDragPoint = bottomRight;
00480       break;
00481     case MOVE_TOP_RIGHT_CORNER:
00482       mousePressPoint = QPoint( topLeft.x(), bottomRight.y() );
00483       mouseDragPoint = QPoint( bottomRight.x(), topLeft.y() );
00484       break;
00485     case MOVE_BOTTOM_LEFT_CORNER:
00486       mousePressPoint = QPoint( bottomRight.x(), topLeft.y() );
00487       mouseDragPoint = QPoint( topLeft.x(), bottomRight.y() );
00488       break;
00489     case MOVE_LEFT_SIDE:
00490       mousePressPoint = bottomRight;
00491       mouseDragPoint  = topLeft;
00492       break;
00493     case MOVE_RIGHT_SIDE:
00494       mousePressPoint = topLeft;
00495       mouseDragPoint  = bottomRight;
00496       break;
00497     case MOVE_TOP_SIDE:
00498       mousePressPoint = bottomRight;
00499       mouseDragPoint  = topLeft;
00500       break;
00501     case MOVE_BOTTOM_SIDE:
00502       mousePressPoint = topLeft;
00503       mouseDragPoint  = bottomRight;
00504       break;
00505     //no effect
00506     default:
00507       return;
00508   }
00509   
00510   //repaint the selection  
00511   repaint(false);
00512   emit selectionChanged();
00513 }

void SelectionInterface::mouseReleaseEvent ( QMouseEvent *  e  )  [protected]

Definition at line 824 of file selectionInterface.cpp.

References bottomRight, cachedMousePosition, ConvertDisplayToImageCoordinate(), ConvertImageToDisplayCoordinate(), currentDragMode, DRAW_LINE, lineSelected(), MINIMUM_SELECTION_SIZE, mouseDragPoint, mousePressPoint, NO_EFFECT, selectNone(), topLeft, and updateCursorShape().

00825 {
00826   //if in draw line mode
00827   if( currentDragMode == DRAW_LINE )
00828   {
00829     //get mouse location in image space
00830     QPoint p = ConvertDisplayToImageCoordinate( e->pos() );
00831 
00832     //if first point has not been set set it now
00833     if( mousePressPoint.x() == -1 )
00834     {
00835       mousePressPoint = p;
00836       repaint(false);
00837     }
00838     //else first point has been set then we're setting the 2nd point, emit the selected line
00839     else
00840     {
00841       //get two points on line
00842       QPoint p1 = mousePressPoint;
00843       QPoint p2 = p;
00844       
00845       //reset mode, press and drag points so there is no selection
00846       currentDragMode = NO_EFFECT;
00847       selectNone();
00848       updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
00849       
00850       //emit the selected line
00851       emit lineSelected( p1, p2 );       
00852     }
00853     return; 
00854   }
00855   
00856   //disable move moving from having an effect on the selection
00857   currentDragMode = NO_EFFECT;
00858   
00859   //construct topLeft and bottomRight points to make logic easier
00860   QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00861                   QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00862   QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00863                       QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
00864 
00865   //convert selection region to display space to check for tiny selections to ignore
00866   topLeft = ConvertImageToDisplayCoordinate( topLeft );
00867   bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
00868   
00869   //if selection is very small reset to select nothing
00870   if( bottomRight.x() - topLeft.x() + 1 < MINIMUM_SELECTION_SIZE ||
00871       bottomRight.y() - topLeft.y() + 1 < MINIMUM_SELECTION_SIZE ) { selectNone(); }  
00872 }

void SelectionInterface::paintEvent ( QPaintEvent *  e  )  [protected]

Definition at line 161 of file selectionInterface.cpp.

References bottomRight, buffer, ConvertImageToDisplayCoordinate(), cropMaxDimen, currentDragMode, DRAW_LINE, height, mouseDragPoint, mousePressPoint, NO_EFFECT, scaledImage, TEXT_MARGIN, topLeft, unselectedScaledImage, and width.

00162 {  
00163     //if no scaled image just return
00164   if(scaledImage.isNull()) { return; }
00165     
00166   //create buffer to draw in
00167   QRect rct = rect();
00168   rct.moveBy(-x(), -y());
00169   QPixmap buffer( size() );
00170   
00171   //create a painter pointing to the buffer
00172   QPainter bufferPainter( &buffer );
00173 
00174   //turn off clipping to make painting operations faster
00175   bufferPainter.setClipping(false);
00176   
00177   //initialize buffer with background brush
00178   bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
00179   
00180   //paint the image
00181   int xOffset = (width() - scaledImage.width()) / 2;
00182   int yOffset = (height() - scaledImage.height()) / 2;
00183 
00184   //if in draw line mode paint the image normall and then the currently selected line
00185   //if the two points are set
00186   if(currentDragMode == DRAW_LINE)
00187   {
00188     //paint entire image normally
00189     bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );       
00190 
00191     //if the first and 2nd points have been set draw the line as well
00192     if( mousePressPoint.x() != -1 &&
00193         mouseDragPoint.x() != -1 )
00194     {
00195       //get points in display space
00196       QPoint p1, p2;
00197       p1 = ConvertImageToDisplayCoordinate( mousePressPoint );
00198       p2 = ConvertImageToDisplayCoordinate( mouseDragPoint  );
00199 
00200       //setup painter to use green color
00201       QPen pen;
00202       pen.setStyle( Qt::SolidLine );
00203       pen.setCapStyle( Qt::RoundCap );
00204       pen.setWidth( 2 );
00205       pen.setColor( green );
00206       bufferPainter.setPen( pen);
00207       
00208       //draw line
00209       bufferPainter.drawLine( p1.x(), p1.y(), p2.x(), p2.y() );
00210     }
00211   }
00212   //else we're in normal selection mode
00213   else
00214   {  
00215     //if selected region is empty paint entire image in color
00216     if( mousePressPoint.x() == -1 ||
00217         (
00218          currentDragMode == NO_EFFECT &&
00219          (
00220           mousePressPoint.x() - mouseDragPoint.x() == 0 ||
00221           mousePressPoint.y() - mouseDragPoint.y() == 0 
00222           )
00223          ))
00224     {
00225       bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );       
00226     }
00227     //otherwise paint using a two-pass approach,
00228     //first in monochrome and then the selected region in color
00229     else
00230     {
00231       //first paint using unselected coloring
00232       bufferPainter.drawImage( QPoint(xOffset, yOffset), unselectedScaledImage );
00233       
00234       //construct topLeft and bottomRight points to make logic easier
00235       QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00236                       QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00237       QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00238                           QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
00239       
00240       //convert coordinates from original image space to display space
00241       topLeft = ConvertImageToDisplayCoordinate( topLeft );
00242       bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
00243       
00244       //now paint selected region in color
00245       bufferPainter.drawImage( topLeft.x(), 
00246                                topLeft.y(),
00247                                scaledImage,
00248                                topLeft.x()-xOffset, topLeft.y()-yOffset,
00249                                bottomRight.x() - topLeft.x(),
00250                                bottomRight.y() - topLeft.y() );                                   
00251       
00252       //determine color for painting selection rectangle and dimensions
00253       //use gray/white if cropping to a custom size (and thus real world dimensions
00254       //are not known). If the crop size is known (eg 5"x7") use green if above
00255       //resolution is great enough, otherwise use red to indicate that cropping to
00256       //the specified size will result in pixelation during printing
00257       QPen pen;
00258       QColor selectionColor = gray;
00259       QColor textColor = white;
00260       int selectedWidth = QABS( mouseDragPoint.x() - mousePressPoint.x() ) + 1;
00261       int selectedHeight = QABS( mouseDragPoint.y() - mousePressPoint.y() ) + 1;
00262       if(selectedWidth == 1) selectedWidth = 0;
00263       if(selectedHeight == 1) selectedHeight = 0;
00264       
00265       int DPI = -1;
00266       int minDPI = -1;
00267       if( cropMaxDimen != -1.0 )
00268       {
00269         //compute DPI that will be used in dominant direction
00270         int maxDimen = QMAX( selectedWidth, selectedHeight );
00271         DPI = (int) (maxDimen / cropMaxDimen);          
00272         
00273         //if DPI is below minimum use red color for selection rectangle to indicate pixalation may occur
00274         minDPI = ((Window*)qApp->mainWidget())->getConfig()->getInt( "misc", "minDPI" );      
00275         if( DPI < minDPI ) 
00276         { selectionColor = QColor( 200, 0, 0 ); }
00277         //otherwise use green to signal cropping to this size is safe
00278         else { selectionColor = QColor( 0, 200, 0 ); }
00279       } 
00280       pen.setStyle( Qt::SolidLine );
00281       pen.setWidth( 2 );
00282       bufferPainter.setPen( pen);
00283       
00284       //paint selection size in lower right corner of selected area
00285       QString selectionText;
00286       if( cropMaxDimen != -1.0 &&
00287           DPI < minDPI )
00288         selectionText = QString("%1 x %2 (DPI: %3!)").arg(selectedWidth).arg(selectedHeight).arg(DPI);
00289       else
00290         selectionText = QString("%1 x %2").arg(selectedWidth).arg(selectedHeight);
00291       
00292       QFontMetrics fm( this->font() );
00293       int stringWidth = fm.width(selectionText);
00294       int stringHeight = fm.ascent();
00295       
00296       int textX = 0;
00297       int textY = 0;
00298       const int TEXT_MARGIN = 4;
00299       if( mouseDragPoint.x() > mousePressPoint.x() )
00300       { 
00301         textX = QMIN( xOffset + unselectedScaledImage.width() - TEXT_MARGIN - stringWidth,
00302                       bottomRight.x() + TEXT_MARGIN ); 
00303       }
00304       else
00305       { 
00306         textX = QMAX( xOffset + TEXT_MARGIN, 
00307                       topLeft.x() - TEXT_MARGIN - stringWidth ); 
00308       }
00309       
00310       if( mouseDragPoint.y() > mousePressPoint.y() )
00311       { 
00312         textY = QMIN( yOffset + unselectedScaledImage.height() - TEXT_MARGIN,
00313                       bottomRight.y() + TEXT_MARGIN + stringHeight); 
00314       }
00315       else
00316       { 
00317         textY = QMAX( yOffset + TEXT_MARGIN + stringHeight, 
00318                       topLeft.y() - TEXT_MARGIN ); 
00319       }
00320       
00321       //paint a thin outline around the selection
00322       pen.setColor( selectionColor );
00323       bufferPainter.setPen( pen);
00324       QRect selection( topLeft, bottomRight );
00325       bufferPainter.drawRect(selection);       
00326       
00327       //paint image under selected dimension using selected coloring to help make it more visible
00328       bufferPainter.drawImage( textX, textY-stringHeight,
00329                                unselectedScaledImage,
00330                                textX - xOffset, textY-stringHeight-yOffset,
00331                                stringWidth, fm.height() );
00332       
00333       
00334       //paint selected dimensions    
00335       pen.setColor( textColor );
00336       bufferPainter.setPen( pen);
00337       bufferPainter.drawText( textX, textY, selectionText );
00338     }        
00339   }
00340   
00341   bufferPainter.end();
00342   
00343   //blit buffer to screen
00344   bitBlt( this,
00345           e->rect().x(), e->rect().y(),
00346           &buffer, 
00347           e->rect().x(), e->rect().y(),
00348           e->rect().width(), e->rect().height() );
00349 }

void SelectionInterface::resizeEvent ( QResizeEvent *   )  [protected]

Definition at line 108 of file selectionInterface.cpp.

References constructDisplayImages(), and fullScreenImage.

00109 {  
00110   //if image has yet to be set return
00111   if( fullScreenImage.isNull() ) return;
00112   
00113   //construct new images for painting
00114   constructDisplayImages();
00115 }

bool SelectionInterface::scaleSelection ( int  delta  )  [private]

increase/decrease selection while maintaining aspect ratio by changing selected width by delta

Definition at line 565 of file selectionInterface.cpp.

References bottomRight, cachedSelctionCenter, cachedSelectionSize, mouseDragPoint, mousePressPoint, origImageSize, and topLeft.

Referenced by keyPressEvent(), and mouseMoveEvent().

00566 {
00567   //construct topLeft and bottomRight points to make logic easier
00568   QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
00569                   QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
00570   QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
00571                       QMAX(mousePressPoint.y(), mouseDragPoint.y()) );     
00572 
00573   //compute new selection dimension
00574   int curSelectionWidth = bottomRight.x() - topLeft.x() + 1;
00575   int curSelectionHeight = bottomRight.y()- topLeft.y() + 1;      
00576   int newSelectionWidth = -1; 
00577   int newSelectionHeight = -1;      
00578 
00579   //adjust in dimension of greater resolution
00580   if( curSelectionWidth > curSelectionHeight )
00581   {
00582     newSelectionWidth = QMIN( curSelectionWidth + delta, origImageSize.width() );
00583     newSelectionHeight = (newSelectionWidth * cachedSelectionSize.height()) / cachedSelectionSize.width();
00584   }
00585   else
00586   {
00587     newSelectionHeight = QMIN( curSelectionHeight + delta, origImageSize.height() );
00588     newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();    
00589   }
00590   
00591   //if selection width or height already maxed out then ignore attempt to make selection bigger
00592   if(delta > 0 &&
00593      ( curSelectionWidth == origImageSize.width() ||
00594        curSelectionHeight == origImageSize.height() ) ) 
00595   { 
00596     return false;
00597   }  
00598   
00599   //again prevent from growing too big, now along y-axis
00600   if(newSelectionHeight > origImageSize.height())
00601   {
00602     newSelectionHeight = origImageSize.height();
00603     newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();
00604   }        
00605   
00606   //prevent selection becoming empty
00607   if(newSelectionWidth <= 0 || newSelectionHeight <= 0)
00608   {
00609     newSelectionWidth = curSelectionWidth;
00610     newSelectionHeight = curSelectionHeight;
00611   }
00612   
00613   //center new selection over current selection , move if necessary
00614   topLeft = QPoint(QMAX( cachedSelctionCenter.x() - newSelectionWidth/2, 0 ),
00615                    QMAX( cachedSelctionCenter.y() - newSelectionHeight/2, 0 ));
00616   bottomRight = QPoint( topLeft.x() + newSelectionWidth - 1,
00617                         topLeft.y() + newSelectionHeight - 1 );   
00618   
00619   //too far right
00620   if(bottomRight.x() > origImageSize.width() - 1 )
00621   {
00622     int diff = bottomRight.x() - (origImageSize.width() - 1);        
00623     topLeft.setX( topLeft.x() - diff );
00624     bottomRight.setX( bottomRight.x() - diff );
00625 
00626     //recompute center
00627     cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00628                                    ( mouseDragPoint.y() + mousePressPoint.y() )/2 );          
00629   }                     
00630   
00631   //too far down
00632   if(bottomRight.y() > origImageSize.height() - 1 )
00633   {
00634     int diff = bottomRight.y() - (origImageSize.height() - 1);        
00635     topLeft.setY( topLeft.y() - diff );
00636     bottomRight.setY( bottomRight.y() - diff );
00637     
00638     //recompute center
00639     cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00640                                    ( mouseDragPoint.y() + mousePressPoint.y() )/2 );      
00641   }                     
00642   
00643   //set new selection
00644   mousePressPoint = topLeft;
00645   mouseDragPoint = bottomRight;  
00646   
00647   //success
00648   return true;  
00649 }

void SelectionInterface::selectAll (  )  [slot]

selects all of the image

Definition at line 946 of file selectionInterface.cpp.

References aspectRatioChanged(), cachedSelctionCenter, cachedSelectionSize, cropMaxDimen, mouseDragPoint, mousePressPoint, origImageSize, and selectionChanged().

Referenced by SelectionInterface().

00947 {
00948   mousePressPoint.setX( 0 );
00949   mousePressPoint.setY( 0 );
00950   mouseDragPoint.setX( origImageSize.width() - 1 );
00951   mouseDragPoint.setY( origImageSize.height() - 1);
00952 
00953   //cache selection size and center, necessary for computing next size
00954   cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
00955                                QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);           
00956   cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00957                                  ( mouseDragPoint.y() + mousePressPoint.y() )/2 );      
00958   
00959   cropMaxDimen = -1.0;
00960   repaint(false);
00961   emit selectionChanged();
00962   emit aspectRatioChanged();
00963 }

void SelectionInterface::selectionChanged (  )  [signal]

emitted when the user changed the selected region

Referenced by keyPressEvent(), mouseMoveEvent(), mousePressEvent(), selectAll(), selectNone(), setPhoto(), and setSelection().

bool SelectionInterface::selectionEmpty (  ) 

returns true if selection is empty

Definition at line 937 of file selectionInterface.cpp.

References mouseDragPoint, and mousePressPoint.

Referenced by keyPressEvent().

00938 {
00939   return (
00940           mousePressPoint.x() == -1 ||
00941           mouseDragPoint.x() - mousePressPoint.x() == 0 ||
00942           mouseDragPoint.y() - mousePressPoint.y() == 0
00943          );  
00944 }

void SelectionInterface::selectNone (  )  [slot]

selects none of the image

Definition at line 965 of file selectionInterface.cpp.

References aspectRatioChanged(), cropMaxDimen, mouseDragPoint, mousePressPoint, and selectionChanged().

Referenced by EditingInterface::applyImageUpdate(), keyPressEvent(), mouseReleaseEvent(), and SelectionInterface().

00966 {
00967   mousePressPoint = QPoint(-1,-1);
00968   mouseDragPoint = QPoint(-1,-1);
00969   cropMaxDimen = -1.0;
00970   repaint(false);
00971   emit selectionChanged();
00972   emit aspectRatioChanged();
00973 }

void SelectionInterface::setPhoto ( QString  imageFilename,
bool  resetSelection = true 
)

Updates displayed photo.

Definition at line 75 of file selectionInterface.cpp.

References constructDisplayImages(), cropMaxDimen, CTRL_Pressed, fullScreenImage, getImageSize(), mouseDragPoint, mousePressPoint, origImageFilename, origImageSize, scaleImage(), selectionChanged(), and SHIFT_Pressed.

Referenced by EditingInterface::applyImageUpdate(), EditingInterface::revertCurrentPhoto(), EditingInterface::rotateFlip(), EditingInterface::setPhoto(), and EditingInterface::showNextPrevFirstLastPhoto().

00076 {  
00077   //store original image filename
00078   origImageFilename = imageFilename;
00079 
00080   //store original image dimensions
00081   getImageSize( origImageFilename, origImageSize );
00082     
00083   //resize image to current screen size for faster
00084   //scaling during resize events
00085   QRect screenSize = qApp->desktop()->availableGeometry();
00086   scaleImage( origImageFilename, fullScreenImage, screenSize.width(), screenSize.height() );
00087 
00088   //construct display images  
00089   constructDisplayImages();
00090   
00091   //reset selection area to nothing
00092   if(resetSelection)
00093   {
00094     mousePressPoint = QPoint(-1,-1);
00095     mouseDragPoint  = QPoint(-1,-1);
00096     cropMaxDimen = -1.0;
00097     SHIFT_Pressed = false;
00098     CTRL_Pressed = false;
00099     emit selectionChanged();
00100   }
00101 
00102   //repaint widget
00103   //if we are resetting the selection then aspect ratio may have changed
00104   //so a full repaint (with erase) is necessary
00105   repaint(resetSelection);
00106 }

void SelectionInterface::setSelection ( QPoint  topLeft,
QPoint  bottomRight,
double  cropMaxDimen = -1.0 
)

Sets the current selection cropMaxDimen specifies the idealized dimension in dominant direction in inches (eg 7").

Definition at line 975 of file selectionInterface.cpp.

References cachedSelctionCenter, cachedSelectionSize, mouseDragPoint, mousePressPoint, and selectionChanged().

Referenced by EditingInterface::rotateSelection(), EditingInterface::selectAspectRatio(), and EditingInterface::showNextPrevFirstLastPhoto().

00977 {
00978   mousePressPoint = topLeft;
00979   mouseDragPoint = bottomRight;
00980   
00981   this->cropMaxDimen = cropMaxDimen;
00982   
00983   //cache selection size and center, necessary for computing next size
00984   cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
00985                                QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);           
00986   cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
00987                                  ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
00988   
00989   repaint(false);
00990   emit selectionChanged();
00991 }

QSize SelectionInterface::sizeHint (  )  [protected]

void SelectionInterface::updateCursorShape ( QPoint  p  )  [private]

update mouse cursor based on position over widget and selected region

Definition at line 515 of file selectionInterface.cpp.

References CROSS_CURSOR, CTRL_Pressed, currentDragMode, currentMouseShape, DRAW_LINE, DRAW_SELECTION, getCursor(), mouseActionByPosition(), MOVE_BOTTOM_LEFT_CORNER, MOVE_BOTTOM_RIGHT_CORNER, MOVE_BOTTOM_SIDE, MOVE_HOR_CURSOR, MOVE_LEFT_SIDE, MOVE_RIGHT_SIDE, MOVE_SELECTION, MOVE_SELECTION_CURSOR, MOVE_TL_CURSOR, MOVE_TOP_LEFT_CORNER, MOVE_TOP_RIGHT_CORNER, MOVE_TOP_SIDE, MOVE_TR_CURSOR, MOVE_VERT_CURSOR, ROTATE_CURSOR, SCALE_SELECTION_CURSOR, SHIFT_Pressed, and TARGET_CURSOR.

Referenced by enterDrawLineMode(), keyPressEvent(), keyReleaseEvent(), mouseMoveEvent(), and mouseReleaseEvent().

00516 {  
00517   //if resizing a selection always use size all cursor
00518   if(SHIFT_Pressed) 
00519   { 
00520     setCursor( getCursor(SCALE_SELECTION_CURSOR) );
00521     return;
00522   }
00523   
00524   //if ctrl pressed show rotate selection cursor  
00525   if(CTRL_Pressed) 
00526   { 
00527     setCursor( getCursor(ROTATE_CURSOR) );
00528     return;
00529   }
00530    
00531   //if selecting a line the cursor is always the same
00532   if( currentDragMode == DRAW_LINE )
00533   {
00534     setCursor( getCursor(TARGET_CURSOR) );
00535     return;
00536   }
00537   
00538   //update mouse cursor based on coordinates
00539   currentMouseShape = mouseActionByPosition( rawP ); 
00540   switch(currentMouseShape)
00541   {
00542     case DRAW_SELECTION:
00543       setCursor( getCursor(CROSS_CURSOR) ); break;
00544     case MOVE_SELECTION:
00545       setCursor( getCursor(MOVE_SELECTION_CURSOR) ); break;
00546     case MOVE_TOP_LEFT_CORNER:
00547     case MOVE_BOTTOM_RIGHT_CORNER:
00548       setCursor( getCursor(MOVE_TL_CURSOR) ); break;
00549     case MOVE_TOP_RIGHT_CORNER:
00550     case MOVE_BOTTOM_LEFT_CORNER:
00551       setCursor( getCursor(MOVE_TR_CURSOR) ); break;
00552     case MOVE_LEFT_SIDE:
00553     case MOVE_RIGHT_SIDE:
00554       setCursor( getCursor(MOVE_HOR_CURSOR) ); break;
00555     case MOVE_TOP_SIDE:
00556     case MOVE_BOTTOM_SIDE:
00557       setCursor( getCursor(MOVE_VERT_CURSOR) ); break;
00558       break;
00559     default:
00560       setCursor( Qt::ArrowCursor );
00561       break;
00562   }  
00563 }


Member Data Documentation

cached mouse position, used to scale or drag around selection area

Definition at line 146 of file selectionInterface.h.

Referenced by enterDrawLineMode(), keyPressEvent(), keyReleaseEvent(), mouseMoveEvent(), mouseReleaseEvent(), and SelectionInterface().

cache the aspect ratio when pressing the control buttion, this helps aleviate numerical error that builds up when scaling up and down selections

Definition at line 169 of file selectionInterface.h.

Referenced by keyPressEvent(), mouseMoveEvent(), scaleSelection(), selectAll(), and setSelection().

Definition at line 170 of file selectionInterface.h.

Referenced by mouseMoveEvent(), scaleSelection(), selectAll(), and setSelection().

Current crop max dimension (in inches).

Definition at line 173 of file selectionInterface.h.

Referenced by mouseMoveEvent(), mousePressEvent(), paintEvent(), selectAll(), SelectionInterface(), selectNone(), and setPhoto().

state of CTRL button, effects if mouse clicks rotate current selection

Definition at line 165 of file selectionInterface.h.

Referenced by enterDrawLineMode(), keyPressEvent(), keyReleaseEvent(), mouseMoveEvent(), mousePressEvent(), setPhoto(), and updateCursorShape().

method of dragging out, either new selection or resizing selection corner or side

Definition at line 149 of file selectionInterface.h.

Referenced by enterDrawLineMode(), keyPressEvent(), mouseMoveEvent(), mousePressEvent(), mouseReleaseEvent(), paintEvent(), SelectionInterface(), and updateCursorShape().

current mouse shape.

by caching this value we avoid resetting the mouse cursor every time it moves etc.

Definition at line 153 of file selectionInterface.h.

Referenced by mouseMoveEvent(), SelectionInterface(), and updateCursorShape().

Full screen version of image.

Definition at line 131 of file selectionInterface.h.

Referenced by constructDisplayImages(), resizeEvent(), and setPhoto().

original image filename

Definition at line 156 of file selectionInterface.h.

Referenced by setPhoto().

state of SHIFT button, effects if mouse drags adjust or scale the current selection

Definition at line 162 of file selectionInterface.h.

Referenced by enterDrawLineMode(), keyPressEvent(), keyReleaseEvent(), mouseActionByPosition(), mouseMoveEvent(), setPhoto(), and updateCursorShape().

Grayscale version of scaled image, used for drawing non-selected regions.

Definition at line 137 of file selectionInterface.h.

Referenced by constructDisplayImages(), and paintEvent().


The documentation for this class was generated from the following files:

Generated on Sun Aug 23 02:34:38 2009 for AlbumShaper by  doxygen 1.5.9