AlbumShaper  1.0a3
Public Slots | Signals | Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes
SelectionInterface Class Reference

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

#include <selectionInterface.h>

Inheritance diagram for SelectionInterface:
Inheritance graph
[legend]
Collaboration diagram for SelectionInterface:
Collaboration graph
[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().

                                                                         : QWidget(parent,name)
{ 
  //avoid flicker when repainting
  setWFlags(WRepaintNoErase);

  //set default selection off screen
  mousePressPoint = QPoint(-1,-1);
  mouseDragPoint = QPoint(-1,-1);
  
  //by default mouse movement does not effect the current selection
  currentDragMode = NO_EFFECT;
  currentMouseShape = NO_EFFECT;
    
  QAccel *keyAccel = new QAccel( this );
  keyAccel->connectItem( keyAccel->insertItem( CTRL + Key_A),
                         this, SLOT(selectAll()) );
  keyAccel->connectItem( keyAccel->insertItem( CTRL + SHIFT + Key_A ),
                         this, SLOT(selectNone()) );
  
  //watch mouse movements in order to change mouse cursor
  setMouseTracking(true);

  //accept focus when clicked on
  setFocusPolicy( QWidget::ClickFocus );
  
  //initialize cached mouse position to be offscreen by default
  cachedMousePosition = QPoint(-1,-1);  

  //no crop size by default
  cropMaxDimen = -1.0;
}
SelectionInterface::~SelectionInterface ( )

Deletes objects.

Definition at line 73 of file selectionInterface.cpp.

{ }

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().

{  
  //rescale image to fit on screen
  scaledImage = fullScreenImage.scale( width(), height(), QImage::ScaleMin );     
  
  //construct an unselected scaled image
  unselectedScaledImage = scaledImage.copy();  
  int x, y;
  QRgb* rgb;
  uchar* scanLine;
  for( y=0; y<unselectedScaledImage.height(); y++)
  {   
    //iterate over each selected pixel in scanline
    scanLine = unselectedScaledImage.scanLine(y);
    for( x=0; x<unselectedScaledImage.width(); x++)
    {
      //compress dynamic range to 25% of original
      rgb = ((QRgb*)scanLine+x);
      
      double r = ((double)qRed(*rgb)   )/255.0;
      double g = ((double)qGreen(*rgb) )/255.0;
      double b = ((double)qBlue(*rgb)  )/255.0;
      
      //convert to hsv
      double h,s,v;
      RGBtoHSV(r,g,b,&h,&s,&v);
      
      //scale and clamp v
      v*=0.25;
      
      //convert adjusted color back to rgb colorspace and clamp
      HSVtoRGB( &r,&g,&b, h,s,v);         
      int rp = (int) QMIN( QMAX((r*255), 0), 255 );
      int gp = (int) QMIN( QMAX((g*255), 0), 255 );
      int bp = (int) QMIN( QMAX((b*255), 0), 255 );
      
      //set adjusted color value
      *rgb = qRgb(rp,gp,bp);          
    }
  }  
  
  
}
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().

{  
  QPoint newPoint = p;
  
  //remove display offset
  int xOffset = (width() - scaledImage.width()   ) / 2;
  int yOffset = (height() - scaledImage.height() ) / 2;  
  newPoint.setX( newPoint.x() - xOffset );
  newPoint.setY( newPoint.y() - yOffset );
  
  //if coordinate is at max set new value explicitly to avoid roundoff error,
  //otherwise scale to full image dimensions
  if(newPoint.x() == scaledImage.width() - 1)
    newPoint.setX( origImageSize.width() - 1);
  else 
    newPoint.setX( (int) (0.5 + ((double)(newPoint.x() * (origImageSize.width()-1))) / (scaledImage.width()-1) ) );
  
  if(newPoint.y() == scaledImage.height() - 1)
    newPoint.setY( origImageSize.height() - 1);
  else 
    newPoint.setY( (int) (0.5 + ((double)(newPoint.y() * (origImageSize.height()-1))) / (scaledImage.height()-1) ) );
  
  //return point in image coordinates
  return newPoint;
}
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().

{       
  QPoint newPoint = p;
  
  //if coordinate is at max set new value explicitly to avoid roundoff error,
  //otherwise scale to full image dimensions
  if(newPoint.x() == origImageSize.width() - 1)
    newPoint.setX( scaledImage.width() - 1);
  else 
    newPoint.setX( (newPoint.x() * (scaledImage.width()-1)) / (origImageSize.width()-1) );
  
  if(newPoint.y() == origImageSize.height() - 1)
    newPoint.setY( scaledImage.height() - 1);
  else 
    newPoint.setY( (newPoint.y() * (scaledImage.height()-1)) / (origImageSize.height()-1) );
  
  //add display offset
  int xOffset = (width() - scaledImage.width()   ) / 2;
  int yOffset = (height() - scaledImage.height() ) / 2;  
  newPoint.setX( newPoint.x() + xOffset );
  newPoint.setY( newPoint.y() + yOffset );
    
  //return point in image coordinates
  return newPoint;
}
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().

{    
  int xOffset = (width() - scaledImage.width()   ) / 2;
  int yOffset = (height() - scaledImage.height() ) / 2;

  QPoint croppedPoint;
  croppedPoint.setX( QMIN( QMAX(xOffset, p.x()), xOffset + scaledImage.width() - 1 ) );
  croppedPoint.setY( QMIN( QMAX(yOffset, p.y()), yOffset + scaledImage.height() - 1 ) );
  return croppedPoint;
}
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().

{
  //set the current mode
  currentDragMode = DRAW_LINE;

  //during draw line mode ignore control and shift keys, they are only useful for adjusting
  //selections, not lines
  SHIFT_Pressed = false;
  CTRL_Pressed = false;
  
  //reset 1st point
  mousePressPoint = QPoint( -1, -1 );
  mouseDragPoint = QPoint( -1, -1 );
  
  //repaint and reset the mouse cursor
  updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
  repaint(false);
}
void SelectionInterface::getDisplaySize ( int &  width,
int &  height 
)
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().

{
  //if none selected just return immediately
  if(mousePressPoint.x() == -1)
  {
    topLeft.setX(-1); topLeft.setY(-1);
    bottomRight.setX(-1); bottomRight.setY(-1);
    return;
  }

  //set coordinates based on raw selection  
  topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) );
  topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) );                
  bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) );                  
}
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().

