AlbumShaper 1.0a3
SelectionInterface Class Reference

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

#include <selectionInterface.h>

Inheritance diagram for SelectionInterface:
Collaboration diagram for SelectionInterface:

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 49 of file selectionInterface.h.

Constructor & Destructor Documentation

◆ SelectionInterface()

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

Creates layout.

Definition at line 51 of file selectionInterface.cpp.

51 : QWidget(parent,name)
52{
53 //avoid flicker when repainting
54 setWindowFlags(Qt::WNoAutoErase);
55
56 //set default selection off screen
57 mousePressPoint = QPoint(-1,-1);
58 mouseDragPoint = QPoint(-1,-1);
59
60 //by default mouse movement does not effect the current selection
63
64 Q3Accel *keyAccel = new Q3Accel( this );
65 keyAccel->connectItem( keyAccel->insertItem( Qt::CTRL + Qt::Key_A),
66 this, SLOT(selectAll()) );
67 keyAccel->connectItem( keyAccel->insertItem( Qt::CTRL + Qt::SHIFT + Qt::Key_A ),
68 this, SLOT(selectNone()) );
69
70 //watch mouse movements in order to change mouse cursor
71 setMouseTracking(true);
72
73 //accept focus when clicked on
74 setFocusPolicy( Qt::ClickFocus );
75
76 //initialize cached mouse position to be offscreen by default
77 cachedMousePosition = QPoint(-1,-1);
78
79 //no crop size by default
80 cropMaxDimen = -1.0;
81}
QPoint mousePressPoint
first corner of selection, where mouse first clicked
void selectNone()
selects none of the image
void selectAll()
selects all of the image
double cropMaxDimen
Current crop max dimension (in inches)
DRAG_MODE currentDragMode
method of dragging out, either new selection or resizing selection corner or side
DRAG_MODE currentMouseShape
current mouse shape.
QPoint mouseDragPoint
second corner of selection, where mouse moved to
QPoint cachedMousePosition
cached mouse position, used to scale or drag around selection area
@ NO_EFFECT

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

◆ ~SelectionInterface()

SelectionInterface::~SelectionInterface ( )

Deletes objects.

Definition at line 83 of file selectionInterface.cpp.

83{ }

Member Function Documentation

◆ aspectRatioChanged

void SelectionInterface::aspectRatioChanged ( )
signal

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

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

◆ constructDisplayImages()

void SelectionInterface::constructDisplayImages ( )
private

construct scaled image and unselected images for drawing purposes

Definition at line 127 of file selectionInterface.cpp.

128{
129 //rescale image to fit on screen
130 scaledImage = fullScreenImage.scaled( width(), height(), Qt::KeepAspectRatio );
131
132 //construct an unselected scaled image
134 int x, y;
135 QRgb* rgb;
136 uchar* scanLine;
137 for( y=0; y<unselectedScaledImage.height(); y++)
138 {
139 //iterate over each selected pixel in scanline
140 scanLine = unselectedScaledImage.scanLine(y);
141 for( x=0; x<unselectedScaledImage.width(); x++)
142 {
143 //compress dynamic range to 25% of original
144 rgb = ((QRgb*)scanLine+x);
145
146 double r = ((double)qRed(*rgb) )/255.0;
147 double g = ((double)qGreen(*rgb) )/255.0;
148 double b = ((double)qBlue(*rgb) )/255.0;
149
150 //convert to hsv
151 double h,s,v;
152 RGBtoHSV(r,g,b,&h,&s,&v);
153
154 //scale and clamp v
155 v*=0.25;
156
157 //convert adjusted color back to rgb colorspace and clamp
158 HSVtoRGB( &r,&g,&b, h,s,v);
159 int rp = (int) MIN( MAX((r*255), 0), 255 );
160 int gp = (int) MIN( MAX((g*255), 0), 255 );
161 int bp = (int) MIN( MAX((b*255), 0), 255 );
162
163 //set adjusted color value
164 *rgb = qRgb(rp,gp,bp);
165 }
166 }
167
168
169}
int width
Definition blur.cpp:79
int height
Definition blur.cpp:79
QImage unselectedScaledImage
Grayscale version of scaled image, used for drawing non-selected regions.
QImage scaledImage
Scaled image used for display purposes.
QImage fullScreenImage
Full screen version of image.
#define MIN(x, y)
Definition color.cpp:20
#define MAX(x, y)
Definition color.cpp:21
void RGBtoHSV(double r, double g, double b, double *h, double *s, double *v)
Convert a RGB color triplet to HSV.
void HSVtoRGB(double *r, double *g, double *b, double h, double s, double v)
Convert a HSV color triplet to RGB.
long b

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

Referenced by resizeEvent(), and setPhoto().

◆ ConvertDisplayToImageCoordinate()

QPoint SelectionInterface::ConvertDisplayToImageCoordinate ( QPoint p)
private

converts a point from display coordinates to original image coordinates

Definition at line 884 of file selectionInterface.cpp.

885{
886 QPoint newPoint = p;
887
888 //remove display offset
889 int xOffset = (width() - scaledImage.width() ) / 2;
890 int yOffset = (height() - scaledImage.height() ) / 2;
891 newPoint.setX( newPoint.x() - xOffset );
892 newPoint.setY( newPoint.y() - yOffset );
893
894 //if coordinate is at max set new value explicitly to avoid roundoff error,
895 //otherwise scale to full image dimensions
896 if(newPoint.x() == scaledImage.width() - 1)
897 newPoint.setX( origImageSize.width() - 1);
898 else
899 newPoint.setX( (int) (0.5 + ((double)(newPoint.x() * (origImageSize.width()-1))) / (scaledImage.width()-1) ) );
900
901 if(newPoint.y() == scaledImage.height() - 1)
902 newPoint.setY( origImageSize.height() - 1);
903 else
904 newPoint.setY( (int) (0.5 + ((double)(newPoint.y() * (origImageSize.height()-1))) / (scaledImage.height()-1) ) );
905
906 //return point in image coordinates
907 return newPoint;
908}
QSize origImageSize
original image dimensions