{
  //if currently drawing a line, allow the user
  //to escape the current acction by hiting escape, all other
  //key presses are ignored
  if( currentDragMode == DRAW_LINE )
  {
    if(e->key() == Qt::Key_Escape )
    {
      //reset mode, press and drag points so there is no selection, and mouse cursor
      currentDragMode = NO_EFFECT;
      selectNone();
      updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
    
      //emit an invalid line
      emit lineSelected( QPoint(-1,-1), QPoint(-1,-1) );       
    }

    return; 
  }
  
  //if user pressed SHIFT button and selection non-empty 
  //then note state change, 
  //this will effect resizing selections during drag events
  if(e->key() == Qt::Key_Shift && !selectionEmpty() )
  {    
    SHIFT_Pressed = true;
    updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
    return;
  }

  //if user pressed CTRL button and selection non-empty 
  //then note state change, 
  //this will effect mouse clicks by rotating the current selection
  if(e->key() == Qt::Key_Control && !selectionEmpty() && !SHIFT_Pressed )
  {    
    CTRL_Pressed = true;
    updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
    return;
  }
    
  //ignore keypress if selection is empty
  if(mousePressPoint.x() == -1 ||
     mousePressPoint.x() - mouseDragPoint.x() == 0 ||
     mousePressPoint.y()  - mouseDragPoint.y() == 0)
  {
    e->ignore();
    return;
  }

  //ignore keypresses while mouse button is down since
  //intended behavious is unclear
  if( currentDragMode != NO_EFFECT )
  {
    e->ignore();
    return;
  }
  
  //-------  
  //if += / -_ keys are pressed scale selection
  if( e->key() == Qt::Key_Plus ||
      e->key() == Qt::Key_Equal ||
      e->key() == Qt::Key_Minus ||
      e->key() == Qt::Key_Underscore )
  {
    int delta = 2*QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
    
    delta = 1;
    
    //negate delta if decreasing size
    if( e->key() == Qt::Key_Minus ||
        e->key() == Qt::Key_Underscore )
      delta = -delta;
    
    if( scaleSelection( delta ) )
    {    
      //repaint the selection
      repaint(false);
      emit selectionChanged();
    }
    return;
  }
  //-------  
  
  //find topleft and bottom right of current selection
  QPoint topLeft, bottomRight;
  topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) );
  topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) );                
  bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) );                  
  
  //compute the number of pixels in the image correspond to one display pixel
  //this is the unit by which the selection will be moved
  int moveBy = 0;
  if( e->key() == Qt::Key_Left ||
      e->key() == Qt::Key_Right )
  {
    moveBy = QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
  }
  else
  {
    moveBy = QMAX( origImageSize.height(), scaledImage.height() ) / scaledImage.height();
  }
  
  //boundary checked moved by value. must be decalred outside switch statement below
  int dx = 0;
  int dy = 0;
  switch( e->key() )
  {
    case Qt::Key_Left:
      dx = QMAX( topLeft.x() - moveBy, 0) - topLeft.x();
      break;
    case Qt::Key_Right:
      dx = QMIN( bottomRight.x() + moveBy, origImageSize.width() - 1) - bottomRight.x();
      break;
    case Qt::Key_Up:
      dy = QMAX( topLeft.y() - moveBy, 0) - topLeft.y();
      break;
    case Qt::Key_Down:
      dy = QMIN( bottomRight.y() + moveBy, origImageSize.height() - 1) - bottomRight.y();
      break;
    default:
      e->ignore();
      return;
  }
  
  //shift by dx
  mousePressPoint.setX( mousePressPoint.x() + dx );
  mouseDragPoint.setX( mouseDragPoint.x() + dx );      
 
  //shift by dy
  mousePressPoint.setY( mousePressPoint.y() + dy );
  mouseDragPoint.setY( mouseDragPoint.y() + dy );      

  //recompute center
  cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
  
  //only bother with repaint and updating cursor shape if shift actually occured
  if(dx != 0 || dy != 0) 
  { 
    repaint(false);
    updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );  
  }
}
void SelectionInterface::keyReleaseEvent ( QKeyEvent *  e) [protected]

Definition at line 1162 of file selectionInterface.cpp.

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

{
  //if user released SHIFT button then note state change, 
  //this will effect resizing selections during drag events
  if(e->key() == Qt::Key_Shift)
  {
    SHIFT_Pressed = false;
    updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
  }
  //if user released CTRL button then note state change, 
  //this will effect mouse clicks
  else  if(e->key() == Qt::Key_Control)
  {
    CTRL_Pressed = false;
    updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
  }
  //unhandled key press: pass up the object tree
  else { e->ignore(); }
}
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().

{   
  //If SHIFT_Pressed is set then scaling a selection
  if(SHIFT_Pressed) { return SCALE_SELECTION; }
  
  //construct topLeft and bottomRight points to make logic easier
  QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                  QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                      QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
   
  //convert selelection bounary to display space since thresholds are all in display space
  topLeft = ConvertImageToDisplayCoordinate( topLeft );
  bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
    
  //compute selection center
  QPoint center( (topLeft.x() + bottomRight.x()) / 2,
                 (topLeft.y() + bottomRight.y()) / 2);
  
  //if pointer is not over image no effect will occur when clicking
  int xOffset = (width() - scaledImage.width()   ) / 2;
  int yOffset = (height() - scaledImage.height() ) / 2;  
  if(p.x() < xOffset || p.x() >= scaledImage.width() + xOffset ||
     p.y() < yOffset || p.y() >= scaledImage.height() + yOffset )
  { return NO_EFFECT; }
    
  //if either there is no selection or the entire image is selected, new
  //mouse clicks are interpreted as being for selecting new regions
  if( mousePressPoint.x() == -1 ||
      ( bottomRight.x() - topLeft.x() == origImageSize.width() - 1 &&
        bottomRight.y() - topLeft.y() == origImageSize.height() - 1 )
      )
  { return DRAW_SELECTION; }
  //move entire selection
  //mouse is within MOVE_THRESH of center and outside
  //DRAG_THRESH of any side
  else if( p.x() >= QMAX( center.x() - MOVE_THRESHOLD, topLeft.x() ) &&
           p.x() <= QMIN( center.x() + MOVE_THRESHOLD, bottomRight.x() ) &&
           p.y() >= QMAX( center.y() - MOVE_THRESHOLD, topLeft.y() ) &&
           p.y() <= QMIN( center.y() + MOVE_THRESHOLD, bottomRight.y() ) &&
           p.x() > topLeft.x() + DRAG_THRESHOLD &&
           p.x() < bottomRight.x() - DRAG_THRESHOLD &&
           p.y() > topLeft.y() + DRAG_THRESHOLD &&
           p.y() < bottomRight.y() - DRAG_THRESHOLD )
{ return MOVE_SELECTION; } 
  //drag top left
  else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
           QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD )  
  { return MOVE_TOP_LEFT_CORNER; }
  //drag top right    
  else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
           QABS(topLeft.y()     - p.y()) <= DRAG_THRESHOLD )  
  { return MOVE_TOP_RIGHT_CORNER; }
  //drag bottom left    
  else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
           QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )  
  { return MOVE_BOTTOM_LEFT_CORNER; }
  //drag bottom right
  else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
           QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )  
  { return MOVE_BOTTOM_RIGHT_CORNER; }
  //drag left
  else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
           p.y() >= topLeft.y() &&
           p.y() <= bottomRight.y() )
  { return MOVE_LEFT_SIDE; }
  //drag right
  else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
           p.y() >= topLeft.y() &&
           p.y() <= bottomRight.y() )
  { return MOVE_RIGHT_SIDE; }
  //drag top
  else if( QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD &&
           p.x() >= topLeft.x() &&
           p.x() <= bottomRight.x() )
  { return MOVE_TOP_SIDE; }
  //drag bottom
  else if( QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD &&
           p.x() >= topLeft.x() &&
           p.x() <= bottomRight.x() )
  { return MOVE_BOTTOM_SIDE; }
  //else new selection
  else { return DRAW_SELECTION; }
}
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().