References height, origImageSize, scaledImage, and width.

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

◆ ConvertImageToDisplayCoordinate()

QPoint SelectionInterface::ConvertImageToDisplayCoordinate ( QPoint p)
private

converts a point from original image coordinates to display coordinates

Definition at line 910 of file selectionInterface.cpp.

911{
912 QPoint newPoint = p;
913
914 //if coordinate is at max set new value explicitly to avoid roundoff error,
915 //otherwise scale to full image dimensions
916 if(newPoint.x() == origImageSize.width() - 1)
917 newPoint.setX( scaledImage.width() - 1);
918 else
919 newPoint.setX( (newPoint.x() * (scaledImage.width()-1)) / (origImageSize.width()-1) );
920
921 if(newPoint.y() == origImageSize.height() - 1)
922 newPoint.setY( scaledImage.height() - 1);
923 else
924 newPoint.setY( (newPoint.y() * (scaledImage.height()-1)) / (origImageSize.height()-1) );
925
926 //add display offset
927 int xOffset = (width() - scaledImage.width() ) / 2;
928 int yOffset = (height() - scaledImage.height() ) / 2;
929 newPoint.setX( newPoint.x() + xOffset );
930 newPoint.setY( newPoint.y() + yOffset );
931
932 //return point in image coordinates
933 return newPoint;
934}

References height, origImageSize, scaledImage, and width.

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

◆ cropSelectedPoint()

QPoint SelectionInterface::cropSelectedPoint ( QPoint p)
private

crops a selected point to within the photo

Definition at line 936 of file selectionInterface.cpp.

937{
938 int xOffset = (width() - scaledImage.width() ) / 2;
939 int yOffset = (height() - scaledImage.height() ) / 2;
940
941 QPoint croppedPoint;
942 croppedPoint.setX( MIN( MAX(xOffset, p.x()), xOffset + scaledImage.width() - 1 ) );
943 croppedPoint.setY( MIN( MAX(yOffset, p.y()), yOffset + scaledImage.height() - 1 ) );
944 return croppedPoint;
945}

References height, MAX, MIN, scaledImage, and width.

Referenced by mouseMoveEvent().

◆ ctrlClick

void SelectionInterface::ctrlClick ( )
signal

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

Referenced by mousePressEvent().

◆ enterDrawLineMode()

void SelectionInterface::enterDrawLineMode ( )

enter draw line mode - used for tilt correction

Definition at line 1192 of file selectionInterface.cpp.

1193{
1194 //set the current mode
1196
1197 //during draw line mode ignore control and shift keys, they are only useful for adjusting
1198 //selections, not lines
1199 SHIFT_Pressed = false;
1200 CTRL_Pressed = false;
1201
1202 //reset 1st point
1203 mousePressPoint = QPoint( -1, -1 );
1204 mouseDragPoint = QPoint( -1, -1 );
1205
1206 //repaint and reset the mouse cursor
1208 repaint(false);
1209}
QPoint ConvertImageToDisplayCoordinate(QPoint p)
converts a point from original image coordinates to display coordinates
void updateCursorShape(QPoint p)
update mouse cursor based on position over widget and selected region
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
@ DRAW_LINE

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

Referenced by EditingInterface::startCorrectTilt().

◆ getDisplaySize()

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

returns the current photo display size (in screen pixels)

Definition at line 1020 of file selectionInterface.cpp.

1021{
1022 width = scaledImage.width();
1023 height = scaledImage.height();
1024}

References height, scaledImage, and width.

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

◆ getSelection()

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 1003 of file selectionInterface.cpp.

1004{
1005 //if none selected just return immediately
1006 if(mousePressPoint.x() == -1)
1007 {
1008 topLeft.setX(-1); topLeft.setY(-1);
1009 bottomRight.setX(-1); bottomRight.setY(-1);
1010 return;
1011 }
1012
1013 //set coordinates based on raw selection
1014 topLeft.setX( MIN(mousePressPoint.x(), mouseDragPoint.x()) );
1015 topLeft.setY( MIN(mousePressPoint.y(), mouseDragPoint.y()) );
1016 bottomRight.setX( MAX( mousePressPoint.x(), mouseDragPoint.x()) );
1017 bottomRight.setY( MAX( mousePressPoint.y(), mouseDragPoint.y()) );
1018}
QPoint topLeft
QPoint bottomRight

References bottomRight, MAX, MIN, mouseDragPoint, mousePressPoint, and topLeft.

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

◆ keyPressEvent()

void SelectionInterface::keyPressEvent ( QKeyEvent * e)
protected

Definition at line 1026 of file selectionInterface.cpp.