{
  //if the SHIFT_Pressed state variable is true but SHIFT is now not pressed
  //reset bool and mouse cursor!
  if( SHIFT_Pressed && !(e->state() & Qt::ShiftButton) )
  {
    SHIFT_Pressed = false;
    updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) );   
  }
      
  //if the CTRL_Pressed state variable is true but CTRL is now not pressed
  //reset bool and mouse cursor!
  if( CTRL_Pressed && !(e->state() & Qt::ControlButton) )
  {
    CTRL_Pressed = false;
    updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) );   
  }  
  
  //if mouse not pressed update mouse cursor if 
  //mode will change if user presses mouse button
  if(currentDragMode == NO_EFFECT)
  {  
    //only update the mouse cursor shape if it will change
    if( mouseActionByPosition( e->pos() ) != currentMouseShape )
      updateCursorShape( e->pos() );
    
    cachedMousePosition = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );
  }
  //if currently in draw line mode update the selected line
  else if(currentDragMode == DRAW_LINE)
  {
    //if the 1st point hasn't been set yet do nothing
    if( mousePressPoint.x() == -1 )
      return;
    
    //1st point set, set 2nd point to current mouse position and redraw
    mouseDragPoint = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );

    //repaint the line
    repaint(false);
  }  
  //update selection rectangle or selected line
  else
  {     
    //get mouse position in original image coordinates
    QPoint p = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) );

    //construct topLeft and bottomRight points to make logic easier
    QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                    QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
    QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                        QMAX(mousePressPoint.y(), mouseDragPoint.y()) );     
    
    //if SHIFT pressed and both selction dimensions non-empty then scale selection
    if(SHIFT_Pressed && 
       bottomRight.x() > topLeft.x() && 
       bottomRight.y() > topLeft.y() )
    {
      //update width, prevent from growing beyond image boundaries
      int delta = p.x() - cachedMousePosition.x(); 
      if( !scaleSelection( delta ) )
      {
        //cache the current mouse position before returning without change
        cachedMousePosition = p;
        return;
      }
    }    
    //if draging the entire selection, update x and y coordinates for
    //both mousePress and mouseDrag points and update the dragSelectionPoint
    else if( currentDragMode == MOVE_SELECTION )
    {
      //compute offset
      QPoint offset( p.x() - cachedMousePosition.x(),
                     p.y() - cachedMousePosition.y() );
      
      //construct topLeft and bottomRight points to make logic easier
      QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                      QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
      QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                          QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
      
      //clip offset so selected area is always within image boundaries
      
      //left
      if(offset.x() < 0 && topLeft.x() + offset.x() < 0 )
        offset.setX( -topLeft.x() );
      
      //right
      if(offset.x() > 0 && bottomRight.x() + offset.x() >= origImageSize.width() )
        offset.setX( origImageSize.width() - 1 - bottomRight.x() );          
      
      //top
      if(offset.y() < 0 && topLeft.y() + offset.y() < 0 )
        offset.setY( -topLeft.y() );
      
      //bottom
      if(offset.y() > 0 && bottomRight.y() + offset.y() >= origImageSize.height() )
        offset.setY( origImageSize.height() - 1 - bottomRight.y() );            
      
      //update press and drag points
      mousePressPoint+= offset;
      mouseDragPoint+= offset;      
      
      //recompute selection center
      cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                     ( mouseDragPoint.y() + mousePressPoint.y() )/2 );          
    }        
    //if moving any corner or drawing the original selection, 
    //update x and y coords of drag point
    else if( currentDragMode == DRAW_SELECTION ||
             currentDragMode == MOVE_TOP_LEFT_CORNER ||
             currentDragMode == MOVE_TOP_RIGHT_CORNER ||
             currentDragMode == MOVE_BOTTOM_LEFT_CORNER ||
             currentDragMode == MOVE_BOTTOM_RIGHT_CORNER )
    {
      mouseDragPoint.setX( p.x() );
      mouseDragPoint.setY( p.y() );
      cropMaxDimen = -1.0;
      
      //cache selection size and center, necessary for computing next size
      cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
                                   QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
      cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                     ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
      
      
      emit aspectRatioChanged();
    }
    //else if moving the left or right sides just update the x coordinate of 
    //the drag point
    else if( currentDragMode == MOVE_LEFT_SIDE ||
             currentDragMode == MOVE_RIGHT_SIDE )
    {
      mouseDragPoint.setX( p.x() );
      cropMaxDimen = -1.0;
      emit aspectRatioChanged();
      
      //cache selection size and center, necessary for computing next size
      cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
                                   QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);                                               
      cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                     ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
    }
    //else if moving the top or bottom sides just update the x coordinate of 
    //the drag point
    else if( currentDragMode == MOVE_TOP_SIDE ||
             currentDragMode == MOVE_BOTTOM_SIDE )
    {
      mouseDragPoint.setY( p.y() );
      cropMaxDimen = -1.0;
      emit aspectRatioChanged();
      
      //cache selection size and center, necessary for computing next size
      cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
                                   QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);                                               
      cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                     ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
      
    }    
    
    //cache current mouse position
    cachedMousePosition = p;

    //repaint the selection
    repaint(false);
    emit selectionChanged();

    //only update the mouse cursor shape if it will change
    if( mouseActionByPosition( e->pos() ) != currentMouseShape )
      updateCursorShape( e->pos() );
  }
}
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.

{        
  //If CTRL pressed then emit ctrlClick event
  if( CTRL_Pressed) 
  {    
    emit ctrlClick();
    return;
  }
  
  //get mouse position in original image coordinates
  QPoint p = ConvertDisplayToImageCoordinate( e->pos() );

  //in draw line mode a mouse press has not immediate effect, 
  //mouse release is how a point is finally selected
  if( currentDragMode == DRAW_LINE )
  { return; }
  
  //construct topLeft and bottomRight points to make logic easier
  QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                  QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                      QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  

  //determine action mouse click will cause
  currentDragMode = mouseActionByPosition(e->pos());

  switch(currentDragMode)
  {
    case DRAW_SELECTION:
      mousePressPoint = p;
      mouseDragPoint = p;
      cropMaxDimen = -1.0;
      emit aspectRatioChanged();
      break;
    case MOVE_SELECTION:
      //nothing done until mouse moves
      break;
    case MOVE_TOP_LEFT_CORNER:
      mousePressPoint = bottomRight;
      mouseDragPoint = topLeft;
      break;
    case MOVE_BOTTOM_RIGHT_CORNER:
      mousePressPoint = topLeft;
      mouseDragPoint = bottomRight;
      break;
    case MOVE_TOP_RIGHT_CORNER:
      mousePressPoint = QPoint( topLeft.x(), bottomRight.y() );
      mouseDragPoint = QPoint( bottomRight.x(), topLeft.y() );
      break;
    case MOVE_BOTTOM_LEFT_CORNER:
      mousePressPoint = QPoint( bottomRight.x(), topLeft.y() );
      mouseDragPoint = QPoint( topLeft.x(), bottomRight.y() );
      break;
    case MOVE_LEFT_SIDE:
      mousePressPoint = bottomRight;
      mouseDragPoint  = topLeft;
      break;
    case MOVE_RIGHT_SIDE:
      mousePressPoint = topLeft;
      mouseDragPoint  = bottomRight;
      break;
    case MOVE_TOP_SIDE:
      mousePressPoint = bottomRight;
      mouseDragPoint  = topLeft;
      break;
    case MOVE_BOTTOM_SIDE:
      mousePressPoint = topLeft;
      mouseDragPoint  = bottomRight;
      break;
    //no effect
    default:
      return;
  }
  
  //repaint the selection  
  repaint(false);
  emit selectionChanged();
}
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().

{
  //if in draw line mode
  if( currentDragMode == DRAW_LINE )
  {
    //get mouse location in image space
    QPoint p = ConvertDisplayToImageCoordinate( e->pos() );

    //if first point has not been set set it now
    if( mousePressPoint.x() == -1 )
    {
      mousePressPoint = p;
      repaint(false);
    }
    //else first point has been set then we're setting the 2nd point, emit the selected line
    else
    {
      //get two points on line
      QPoint p1 = mousePressPoint;
      QPoint p2 = p;
      
      //reset mode, press and drag points so there is no selection
      currentDragMode = NO_EFFECT;
      selectNone();
      updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) );   
      
      //emit the selected line
      emit lineSelected( p1, p2 );       
    }
    return; 
  }
  
  //disable move moving from having an effect on the selection
  currentDragMode = NO_EFFECT;
  
  //construct topLeft and bottomRight points to make logic easier
  QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                  QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                      QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  

  //convert selection region to display space to check for tiny selections to ignore
  topLeft = ConvertImageToDisplayCoordinate( topLeft );
  bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
  
  //if selection is very small reset to select nothing
  if( bottomRight.x() - topLeft.x() + 1 < MINIMUM_SELECTION_SIZE ||
      bottomRight.y() - topLeft.y() + 1 < MINIMUM_SELECTION_SIZE ) { selectNone(); }  
}
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.