1027{
1028 //if currently drawing a line, allow the user
1029 //to escape the current acction by hiting escape, all other
1030 //key presses are ignored
1031 if( currentDragMode == DRAW_LINE )
1032 {
1033 if(e->key() == Qt::Key_Escape )
1034 {
1035 //reset mode, press and drag points so there is no selection, and mouse cursor
1037 selectNone();
1039
1040 //emit an invalid line
1041 emit lineSelected( QPoint(-1,-1), QPoint(-1,-1) );
1042 }
1043
1044 return;
1045 }
1046
1047 //if user pressed SHIFT button and selection non-empty
1048 //then note state change,
1049 //this will effect resizing selections during drag events
1050 if(e->key() == Qt::Key_Shift && !selectionEmpty() )
1051 {
1052 SHIFT_Pressed = true;
1054 return;
1055 }
1056
1057 //if user pressed CTRL button and selection non-empty
1058 //then note state change,
1059 //this will effect mouse clicks by rotating the current selection
1060 if(e->key() == Qt::Key_Control && !selectionEmpty() && !SHIFT_Pressed )
1061 {
1062 CTRL_Pressed = true;
1064 return;
1065 }
1066
1067 //ignore keypress if selection is empty
1068 if(mousePressPoint.x() == -1 ||
1069 mousePressPoint.x() - mouseDragPoint.x() == 0 ||
1070 mousePressPoint.y() - mouseDragPoint.y() == 0)
1071 {
1072 e->ignore();
1073 return;
1074 }
1075
1076 //ignore keypresses while mouse button is down since
1077 //intended behavious is unclear
1078 if( currentDragMode != NO_EFFECT )
1079 {
1080 e->ignore();
1081 return;
1082 }
1083
1084 //-------
1085 //if += / -_ keys are pressed scale selection
1086 if( e->key() == Qt::Key_Plus ||
1087 e->key() == Qt::Key_Equal ||
1088 e->key() == Qt::Key_Minus ||
1089 e->key() == Qt::Key_Underscore )
1090 {
1091 int delta = 2*QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
1092
1093 delta = 1;
1094
1095 //negate delta if decreasing size
1096 if( e->key() == Qt::Key_Minus ||
1097 e->key() == Qt::Key_Underscore )
1098 delta = -delta;
1099
1100 if( scaleSelection( delta ) )
1101 {
1102 //repaint the selection
1103 repaint(false);
1104 emit selectionChanged();
1105 }
1106 return;
1107 }
1108 //-------
1109
1110 //find topleft and bottom right of current selection
1111 QPoint topLeft, bottomRight;
1112 topLeft.setX( MIN(mousePressPoint.x(), mouseDragPoint.x()) );
1113 topLeft.setY( MIN(mousePressPoint.y(), mouseDragPoint.y()) );
1114 bottomRight.setX( MAX( mousePressPoint.x(), mouseDragPoint.x()) );
1115 bottomRight.setY( MAX( mousePressPoint.y(), mouseDragPoint.y()) );
1116
1117 //compute the number of pixels in the image correspond to one display pixel
1118 //this is the unit by which the selection will be moved
1119 int moveBy = 0;
1120 if( e->key() == Qt::Key_Left ||
1121 e->key() == Qt::Key_Right )
1122 {
1123 moveBy = QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width();
1124 }
1125 else
1126 {
1127 moveBy = QMAX( origImageSize.height(), scaledImage.height() ) / scaledImage.height();
1128 }
1129
1130 //boundary checked moved by value. must be decalred outside switch statement below
1131 int dx = 0;
1132 int dy = 0;
1133 switch( e->key() )
1134 {
1135 case Qt::Key_Left:
1136 dx = QMAX( topLeft.x() - moveBy, 0) - topLeft.x();
1137 break;
1138 case Qt::Key_Right:
1139 dx = MIN( bottomRight.x() + moveBy, origImageSize.width() - 1) - bottomRight.x();
1140 break;
1141 case Qt::Key_Up:
1142 dy = MAX( topLeft.y() - moveBy, 0) - topLeft.y();
1143 break;
1144 case Qt::Key_Down:
1145 dy = MIN( bottomRight.y() + moveBy, origImageSize.height() - 1) - bottomRight.y();
1146 break;
1147 default:
1148 e->ignore();
1149 return;
1150 }
1151
1152 //shift by dx
1153 mousePressPoint.setX( mousePressPoint.x() + dx );
1154 mouseDragPoint.setX( mouseDragPoint.x() + dx );
1155
1156 //shift by dy
1157 mousePressPoint.setY( mousePressPoint.y() + dy );
1158 mouseDragPoint.setY( mouseDragPoint.y() + dy );
1159
1160 //recompute center
1161 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
1162 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
1163
1164 //only bother with repaint and updating cursor shape if shift actually occured
1165 if(dx != 0 || dy != 0)
1166 {
1167 repaint(false);
1169 }
1170}
bool selectionEmpty()
returns true if selection is empty
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 ...
bool scaleSelection(int delta)
increase/decrease selection while maintaining aspect ratio by changing selected width by delta
QPoint cachedSelctionCenter
cache the aspect ratio when pressing the control buttion, this helps aleviate numerical error that bu...
void selectionChanged()
emitted when the user changed the selected region

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

◆ keyReleaseEvent()

void SelectionInterface::keyReleaseEvent ( QKeyEvent * e)
protected

Definition at line 1172 of file selectionInterface.cpp.

1173{
1174 //if user released SHIFT button then note state change,
1175 //this will effect resizing selections during drag events
1176 if(e->key() == Qt::Key_Shift)
1177 {
1178 SHIFT_Pressed = false;
1180 }
1181 //if user released CTRL button then note state change,
1182 //this will effect mouse clicks
1183 else if(e->key() == Qt::Key_Control)
1184 {
1185 CTRL_Pressed = false;
1187 }
1188 //unhandled key press: pass up the object tree
1189 else { e->ignore(); }
1190}

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

◆ lineSelected

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

◆ mouseActionByPosition()

DRAG_MODE SelectionInterface::mouseActionByPosition ( QPoint p)
private

determine action based on mouse position

Definition at line 361 of file selectionInterface.cpp.