{  
    //if no scaled image just return
  if(scaledImage.isNull()) { return; }
    
  //create buffer to draw in
  QRect rct = rect();
  rct.moveBy(-x(), -y());
  QPixmap buffer( size() );
  
  //create a painter pointing to the buffer
  QPainter bufferPainter( &buffer );

  //turn off clipping to make painting operations faster
  bufferPainter.setClipping(false);
  
  //initialize buffer with background brush
  bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
  
  //paint the image
  int xOffset = (width() - scaledImage.width()) / 2;
  int yOffset = (height() - scaledImage.height()) / 2;

  //if in draw line mode paint the image normall and then the currently selected line
  //if the two points are set
  if(currentDragMode == DRAW_LINE)
  {
    //paint entire image normally
    bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );       

    //if the first and 2nd points have been set draw the line as well
    if( mousePressPoint.x() != -1 &&
        mouseDragPoint.x() != -1 )
    {
      //get points in display space
      QPoint p1, p2;
      p1 = ConvertImageToDisplayCoordinate( mousePressPoint );
      p2 = ConvertImageToDisplayCoordinate( mouseDragPoint  );

      //setup painter to use green color
      QPen pen;
      pen.setStyle( Qt::SolidLine );
      pen.setCapStyle( Qt::RoundCap );
      pen.setWidth( 2 );
      pen.setColor( green );
      bufferPainter.setPen( pen);
      
      //draw line
      bufferPainter.drawLine( p1.x(), p1.y(), p2.x(), p2.y() );
    }
  }
  //else we're in normal selection mode
  else
  {  
    //if selected region is empty paint entire image in color
    if( mousePressPoint.x() == -1 ||
        (
         currentDragMode == NO_EFFECT &&
         (
          mousePressPoint.x() - mouseDragPoint.x() == 0 ||
          mousePressPoint.y() - mouseDragPoint.y() == 0 
          )
         ))
    {
      bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );       
    }
    //otherwise paint using a two-pass approach,
    //first in monochrome and then the selected region in color
    else
    {
      //first paint using unselected coloring
      bufferPainter.drawImage( QPoint(xOffset, yOffset), unselectedScaledImage );
      
      //construct topLeft and bottomRight points to make logic easier
      QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                      QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
      QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                          QMAX(mousePressPoint.y(), mouseDragPoint.y()) );  
      
      //convert coordinates from original image space to display space
      topLeft = ConvertImageToDisplayCoordinate( topLeft );
      bottomRight = ConvertImageToDisplayCoordinate( bottomRight );
      
      //now paint selected region in color
      bufferPainter.drawImage( topLeft.x(), 
                               topLeft.y(),
                               scaledImage,
                               topLeft.x()-xOffset, topLeft.y()-yOffset,
                               bottomRight.x() - topLeft.x(),
                               bottomRight.y() - topLeft.y() );                                   
      
      //determine color for painting selection rectangle and dimensions
      //use gray/white if cropping to a custom size (and thus real world dimensions
      //are not known). If the crop size is known (eg 5"x7") use green if above
      //resolution is great enough, otherwise use red to indicate that cropping to
      //the specified size will result in pixelation during printing
      QPen pen;
      QColor selectionColor = gray;
      QColor textColor = white;
      int selectedWidth = QABS( mouseDragPoint.x() - mousePressPoint.x() ) + 1;
      int selectedHeight = QABS( mouseDragPoint.y() - mousePressPoint.y() ) + 1;
      if(selectedWidth == 1) selectedWidth = 0;
      if(selectedHeight == 1) selectedHeight = 0;
      
      int DPI = -1;
      int minDPI = -1;
      if( cropMaxDimen != -1.0 )
      {
        //compute DPI that will be used in dominant direction
        int maxDimen = QMAX( selectedWidth, selectedHeight );
        DPI = (int) (maxDimen / cropMaxDimen);          
        
        //if DPI is below minimum use red color for selection rectangle to indicate pixalation may occur
        minDPI = ((Window*)qApp->mainWidget())->getConfig()->getInt( "misc", "minDPI" );      
        if( DPI < minDPI ) 
        { selectionColor = QColor( 200, 0, 0 ); }
        //otherwise use green to signal cropping to this size is safe
        else { selectionColor = QColor( 0, 200, 0 ); }
      } 
      pen.setStyle( Qt::SolidLine );
      pen.setWidth( 2 );
      bufferPainter.setPen( pen);
      
      //paint selection size in lower right corner of selected area
      QString selectionText;
      if( cropMaxDimen != -1.0 &&
          DPI < minDPI )
        selectionText = QString("%1 x %2 (DPI: %3!)").arg(selectedWidth).arg(selectedHeight).arg(DPI);
      else
        selectionText = QString("%1 x %2").arg(selectedWidth).arg(selectedHeight);
      
      QFontMetrics fm( this->font() );
      int stringWidth = fm.width(selectionText);
      int stringHeight = fm.ascent();
      
      int textX = 0;
      int textY = 0;
      const int TEXT_MARGIN = 4;
      if( mouseDragPoint.x() > mousePressPoint.x() )
      { 
        textX = QMIN( xOffset + unselectedScaledImage.width() - TEXT_MARGIN - stringWidth,
                      bottomRight.x() + TEXT_MARGIN ); 
      }
      else
      { 
        textX = QMAX( xOffset + TEXT_MARGIN, 
                      topLeft.x() - TEXT_MARGIN - stringWidth ); 
      }
      
      if( mouseDragPoint.y() > mousePressPoint.y() )
      { 
        textY = QMIN( yOffset + unselectedScaledImage.height() - TEXT_MARGIN,
                      bottomRight.y() + TEXT_MARGIN + stringHeight); 
      }
      else
      { 
        textY = QMAX( yOffset + TEXT_MARGIN + stringHeight, 
                      topLeft.y() - TEXT_MARGIN ); 
      }
      
      //paint a thin outline around the selection
      pen.setColor( selectionColor );
      bufferPainter.setPen( pen);
      QRect selection( topLeft, bottomRight );
      bufferPainter.drawRect(selection);       
      
      //paint image under selected dimension using selected coloring to help make it more visible
      bufferPainter.drawImage( textX, textY-stringHeight,
                               unselectedScaledImage,
                               textX - xOffset, textY-stringHeight-yOffset,
                               stringWidth, fm.height() );
      
      
      //paint selected dimensions    
      pen.setColor( textColor );
      bufferPainter.setPen( pen);
      bufferPainter.drawText( textX, textY, selectionText );
    }        
  }
  
  bufferPainter.end();
  
  //blit buffer to screen
  bitBlt( this,
          e->rect().x(), e->rect().y(),
          &buffer, 
          e->rect().x(), e->rect().y(),
          e->rect().width(), e->rect().height() );
}
void SelectionInterface::resizeEvent ( QResizeEvent *  ) [protected]