362{
363 //If SHIFT_Pressed is set then scaling a selection
364 if(SHIFT_Pressed) { return SCALE_SELECTION; }
365
366 //construct topLeft and bottomRight points to make logic easier
367 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
371
372 //convert selelection bounary to display space since thresholds are all in display space
375
376 //compute selection center
377 QPoint center( (topLeft.x() + bottomRight.x()) / 2,
378 (topLeft.y() + bottomRight.y()) / 2);
379
380 //if pointer is not over image no effect will occur when clicking
381 int xOffset = (width() - scaledImage.width() ) / 2;
382 int yOffset = (height() - scaledImage.height() ) / 2;
383 if(p.x() < xOffset || p.x() >= scaledImage.width() + xOffset ||
384 p.y() < yOffset || p.y() >= scaledImage.height() + yOffset )
385 { return NO_EFFECT; }
386
387 //if either there is no selection or the entire image is selected, new
388 //mouse clicks are interpreted as being for selecting new regions
389 if( mousePressPoint.x() == -1 ||
390 ( bottomRight.x() - topLeft.x() == origImageSize.width() - 1 &&
391 bottomRight.y() - topLeft.y() == origImageSize.height() - 1 )
392 )
393 { return DRAW_SELECTION; }
394 //move entire selection
395 //mouse is within MOVE_THRESH of center and outside
396 //DRAG_THRESH of any side
397 else if( p.x() >= MAX( center.x() - MOVE_THRESHOLD, topLeft.x() ) &&
398 p.x() <= MIN( center.x() + MOVE_THRESHOLD, bottomRight.x() ) &&
399 p.y() >= MAX( center.y() - MOVE_THRESHOLD, topLeft.y() ) &&
400 p.y() <= MIN( center.y() + MOVE_THRESHOLD, bottomRight.y() ) &&
401 p.x() > topLeft.x() + DRAG_THRESHOLD &&
402 p.x() < bottomRight.x() - DRAG_THRESHOLD &&
403 p.y() > topLeft.y() + DRAG_THRESHOLD &&
404 p.y() < bottomRight.y() - DRAG_THRESHOLD )
405{ return MOVE_SELECTION; }
406 //drag top left
407 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
408 QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD )
409 { return MOVE_TOP_LEFT_CORNER; }
410 //drag top right
411 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
412 QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD )
413 { return MOVE_TOP_RIGHT_CORNER; }
414 //drag bottom left
415 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
416 QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )
417 { return MOVE_BOTTOM_LEFT_CORNER; }
418 //drag bottom right
419 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
420 QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD )
421 { return MOVE_BOTTOM_RIGHT_CORNER; }
422 //drag left
423 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD &&
424 p.y() >= topLeft.y() &&
425 p.y() <= bottomRight.y() )
426 { return MOVE_LEFT_SIDE; }
427 //drag right
428 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD &&
429 p.y() >= topLeft.y() &&
430 p.y() <= bottomRight.y() )
431 { return MOVE_RIGHT_SIDE; }
432 //drag top
433 else if( QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD &&
434 p.x() >= topLeft.x() &&
435 p.x() <= bottomRight.x() )
436 { return MOVE_TOP_SIDE; }
437 //drag bottom
438 else if( QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD &&
439 p.x() >= topLeft.x() &&
440 p.x() <= bottomRight.x() )
441 { return MOVE_BOTTOM_SIDE; }
442 //else new selection
443 else { return DRAW_SELECTION; }
444}
#define DRAG_THRESHOLD
#define MOVE_THRESHOLD
@ MOVE_TOP_SIDE
@ MOVE_BOTTOM_RIGHT_CORNER
@ MOVE_TOP_RIGHT_CORNER
@ DRAW_SELECTION
@ MOVE_BOTTOM_SIDE
@ MOVE_RIGHT_SIDE
@ MOVE_SELECTION
@ MOVE_LEFT_SIDE
@ MOVE_TOP_LEFT_CORNER
@ MOVE_BOTTOM_LEFT_CORNER
@ SCALE_SELECTION

References bottomRight, ConvertImageToDisplayCoordinate(), DRAG_THRESHOLD, DRAW_SELECTION, height, MAX, MIN, 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().

◆ mouseMoveEvent()

void SelectionInterface::mouseMoveEvent ( QMouseEvent * e)
protected

Definition at line 661 of file selectionInterface.cpp.