Definition at line 108 of file selectionInterface.cpp.

References constructDisplayImages(), and fullScreenImage.

{  
  //if image has yet to be set return
  if( fullScreenImage.isNull() ) return;
  
  //construct new images for painting
  constructDisplayImages();
}
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().

{
  //construct topLeft and bottomRight points to make logic easier
  QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()),
                  QMIN(mousePressPoint.y(), mouseDragPoint.y()) );
  QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()),
                      QMAX(mousePressPoint.y(), mouseDragPoint.y()) );     

  //compute new selection dimension
  int curSelectionWidth = bottomRight.x() - topLeft.x() + 1;
  int curSelectionHeight = bottomRight.y()- topLeft.y() + 1;      
  int newSelectionWidth = -1; 
  int newSelectionHeight = -1;      

  //adjust in dimension of greater resolution
  if( curSelectionWidth > curSelectionHeight )
  {
    newSelectionWidth = QMIN( curSelectionWidth + delta, origImageSize.width() );
    newSelectionHeight = (newSelectionWidth * cachedSelectionSize.height()) / cachedSelectionSize.width();
  }
  else
  {
    newSelectionHeight = QMIN( curSelectionHeight + delta, origImageSize.height() );
    newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();    
  }
  
  //if selection width or height already maxed out then ignore attempt to make selection bigger
  if(delta > 0 &&
     ( curSelectionWidth == origImageSize.width() ||
       curSelectionHeight == origImageSize.height() ) ) 
  { 
    return false;
  }  
  
  //again prevent from growing too big, now along y-axis
  if(newSelectionHeight > origImageSize.height())
  {
    newSelectionHeight = origImageSize.height();
    newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();
  }        
  
  //prevent selection becoming empty
  if(newSelectionWidth <= 0 || newSelectionHeight <= 0)
  {
    newSelectionWidth = curSelectionWidth;
    newSelectionHeight = curSelectionHeight;
  }
  
  //center new selection over current selection , move if necessary
  topLeft = QPoint(QMAX( cachedSelctionCenter.x() - newSelectionWidth/2, 0 ),
                   QMAX( cachedSelctionCenter.y() - newSelectionHeight/2, 0 ));
  bottomRight = QPoint( topLeft.x() + newSelectionWidth - 1,
                        topLeft.y() + newSelectionHeight - 1 );   
  
  //too far right
  if(bottomRight.x() > origImageSize.width() - 1 )
  {
    int diff = bottomRight.x() - (origImageSize.width() - 1);        
    topLeft.setX( topLeft.x() - diff );
    bottomRight.setX( bottomRight.x() - diff );

    //recompute center
    cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                   ( mouseDragPoint.y() + mousePressPoint.y() )/2 );          
  }                     
  
  //too far down
  if(bottomRight.y() > origImageSize.height() - 1 )
  {
    int diff = bottomRight.y() - (origImageSize.height() - 1);        
    topLeft.setY( topLeft.y() - diff );
    bottomRight.setY( bottomRight.y() - diff );
    
    //recompute center
    cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                   ( mouseDragPoint.y() + mousePressPoint.y() )/2 );      
  }                     
  
  //set new selection
  mousePressPoint = topLeft;
  mouseDragPoint = bottomRight;  
  
  //success
  return true;  
}
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().