662{
663 //if the SHIFT_Pressed state variable is true but SHIFT is now not pressed
664 //reset bool and mouse cursor!
665 if( SHIFT_Pressed && !(e->state() & Qt::ShiftModifier) )
666 {
667 SHIFT_Pressed = false;
669 }
670
671 //if the CTRL_Pressed state variable is true but CTRL is now not pressed
672 //reset bool and mouse cursor!
673 if( CTRL_Pressed && !(e->state() & Qt::ControlModifier) )
674 {
675 CTRL_Pressed = false;
677 }
678
679 //if mouse not pressed update mouse cursor if
680 //mode will change if user presses mouse button
682 {
683 //only update the mouse cursor shape if it will change
684 if( mouseActionByPosition( e->pos() ) != currentMouseShape )
685 updateCursorShape( e->pos() );
686
688 }
689 //if currently in draw line mode update the selected line
690 else if(currentDragMode == DRAW_LINE)
691 {
692 //if the 1st point hasn't been set yet do nothing
693 if( mousePressPoint.x() == -1 )
694 return;
695
696 //1st point set, set 2nd point to current mouse position and redraw
698
699 //repaint the line
700 repaint(false);
701 }
702 //update selection rectangle or selected line
703 else
704 {
705 //get mouse position in original image coordinates
707
708 //construct topLeft and bottomRight points to make logic easier
709 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
713
714 //if SHIFT pressed and both selction dimensions non-empty then scale selection
715 if(SHIFT_Pressed &&
716 bottomRight.x() > topLeft.x() &&
717 bottomRight.y() > topLeft.y() )
718 {
719 //update width, prevent from growing beyond image boundaries
720 int delta = p.x() - cachedMousePosition.x();
721 if( !scaleSelection( delta ) )
722 {
723 //cache the current mouse position before returning without change
725 return;
726 }
727 }
728 //if draging the entire selection, update x and y coordinates for
729 //both mousePress and mouseDrag points and update the dragSelectionPoint
730 else if( currentDragMode == MOVE_SELECTION )
731 {
732 //compute offset
733 QPoint offset( p.x() - cachedMousePosition.x(),
734 p.y() - cachedMousePosition.y() );
735
736 //construct topLeft and bottomRight points to make logic easier
737 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
741
742 //clip offset so selected area is always within image boundaries
743
744 //left
745 if(offset.x() < 0 && topLeft.x() + offset.x() < 0 )
746 offset.setX( -topLeft.x() );
747
748 //right
749 if(offset.x() > 0 && bottomRight.x() + offset.x() >= origImageSize.width() )
750 offset.setX( origImageSize.width() - 1 - bottomRight.x() );
751
752 //top
753 if(offset.y() < 0 && topLeft.y() + offset.y() < 0 )
754 offset.setY( -topLeft.y() );
755
756 //bottom
757 if(offset.y() > 0 && bottomRight.y() + offset.y() >= origImageSize.height() )
758 offset.setY( origImageSize.height() - 1 - bottomRight.y() );
759
760 //update press and drag points
761 mousePressPoint+= offset;
762 mouseDragPoint+= offset;
763
764 //recompute selection center
765 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
766 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
767 }
768 //if moving any corner or drawing the original selection,
769 //update x and y coords of drag point
770 else if( currentDragMode == DRAW_SELECTION ||
775 {
776 mouseDragPoint.setX( p.x() );
777 mouseDragPoint.setY( p.y() );
778 cropMaxDimen = -1.0;
779
780 //cache selection size and center, necessary for computing next size
781 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
782 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
783 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
784 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
785
786
787 emit aspectRatioChanged();
788 }
789 //else if moving the left or right sides just update the x coordinate of
790 //the drag point
791 else if( currentDragMode == MOVE_LEFT_SIDE ||
793 {
794 mouseDragPoint.setX( p.x() );
795 cropMaxDimen = -1.0;
796 emit aspectRatioChanged();
797
798 //cache selection size and center, necessary for computing next size
799 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
800 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
801 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
802 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
803 }
804 //else if moving the top or bottom sides just update the x coordinate of
805 //the drag point
806 else if( currentDragMode == MOVE_TOP_SIDE ||
808 {
809 mouseDragPoint.setY( p.y() );
810 cropMaxDimen = -1.0;
811 emit aspectRatioChanged();
812
813 //cache selection size and center, necessary for computing next size
814 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
815 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
816 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
817 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
818
819 }
820
821 //cache current mouse position
823
824 //repaint the selection
825 repaint(false);
826 emit selectionChanged();
827
828 //only update the mouse cursor shape if it will change
829 if( mouseActionByPosition( e->pos() ) != currentMouseShape )
830 updateCursorShape( e->pos() );
831 }
832}
void aspectRatioChanged()
emitted when the user changed the aspect ratio of the selected region
QPoint ConvertDisplayToImageCoordinate(QPoint p)
converts a point from display coordinates to original image coordinates
DRAG_MODE mouseActionByPosition(QPoint p)
determine action based on mouse position
QPoint cropSelectedPoint(QPoint p)
crops a selected point to within the photo

References aspectRatioChanged(), bottomRight, cachedMousePosition, cachedSelctionCenter, cachedSelectionSize, ConvertDisplayToImageCoordinate(), ConvertImageToDisplayCoordinate(), cropMaxDimen, cropSelectedPoint(), CTRL_Pressed, currentDragMode, currentMouseShape, DRAW_LINE, DRAW_SELECTION, MAX, MIN, 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().

◆ mousePressEvent()

void SelectionInterface::mousePressEvent ( QMouseEvent * e)
protected

Definition at line 446 of file selectionInterface.cpp.

447{
448 //If CTRL pressed then emit ctrlClick event
449 if( CTRL_Pressed)
450 {
451 emit ctrlClick();
452 return;
453 }
454
455 //get mouse position in original image coordinates
456 QPoint p = ConvertDisplayToImageCoordinate( e->pos() );
457
458 //in draw line mode a mouse press has not immediate effect,
459 //mouse release is how a point is finally selected
461 { return; }
462
463 //construct topLeft and bottomRight points to make logic easier
464 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
468
469 //determine action mouse click will cause
471
472 switch(currentDragMode)
473 {
474 case DRAW_SELECTION:
475 mousePressPoint = p;
476 mouseDragPoint = p;
477 cropMaxDimen = -1.0;
478 emit aspectRatioChanged();
479 break;
480 case MOVE_SELECTION:
481 //nothing done until mouse moves
482 break;
486 break;
490 break;
492 mousePressPoint = QPoint( topLeft.x(), bottomRight.y() );
493 mouseDragPoint = QPoint( bottomRight.x(), topLeft.y() );
494 break;
496 mousePressPoint = QPoint( bottomRight.x(), topLeft.y() );
497 mouseDragPoint = QPoint( topLeft.x(), bottomRight.y() );
498 break;
499 case MOVE_LEFT_SIDE:
502 break;
503 case MOVE_RIGHT_SIDE:
506 break;
507 case MOVE_TOP_SIDE:
510 break;
511 case MOVE_BOTTOM_SIDE:
514 break;
515 //no effect
516 default:
517 return;
518 }
519
520 //repaint the selection
521 repaint(false);
522 emit selectionChanged();
523}
void ctrlClick()
emitted when a user CTRL-clicks a selection indicating the selection needs to be rotated intelligentl...

References aspectRatioChanged(), bottomRight, ConvertDisplayToImageCoordinate(), cropMaxDimen, CTRL_Pressed, ctrlClick(), currentDragMode, DRAW_LINE, DRAW_SELECTION, MAX, MIN, 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.

◆ mouseReleaseEvent()

void SelectionInterface::mouseReleaseEvent ( QMouseEvent * e)
protected

Definition at line 834 of file selectionInterface.cpp.

835{
836 //if in draw line mode
838 {
839 //get mouse location in image space
840 QPoint p = ConvertDisplayToImageCoordinate( e->pos() );
841
842 //if first point has not been set set it now
843 if( mousePressPoint.x() == -1 )
844 {
845 mousePressPoint = p;
846 repaint(false);
847 }
848 //else first point has been set then we're setting the 2nd point, emit the selected line
849 else
850 {
851 //get two points on line
852 QPoint p1 = mousePressPoint;
853 QPoint p2 = p;
854
855 //reset mode, press and drag points so there is no selection
857 selectNone();
859
860 //emit the selected line
861 emit lineSelected( p1, p2 );
862 }
863 return;
864 }
865
866 //disable move moving from having an effect on the selection
868
869 //construct topLeft and bottomRight points to make logic easier
870 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
874
875 //convert selection region to display space to check for tiny selections to ignore
878
879 //if selection is very small reset to select nothing
880 if( bottomRight.x() - topLeft.x() + 1 < MINIMUM_SELECTION_SIZE ||
881 bottomRight.y() - topLeft.y() + 1 < MINIMUM_SELECTION_SIZE ) { selectNone(); }
882}
#define MINIMUM_SELECTION_SIZE

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

◆ paintEvent()

void SelectionInterface::paintEvent ( QPaintEvent * e)
protected

Definition at line 171 of file selectionInterface.cpp.

172{
173 //if no scaled image just return
174 if(scaledImage.isNull()) { return; }
175
176 //create buffer to draw in
177 QRect rct = rect();
178 rct.moveBy(-x(), -y());
179 QPixmap buffer( size() );
180
181 //create a painter pointing to the buffer
182 QPainter bufferPainter( &buffer );
183
184 //turn off clipping to make painting operations faster
185 bufferPainter.setClipping(false);
186
187 //initialize buffer with background brush
188 bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
189
190 //paint the image
191 int xOffset = (width() - scaledImage.width()) / 2;
192 int yOffset = (height() - scaledImage.height()) / 2;
193
194 //if in draw line mode paint the image normall and then the currently selected line
195 //if the two points are set
197 {
198 //paint entire image normally
199 bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );
200
201 //if the first and 2nd points have been set draw the line as well
202 if( mousePressPoint.x() != -1 &&
203 mouseDragPoint.x() != -1 )
204 {
205 //get points in display space
206 QPoint p1, p2;
209
210 //setup painter to use green color
211 QPen pen;
212 pen.setStyle( Qt::SolidLine );
213 pen.setCapStyle( Qt::RoundCap );
214 pen.setWidth( 2 );
215 pen.setColor( Qt::green );
216 bufferPainter.setPen( pen);
217
218 //draw line
219 bufferPainter.drawLine( p1.x(), p1.y(), p2.x(), p2.y() );
220 }
221 }
222 //else we're in normal selection mode
223 else
224 {
225 //if selected region is empty paint entire image in color
226 if( mousePressPoint.x() == -1 ||
227 (
229 (
230 mousePressPoint.x() - mouseDragPoint.x() == 0 ||
231 mousePressPoint.y() - mouseDragPoint.y() == 0
232 )
233 ))
234 {
235 bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage );
236 }
237 //otherwise paint using a two-pass approach,
238 //first in monochrome and then the selected region in color
239 else
240 {
241 //first paint using unselected coloring
242 bufferPainter.drawImage( QPoint(xOffset, yOffset), unselectedScaledImage );
243
244 //construct topLeft and bottomRight points to make logic easier
245 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
249
250 //convert coordinates from original image space to display space
253
254 //now paint selected region in color
255 bufferPainter.drawImage( topLeft.x(),
256 topLeft.y(),
258 topLeft.x()-xOffset, topLeft.y()-yOffset,
259 bottomRight.x() - topLeft.x(),
260 bottomRight.y() - topLeft.y() );
261
262 //determine color for painting selection rectangle and dimensions
263 //use gray/white if cropping to a custom size (and thus real world dimensions
264 //are not known). If the crop size is known (eg 5"x7") use green if above
265 //resolution is great enough, otherwise use red to indicate that cropping to
266 //the specified size will result in pixelation during printing
267 QPen pen;
268 QColor selectionColor = Qt::gray;
269 QColor textColor = Qt::white;
270 int selectedWidth = QABS( mouseDragPoint.x() - mousePressPoint.x() ) + 1;
271 int selectedHeight = QABS( mouseDragPoint.y() - mousePressPoint.y() ) + 1;
272 if(selectedWidth == 1) selectedWidth = 0;
273 if(selectedHeight == 1) selectedHeight = 0;
274
275 int DPI = -1;
276 int minDPI = -1;
277 if( cropMaxDimen != -1.0 )
278 {
279 //compute DPI that will be used in dominant direction
280 int maxDimen = QMAX( selectedWidth, selectedHeight );
281 DPI = (int) (maxDimen / cropMaxDimen);
282
283 //if DPI is below minimum use red color for selection rectangle to indicate pixalation may occur
284 minDPI = ((Window*)qApp->mainWidget())->getConfig()->getInt( "misc", "minDPI" );
285 if( DPI < minDPI )
286 { selectionColor = QColor( 200, 0, 0 ); }
287 //otherwise use green to signal cropping to this size is safe
288 else { selectionColor = QColor( 0, 200, 0 ); }
289 }
290 pen.setStyle( Qt::SolidLine );
291 pen.setWidth( 2 );
292 bufferPainter.setPen( pen);
293
294 //paint selection size in lower right corner of selected area
295 QString selectionText;
296 if( cropMaxDimen != -1.0 &&
297 DPI < minDPI )
298 selectionText = QString("%1 x %2 (DPI: %3!)").arg(selectedWidth).arg(selectedHeight).arg(DPI);
299 else
300 selectionText = QString("%1 x %2").arg(selectedWidth).arg(selectedHeight);
301
302 QFontMetrics fm( this->font() );
303 int stringWidth = fm.width(selectionText);
304 int stringHeight = fm.ascent();
305
306 int textX = 0;
307 int textY = 0;
308 const int TEXT_MARGIN = 4;
309 if( mouseDragPoint.x() > mousePressPoint.x() )
310 {
311 textX = MIN( xOffset + unselectedScaledImage.width() - TEXT_MARGIN - stringWidth,
312 bottomRight.x() + TEXT_MARGIN );
313 }
314 else
315 {
316 textX = MAX( xOffset + TEXT_MARGIN,
317 topLeft.x() - TEXT_MARGIN - stringWidth );
318 }
319
320 if( mouseDragPoint.y() > mousePressPoint.y() )
321 {
322 textY = MIN( yOffset + unselectedScaledImage.height() - TEXT_MARGIN,
323 bottomRight.y() + TEXT_MARGIN + stringHeight);
324 }
325 else
326 {
327 textY = MAX( yOffset + TEXT_MARGIN + stringHeight,
328 topLeft.y() - TEXT_MARGIN );
329 }
330
331 //paint a thin outline around the selection
332 pen.setColor( selectionColor );
333 bufferPainter.setPen( pen);
334 QRect selection( topLeft, bottomRight );
335 bufferPainter.drawRect(selection);
336
337 //paint image under selected dimension using selected coloring to help make it more visible
338 bufferPainter.drawImage( textX, textY-stringHeight,
340 textX - xOffset, textY-stringHeight-yOffset,
341 stringWidth, fm.height() );
342
343
344 //paint selected dimensions
345 pen.setColor( textColor );
346 bufferPainter.setPen( pen);
347 bufferPainter.drawText( textX, textY, selectionText );
348 }
349 }
350
351 bufferPainter.end();
352
353 //blit buffer to screen
354 bitBlt( this,
355 e->rect().x(), e->rect().y(),
356 &buffer,
357 e->rect().x(), e->rect().y(),
358 e->rect().width(), e->rect().height() );
359}
float * buffer
Definition blur.cpp:80
Top level widget, encapsulates the title widget, the layout widget, and the toolbar widget.
Definition window.h:40
#define TEXT_MARGIN

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

◆ resizeEvent()

void SelectionInterface::resizeEvent ( QResizeEvent * )
protected

Definition at line 118 of file selectionInterface.cpp.

119{
120 //if image has yet to be set return
121 if( fullScreenImage.isNull() ) return;
122
123 //construct new images for painting
125}
void constructDisplayImages()
construct scaled image and unselected images for drawing purposes

References constructDisplayImages(), and fullScreenImage.

◆ scaleSelection()

bool SelectionInterface::scaleSelection ( int delta)
private

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

Definition at line 575 of file selectionInterface.cpp.

576{
577 //construct topLeft and bottomRight points to make logic easier
578 QPoint topLeft( MIN(mousePressPoint.x(), mouseDragPoint.x()),
582
583 //compute new selection dimension
584 int curSelectionWidth = bottomRight.x() - topLeft.x() + 1;
585 int curSelectionHeight = bottomRight.y()- topLeft.y() + 1;
586 int newSelectionWidth = -1;
587 int newSelectionHeight = -1;
588
589 //adjust in dimension of greater resolution
590 if( curSelectionWidth > curSelectionHeight )
591 {
592 newSelectionWidth = MIN( curSelectionWidth + delta, origImageSize.width() );
593 newSelectionHeight = (newSelectionWidth * cachedSelectionSize.height()) / cachedSelectionSize.width();
594 }
595 else
596 {
597 newSelectionHeight = MIN( curSelectionHeight + delta, origImageSize.height() );
598 newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();
599 }
600
601 //if selection width or height already maxed out then ignore attempt to make selection bigger
602 if(delta > 0 &&
603 ( curSelectionWidth == origImageSize.width() ||
604 curSelectionHeight == origImageSize.height() ) )
605 {
606 return false;
607 }
608
609 //again prevent from growing too big, now along y-axis
610 if(newSelectionHeight > origImageSize.height())
611 {
612 newSelectionHeight = origImageSize.height();
613 newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height();
614 }
615
616 //prevent selection becoming empty
617 if(newSelectionWidth <= 0 || newSelectionHeight <= 0)
618 {
619 newSelectionWidth = curSelectionWidth;
620 newSelectionHeight = curSelectionHeight;
621 }
622
623 //center new selection over current selection , move if necessary
624 topLeft = QPoint(QMAX( cachedSelctionCenter.x() - newSelectionWidth/2, 0 ),
625 QMAX( cachedSelctionCenter.y() - newSelectionHeight/2, 0 ));
626 bottomRight = QPoint( topLeft.x() + newSelectionWidth - 1,
627 topLeft.y() + newSelectionHeight - 1 );
628
629 //too far right
630 if(bottomRight.x() > origImageSize.width() - 1 )
631 {
632 int diff = bottomRight.x() - (origImageSize.width() - 1);
633 topLeft.setX( topLeft.x() - diff );
634 bottomRight.setX( bottomRight.x() - diff );
635
636 //recompute center
637 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
638 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
639 }
640
641 //too far down
642 if(bottomRight.y() > origImageSize.height() - 1 )
643 {
644 int diff = bottomRight.y() - (origImageSize.height() - 1);
645 topLeft.setY( topLeft.y() - diff );
646 bottomRight.setY( bottomRight.y() - diff );
647
648 //recompute center
649 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
650 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
651 }
652
653 //set new selection
656
657 //success
658 return true;
659}

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

Referenced by keyPressEvent(), and mouseMoveEvent().

◆ selectAll

void SelectionInterface::selectAll ( )
slot

selects all of the image

Definition at line 956 of file selectionInterface.cpp.

957{
958 mousePressPoint.setX( 0 );
959 mousePressPoint.setY( 0 );
960 mouseDragPoint.setX( origImageSize.width() - 1 );
961 mouseDragPoint.setY( origImageSize.height() - 1);
962
963 //cache selection size and center, necessary for computing next size
964 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
965 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
966 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
967 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
968
969 cropMaxDimen = -1.0;
970 repaint(false);
971 emit selectionChanged();
972 emit aspectRatioChanged();
973}

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

Referenced by SelectionInterface().

◆ selectionChanged

void SelectionInterface::selectionChanged ( )
signal

emitted when the user changed the selected region

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

◆ selectionEmpty()

bool SelectionInterface::selectionEmpty ( )

returns true if selection is empty

Definition at line 947 of file selectionInterface.cpp.

948{
949 return (
950 mousePressPoint.x() == -1 ||
951 mouseDragPoint.x() - mousePressPoint.x() == 0 ||
952 mouseDragPoint.y() - mousePressPoint.y() == 0
953 );
954}

References mouseDragPoint, and mousePressPoint.

Referenced by keyPressEvent().

◆ selectNone

void SelectionInterface::selectNone ( )
slot

selects none of the image

Definition at line 975 of file selectionInterface.cpp.

976{
977 mousePressPoint = QPoint(-1,-1);
978 mouseDragPoint = QPoint(-1,-1);
979 cropMaxDimen = -1.0;
980 repaint(false);
981 emit selectionChanged();
982 emit aspectRatioChanged();
983}

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

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

◆ setPhoto()

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

Updates displayed photo.

Definition at line 85 of file selectionInterface.cpp.

86{
87 //store original image filename
88 origImageFilename = imageFilename;
89
90 //store original image dimensions
92
93 //resize image to current screen size for faster
94 //scaling during resize events
95 QRect screenSize = qApp->desktop()->availableGeometry();
96 scaleImage( origImageFilename, fullScreenImage, screenSize.width(), screenSize.height() );
97
98 //construct display images
100
101 //reset selection area to nothing
102 if(resetSelection)
103 {
104 mousePressPoint = QPoint(-1,-1);
105 mouseDragPoint = QPoint(-1,-1);
106 cropMaxDimen = -1.0;
107 SHIFT_Pressed = false;
108 CTRL_Pressed = false;
109 emit selectionChanged();
110 }
111
112 //repaint widget
113 //if we are resetting the selection then aspect ratio may have changed
114 //so a full repaint (with erase) is necessary
115 repaint(resetSelection);
116}
QString origImageFilename
original image filename
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
bool getImageSize(const char *filename, QSize &size)
Get image dimensions.

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

◆ setSelection()

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 985 of file selectionInterface.cpp.

987{
990
991 this->cropMaxDimen = cropMaxDimen;
992
993 //cache selection size and center, necessary for computing next size
994 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1,
995 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1);
996 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2,
997 ( mouseDragPoint.y() + mousePressPoint.y() )/2 );
998
999 repaint(false);
1000 emit selectionChanged();
1001}

References bottomRight, cachedSelctionCenter, cachedSelectionSize, cropMaxDimen, mouseDragPoint, mousePressPoint, selectionChanged(), and topLeft.

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

◆ sizeHint()

QSize SelectionInterface::sizeHint ( )
protected

◆ updateCursorShape()

void SelectionInterface::updateCursorShape ( QPoint p)
private

update mouse cursor based on position over widget and selected region

Definition at line 525 of file selectionInterface.cpp.

526{
527 //if resizing a selection always use size all cursor
528 if(SHIFT_Pressed)
529 {
530 setCursor( getCursor(SCALE_SELECTION_CURSOR) );
531 return;
532 }
533
534 //if ctrl pressed show rotate selection cursor
535 if(CTRL_Pressed)
536 {
537 setCursor( getCursor(ROTATE_CURSOR) );
538 return;
539 }
540
541 //if selecting a line the cursor is always the same
543 {
544 setCursor( getCursor(TARGET_CURSOR) );
545 return;
546 }
547
548 //update mouse cursor based on coordinates
550 switch(currentMouseShape)
551 {
552 case DRAW_SELECTION:
553 setCursor( getCursor(CROSS_CURSOR) ); break;
554 case MOVE_SELECTION:
555 setCursor( getCursor(MOVE_SELECTION_CURSOR) ); break;
558 setCursor( getCursor(MOVE_TL_CURSOR) ); break;
561 setCursor( getCursor(MOVE_TR_CURSOR) ); break;
562 case MOVE_LEFT_SIDE:
563 case MOVE_RIGHT_SIDE:
564 setCursor( getCursor(MOVE_HOR_CURSOR) ); break;
565 case MOVE_TOP_SIDE:
566 case MOVE_BOTTOM_SIDE:
567 setCursor( getCursor(MOVE_VERT_CURSOR) ); break;
568 break;
569 default:
570 setCursor( Qt::ArrowCursor );
571 break;
572 }
573}
const QCursor & getCursor(CUSTOM_CURSOR_TYPE type)
Definition cursors.cpp:52
@ SCALE_SELECTION_CURSOR
Definition cursors.h:25
@ MOVE_TR_CURSOR
Definition cursors.h:23
@ ROTATE_CURSOR
Definition cursors.h:26
@ MOVE_VERT_CURSOR
Definition cursors.h:21
@ TARGET_CURSOR
Definition cursors.h:28
@ MOVE_HOR_CURSOR
Definition cursors.h:20
@ MOVE_TL_CURSOR
Definition cursors.h:22
@ CROSS_CURSOR
Definition cursors.h:17
@ MOVE_SELECTION_CURSOR
Definition cursors.h:19

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

Member Data Documentation

◆ cachedMousePosition

QPoint SelectionInterface::cachedMousePosition
private

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

Definition at line 151 of file selectionInterface.h.

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

◆ cachedSelctionCenter

QPoint SelectionInterface::cachedSelctionCenter
private

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 174 of file selectionInterface.h.

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

◆ cachedSelectionSize

QSize SelectionInterface::cachedSelectionSize
private

Definition at line 175 of file selectionInterface.h.

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

◆ cropMaxDimen

double SelectionInterface::cropMaxDimen
private

Current crop max dimension (in inches)

Definition at line 178 of file selectionInterface.h.

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

◆ CTRL_Pressed

bool SelectionInterface::CTRL_Pressed
private

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

Definition at line 170 of file selectionInterface.h.

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

◆ currentDragMode

DRAG_MODE SelectionInterface::currentDragMode
private

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

Definition at line 154 of file selectionInterface.h.

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

◆ currentMouseShape

DRAG_MODE SelectionInterface::currentMouseShape
private

current mouse shape.

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

Definition at line 158 of file selectionInterface.h.

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

◆ fullScreenImage

QImage SelectionInterface::fullScreenImage
private

Full screen version of image.

Definition at line 136 of file selectionInterface.h.

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

◆ mouseDragPoint

QPoint SelectionInterface::mouseDragPoint
private

◆ mousePressPoint

QPoint SelectionInterface::mousePressPoint
private

◆ origImageFilename

QString SelectionInterface::origImageFilename
private

original image filename

Definition at line 161 of file selectionInterface.h.

Referenced by setPhoto().

◆ origImageSize

QSize SelectionInterface::origImageSize
private

◆ scaledImage

QImage SelectionInterface::scaledImage
private

◆ SHIFT_Pressed

bool SelectionInterface::SHIFT_Pressed
private

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

Definition at line 167 of file selectionInterface.h.

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

◆ unselectedScaledImage

QImage SelectionInterface::unselectedScaledImage
private

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

Definition at line 142 of file selectionInterface.h.

Referenced by constructDisplayImages(), and paintEvent().


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