{
  mousePressPoint.setX( 0 );
  mousePressPoint.setY( 0 );
  mouseDragPoint.setX( origImageSize.width() - 1 );
  mouseDragPoint.setY( origImageSize.height() - 1);

  //cache selection size and center, necessary for computing next size
  cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
                               QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);           
  cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );      
  
  cropMaxDimen = -1.0;
  repaint(false);
  emit selectionChanged();
  emit aspectRatioChanged();
}
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().

{
  return (
          mousePressPoint.x() == -1 ||
          mouseDragPoint.x() - mousePressPoint.x() == 0 ||
          mouseDragPoint.y() - mousePressPoint.y() == 0
         );  
}
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().

{
  mousePressPoint = QPoint(-1,-1);
  mouseDragPoint = QPoint(-1,-1);
  cropMaxDimen = -1.0;
  repaint(false);
  emit selectionChanged();
  emit aspectRatioChanged();
}
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().

{  
  //store original image filename
  origImageFilename = imageFilename;

  //store original image dimensions
  getImageSize( origImageFilename, origImageSize );
    
  //resize image to current screen size for faster
  //scaling during resize events
  QRect screenSize = qApp->desktop()->availableGeometry();
  scaleImage( origImageFilename, fullScreenImage, screenSize.width(), screenSize.height() );

  //construct display images  
  constructDisplayImages();
  
  //reset selection area to nothing
  if(resetSelection)
  {
    mousePressPoint = QPoint(-1,-1);
    mouseDragPoint  = QPoint(-1,-1);
    cropMaxDimen = -1.0;
    SHIFT_Pressed = false;
    CTRL_Pressed = false;
    emit selectionChanged();
  }

  //repaint widget
  //if we are resetting the selection then aspect ratio may have changed
  //so a full repaint (with erase) is necessary
  repaint(resetSelection);
}
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 bottomRight, cachedSelctionCenter, cachedSelectionSize, cropMaxDimen, mouseDragPoint, mousePressPoint, selectionChanged(), and topLeft.

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

{
  mousePressPoint = topLeft;
  mouseDragPoint = bottomRight;
  
  this->cropMaxDimen = cropMaxDimen;
  
  //cache selection size and center, necessary for computing next size
  cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
                               QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);           
  cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
                                 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );    
  
  repaint(false);
  emit selectionChanged();
}
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().

{  
  //if resizing a selection always use size all cursor
  if(SHIFT_Pressed) 
  { 
    setCursor( getCursor(SCALE_SELECTION_CURSOR) );
    return;
  }
  
  //if ctrl pressed show rotate selection cursor  
  if(CTRL_Pressed) 
  { 
    setCursor( getCursor(ROTATE_CURSOR) );
    return;
  }
   
  //if selecting a line the cursor is always the same
  if( currentDragMode == DRAW_LINE )
  {
    setCursor( getCursor(TARGET_CURSOR) );
    return;
  }
  
  //update mouse cursor based on coordinates
  currentMouseShape = mouseActionByPosition( rawP ); 
  switch(currentMouseShape)
  {
    case DRAW_SELECTION:
      setCursor( getCursor(CROSS_CURSOR) ); break;
    case MOVE_SELECTION:
      setCursor( getCursor(MOVE_SELECTION_CURSOR) ); break;
    case MOVE_TOP_LEFT_CORNER:
    case MOVE_BOTTOM_RIGHT_CORNER:
      setCursor( getCursor(MOVE_TL_CURSOR) ); break;
    case MOVE_TOP_RIGHT_CORNER:
    case MOVE_BOTTOM_LEFT_CORNER:
      setCursor( getCursor(MOVE_TR_CURSOR) ); break;
    case MOVE_LEFT_SIDE:
    case MOVE_RIGHT_SIDE:
      setCursor( getCursor(MOVE_HOR_CURSOR) ); break;
    case MOVE_TOP_SIDE:
    case MOVE_BOTTOM_SIDE:
      setCursor( getCursor(MOVE_VERT_CURSOR) ); break;
      break;
    default:
      setCursor( Qt::ArrowCursor );
      break;
  }  
}

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(), setPhoto(), and setSelection().

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: