Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

selectionInterface.cpp

Go to the documentation of this file.
00001 //============================================== 00002 // copyright : (C) 2003-2005 by Will Stokes 00003 //============================================== 00004 // This program is free software; you can redistribute it 00005 // and/or modify it under the terms of the GNU General 00006 // Public License as published by the Free Software 00007 // Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 //============================================== 00010 00011 //Systemwide includes 00012 #include <qsize.h> 00013 #include <qapplication.h> 00014 #include <qpainter.h> 00015 #include <qevent.h> 00016 #include <qpoint.h> 00017 #include <qaccel.h> 00018 #include <qcursor.h> 00019 00020 //Projectwide includes 00021 #include "selectionInterface.h" 00022 #include "../cursors.h" 00023 #include "../../config.h" 00024 #include "../../backend/tools/imageTools.h" 00025 #include "../window.h" 00026 #include "../../configuration/configuration.h" 00027 00028 //a mouse press within DRAG_THRESHOLD will move corners or sides 00029 //if mouse press is not within DRAG_THRESHOLD of any corner or side of 00030 //current selection a new selection will be started and both press and drag points will be reset 00031 #define DRAG_THRESHOLD 8 00032 00033 //a mouse press within MOVE_THRESHOLD of the center along both x and y axis will 00034 //move the entier selection 00035 #define MOVE_THRESHOLD 150 00036 00037 //minimum size of a valid selection 00038 #define MINIMUM_SELECTION_SIZE 3 00039 00040 //============================================== 00041 SelectionInterface::SelectionInterface(QWidget *parent, const char* name ) : QWidget(parent,name) 00042 { 00043 //avoid flicker when repainting 00044 setWFlags(WRepaintNoErase); 00045 00046 //set default selection off screen 00047 mousePressPoint = QPoint(-1,-1); 00048 mouseDragPoint = QPoint(-1,-1); 00049 00050 //by default mouse movement does not effect the current selection 00051 currentDragMode = NO_EFFECT; 00052 currentMouseShape = NO_EFFECT; 00053 00054 QAccel *keyAccel = new QAccel( this ); 00055 keyAccel->connectItem( keyAccel->insertItem( CTRL + Key_A), 00056 this, SLOT(selectAll()) ); 00057 keyAccel->connectItem( keyAccel->insertItem( CTRL + SHIFT + Key_A ), 00058 this, SLOT(selectNone()) ); 00059 00060 //watch mouse movements in order to change mouse cursor 00061 setMouseTracking(true); 00062 00063 //accept focus when clicked on 00064 setFocusPolicy( QWidget::ClickFocus ); 00065 00066 //initialize cached mouse position to be offscreen by default 00067 cachedMousePosition = QPoint(-1,-1); 00068 00069 //no crop size by default 00070 cropMaxDimen = -1.0; 00071 } 00072 //============================================== 00073 SelectionInterface::~SelectionInterface() { } 00074 //============================================== 00075 void SelectionInterface::setPhoto(QString imageFilename, bool resetSelection) 00076 { 00077 //store original image filename 00078 origImageFilename = imageFilename; 00079 00080 //store original image dimensions 00081 getImageSize( origImageFilename, origImageSize ); 00082 00083 //resize image to current screen size for faster 00084 //scaling during resize events 00085 QRect screenSize = qApp->desktop()->availableGeometry(); 00086 scaleImage( origImageFilename, fullScreenImage, screenSize.width(), screenSize.height() ); 00087 00088 //construct display images 00089 constructDisplayImages(); 00090 00091 //reset selection area to nothing 00092 if(resetSelection) 00093 { 00094 mousePressPoint = QPoint(-1,-1); 00095 mouseDragPoint = QPoint(-1,-1); 00096 cropMaxDimen = -1.0; 00097 SHIFT_Pressed = false; 00098 CTRL_Pressed = false; 00099 emit selectionChanged(); 00100 } 00101 00102 //repaint widget 00103 //if we are resetting the selection then aspect ratio may have changed 00104 //so a full repaint (with erase) is necessary 00105 repaint(resetSelection); 00106 } 00107 //============================================== 00108 void SelectionInterface::resizeEvent( QResizeEvent * ) 00109 { 00110 //if image has yet to be set return 00111 if( fullScreenImage.isNull() ) return; 00112 00113 //construct new images for painting 00114 constructDisplayImages(); 00115 } 00116 //============================================== 00117 void SelectionInterface::constructDisplayImages() 00118 { 00119 //rescale image to fit on screen 00120 scaledImage = fullScreenImage.scale( width(), height(), QImage::ScaleMin ); 00121 00122 //construct an unselected scaled image 00123 unselectedScaledImage = scaledImage.copy(); 00124 int x, y; 00125 QRgb* rgb; 00126 uchar* scanLine; 00127 for( y=0; y<unselectedScaledImage.height(); y++) 00128 { 00129 //iterate over each selected pixel in scanline 00130 scanLine = unselectedScaledImage.scanLine(y); 00131 for( x=0; x<unselectedScaledImage.width(); x++) 00132 { 00133 //compress dynamic range to 25% of original 00134 rgb = ((QRgb*)scanLine+x); 00135 00136 double r = ((double)qRed(*rgb) )/255.0; 00137 double g = ((double)qGreen(*rgb) )/255.0; 00138 double b = ((double)qBlue(*rgb) )/255.0; 00139 00140 //convert to hsv 00141 double h,s,v; 00142 RGBtoHSV(r,g,b,&h,&s,&v); 00143 00144 //scale and clamp v 00145 v*=0.25; 00146 00147 //convert adjusted color back to rgb colorspace and clamp 00148 HSVtoRGB( &r,&g,&b, h,s,v); 00149 int rp = (int) QMIN( QMAX((r*255), 0), 255 ); 00150 int gp = (int) QMIN( QMAX((g*255), 0), 255 ); 00151 int bp = (int) QMIN( QMAX((b*255), 0), 255 ); 00152 00153 //set adjusted color value 00154 *rgb = qRgb(rp,gp,bp); 00155 } 00156 } 00157 00158 00159 } 00160 //============================================== 00161 void SelectionInterface::paintEvent(QPaintEvent *e) 00162 { 00163 //if no scaled image just return 00164 if(scaledImage.isNull()) { return; } 00165 00166 //create buffer to draw in 00167 QRect rct = rect(); 00168 rct.moveBy(-x(), -y()); 00169 QPixmap buffer( size() ); 00170 00171 //create a painter pointing to the buffer 00172 QPainter bufferPainter( &buffer ); 00173 00174 //turn off clipping to make painting operations faster 00175 bufferPainter.setClipping(false); 00176 00177 //initialize buffer with background brush 00178 bufferPainter.fillRect( buffer.rect(), backgroundBrush() ); 00179 00180 //paint the image 00181 int xOffset = (width() - scaledImage.width()) / 2; 00182 int yOffset = (height() - scaledImage.height()) / 2; 00183 00184 //if in draw line mode paint the image normall and then the currently selected line 00185 //if the two points are set 00186 if(currentDragMode == DRAW_LINE) 00187 { 00188 //paint entire image normally 00189 bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage ); 00190 00191 //if the first and 2nd points have been set draw the line as well 00192 if( mousePressPoint.x() != -1 && 00193 mouseDragPoint.x() != -1 ) 00194 { 00195 //get points in display space 00196 QPoint p1, p2; 00197 p1 = ConvertImageToDisplayCoordinate( mousePressPoint ); 00198 p2 = ConvertImageToDisplayCoordinate( mouseDragPoint ); 00199 00200 //setup painter to use green color 00201 QPen pen; 00202 pen.setStyle( Qt::SolidLine ); 00203 pen.setCapStyle( Qt::RoundCap ); 00204 pen.setWidth( 2 ); 00205 pen.setColor( green ); 00206 bufferPainter.setPen( pen); 00207 00208 //draw line 00209 bufferPainter.drawLine( p1.x(), p1.y(), p2.x(), p2.y() ); 00210 } 00211 } 00212 //else we're in normal selection mode 00213 else 00214 { 00215 //if selected region is empty paint entire image in color 00216 if( mousePressPoint.x() == -1 || 00217 ( 00218 currentDragMode == NO_EFFECT && 00219 ( 00220 mousePressPoint.x() - mouseDragPoint.x() == 0 || 00221 mousePressPoint.y() - mouseDragPoint.y() == 0 00222 ) 00223 )) 00224 { 00225 bufferPainter.drawImage( QPoint(xOffset, yOffset), scaledImage ); 00226 } 00227 //otherwise paint using a two-pass approach, 00228 //first in monochrome and then the selected region in color 00229 else 00230 { 00231 //first paint using unselected coloring 00232 bufferPainter.drawImage( QPoint(xOffset, yOffset), unselectedScaledImage ); 00233 00234 //construct topLeft and bottomRight points to make logic easier 00235 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00236 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00237 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00238 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00239 00240 //convert coordinates from original image space to display space 00241 topLeft = ConvertImageToDisplayCoordinate( topLeft ); 00242 bottomRight = ConvertImageToDisplayCoordinate( bottomRight ); 00243 00244 //now paint selected region in color 00245 bufferPainter.drawImage( topLeft.x(), 00246 topLeft.y(), 00247 scaledImage, 00248 topLeft.x()-xOffset, topLeft.y()-yOffset, 00249 bottomRight.x() - topLeft.x(), 00250 bottomRight.y() - topLeft.y() ); 00251 00252 //determine color for painting selection rectangle and dimensions 00253 //use gray/white if cropping to a custom size (and thus real world dimensions 00254 //are not known). If the crop size is known (eg 5"x7") use green if above 00255 //resolution is great enough, otherwise use red to indicate that cropping to 00256 //the specified size will result in pixelation during printing 00257 QPen pen; 00258 QColor selectionColor = gray; 00259 QColor textColor = white; 00260 int selectedWidth = QABS( mouseDragPoint.x() - mousePressPoint.x() ) + 1; 00261 int selectedHeight = QABS( mouseDragPoint.y() - mousePressPoint.y() ) + 1; 00262 if(selectedWidth == 1) selectedWidth = 0; 00263 if(selectedHeight == 1) selectedHeight = 0; 00264 00265 int DPI = -1; 00266 int minDPI = -1; 00267 if( cropMaxDimen != -1.0 ) 00268 { 00269 //compute DPI that will be used in dominant direction 00270 int maxDimen = QMAX( selectedWidth, selectedHeight ); 00271 DPI = (int) (maxDimen / cropMaxDimen); 00272 00273 //if DPI is below minimum use red color for selection rectangle to indicate pixalation may occur 00274 minDPI = ((Window*)qApp->mainWidget())->getConfig()->getInt( "misc", "minDPI" ); 00275 if( DPI < minDPI ) 00276 { selectionColor = QColor( 200, 0, 0 ); } 00277 //otherwise use green to signal cropping to this size is safe 00278 else { selectionColor = QColor( 0, 200, 0 ); } 00279 } 00280 pen.setStyle( Qt::SolidLine ); 00281 pen.setWidth( 2 ); 00282 bufferPainter.setPen( pen); 00283 00284 //paint selection size in lower right corner of selected area 00285 QString selectionText; 00286 if( cropMaxDimen != -1.0 && 00287 DPI < minDPI ) 00288 selectionText = QString("%1 x %2 (DPI: %3!)").arg(selectedWidth).arg(selectedHeight).arg(DPI); 00289 else 00290 selectionText = QString("%1 x %2").arg(selectedWidth).arg(selectedHeight); 00291 00292 QFontMetrics fm( this->font() ); 00293 int stringWidth = fm.width(selectionText); 00294 int stringHeight = fm.ascent(); 00295 00296 int textX = 0; 00297 int textY = 0; 00298 const int TEXT_MARGIN = 4; 00299 if( mouseDragPoint.x() > mousePressPoint.x() ) 00300 { 00301 textX = QMIN( xOffset + unselectedScaledImage.width() - TEXT_MARGIN - stringWidth, 00302 bottomRight.x() + TEXT_MARGIN ); 00303 } 00304 else 00305 { 00306 textX = QMAX( xOffset + TEXT_MARGIN, 00307 topLeft.x() - TEXT_MARGIN - stringWidth ); 00308 } 00309 00310 if( mouseDragPoint.y() > mousePressPoint.y() ) 00311 { 00312 textY = QMIN( yOffset + unselectedScaledImage.height() - TEXT_MARGIN, 00313 bottomRight.y() + TEXT_MARGIN + stringHeight); 00314 } 00315 else 00316 { 00317 textY = QMAX( yOffset + TEXT_MARGIN + stringHeight, 00318 topLeft.y() - TEXT_MARGIN ); 00319 } 00320 00321 //paint a thin outline around the selection 00322 pen.setColor( selectionColor ); 00323 bufferPainter.setPen( pen); 00324 QRect selection( topLeft, bottomRight ); 00325 bufferPainter.drawRect(selection); 00326 00327 //paint image under selected dimension using selected coloring to help make it more visible 00328 bufferPainter.drawImage( textX, textY-stringHeight, 00329 unselectedScaledImage, 00330 textX - xOffset, textY-stringHeight-yOffset, 00331 stringWidth, fm.height() ); 00332 00333 00334 //paint selected dimensions 00335 pen.setColor( textColor ); 00336 bufferPainter.setPen( pen); 00337 bufferPainter.drawText( textX, textY, selectionText ); 00338 } 00339 } 00340 00341 bufferPainter.end(); 00342 00343 //blit buffer to screen 00344 bitBlt( this, 00345 e->rect().x(), e->rect().y(), 00346 &buffer, 00347 e->rect().x(), e->rect().y(), 00348 e->rect().width(), e->rect().height() ); 00349 } 00350 //============================================== 00351 DRAG_MODE SelectionInterface::mouseActionByPosition(QPoint p) 00352 { 00353 //If SHIFT_Pressed is set then scaling a selection 00354 if(SHIFT_Pressed) { return SCALE_SELECTION; } 00355 00356 //construct topLeft and bottomRight points to make logic easier 00357 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00358 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00359 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00360 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00361 00362 //convert selelection bounary to display space since thresholds are all in display space 00363 topLeft = ConvertImageToDisplayCoordinate( topLeft ); 00364 bottomRight = ConvertImageToDisplayCoordinate( bottomRight ); 00365 00366 //compute selection center 00367 QPoint center( (topLeft.x() + bottomRight.x()) / 2, 00368 (topLeft.y() + bottomRight.y()) / 2); 00369 00370 //if pointer is not over image no effect will occur when clicking 00371 int xOffset = (width() - scaledImage.width() ) / 2; 00372 int yOffset = (height() - scaledImage.height() ) / 2; 00373 if(p.x() < xOffset || p.x() >= scaledImage.width() + xOffset || 00374 p.y() < yOffset || p.y() >= scaledImage.height() + yOffset ) 00375 { return NO_EFFECT; } 00376 00377 //if either there is no selection or the entire image is selected, new 00378 //mouse clicks are interpreted as being for selecting new regions 00379 if( mousePressPoint.x() == -1 || 00380 ( bottomRight.x() - topLeft.x() == origImageSize.width() - 1 && 00381 bottomRight.y() - topLeft.y() == origImageSize.height() - 1 ) 00382 ) 00383 { return DRAW_SELECTION; } 00384 //move entire selection 00385 //mouse is within MOVE_THRESH of center and outside 00386 //DRAG_THRESH of any side 00387 else if( p.x() >= QMAX( center.x() - MOVE_THRESHOLD, topLeft.x() ) && 00388 p.x() <= QMIN( center.x() + MOVE_THRESHOLD, bottomRight.x() ) && 00389 p.y() >= QMAX( center.y() - MOVE_THRESHOLD, topLeft.y() ) && 00390 p.y() <= QMIN( center.y() + MOVE_THRESHOLD, bottomRight.y() ) && 00391 p.x() > topLeft.x() + DRAG_THRESHOLD && 00392 p.x() < bottomRight.x() - DRAG_THRESHOLD && 00393 p.y() > topLeft.y() + DRAG_THRESHOLD && 00394 p.y() < bottomRight.y() - DRAG_THRESHOLD ) 00395 { return MOVE_SELECTION; } 00396 //drag top left 00397 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD && 00398 QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD ) 00399 { return MOVE_TOP_LEFT_CORNER; } 00400 //drag top right 00401 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD && 00402 QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD ) 00403 { return MOVE_TOP_RIGHT_CORNER; } 00404 //drag bottom left 00405 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD && 00406 QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD ) 00407 { return MOVE_BOTTOM_LEFT_CORNER; } 00408 //drag bottom right 00409 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD && 00410 QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD ) 00411 { return MOVE_BOTTOM_RIGHT_CORNER; } 00412 //drag left 00413 else if( QABS(topLeft.x() - p.x()) <= DRAG_THRESHOLD && 00414 p.y() >= topLeft.y() && 00415 p.y() <= bottomRight.y() ) 00416 { return MOVE_LEFT_SIDE; } 00417 //drag right 00418 else if( QABS(bottomRight.x() - p.x()) <= DRAG_THRESHOLD && 00419 p.y() >= topLeft.y() && 00420 p.y() <= bottomRight.y() ) 00421 { return MOVE_RIGHT_SIDE; } 00422 //drag top 00423 else if( QABS(topLeft.y() - p.y()) <= DRAG_THRESHOLD && 00424 p.x() >= topLeft.x() && 00425 p.x() <= bottomRight.x() ) 00426 { return MOVE_TOP_SIDE; } 00427 //drag bottom 00428 else if( QABS(bottomRight.y() - p.y()) <= DRAG_THRESHOLD && 00429 p.x() >= topLeft.x() && 00430 p.x() <= bottomRight.x() ) 00431 { return MOVE_BOTTOM_SIDE; } 00432 //else new selection 00433 else { return DRAW_SELECTION; } 00434 } 00435 //============================================== 00436 void SelectionInterface::mousePressEvent(QMouseEvent *e) 00437 { 00438 //If CTRL pressed then emit ctrlClick event 00439 if( CTRL_Pressed) 00440 { 00441 emit ctrlClick(); 00442 return; 00443 } 00444 00445 //get mouse position in original image coordinates 00446 QPoint p = ConvertDisplayToImageCoordinate( e->pos() ); 00447 00448 //in draw line mode a mouse press has not immediate effect, 00449 //mouse release is how a point is finally selected 00450 if( currentDragMode == DRAW_LINE ) 00451 { return; } 00452 00453 //construct topLeft and bottomRight points to make logic easier 00454 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00455 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00456 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00457 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00458 00459 //determine action mouse click will cause 00460 currentDragMode = mouseActionByPosition(e->pos()); 00461 00462 switch(currentDragMode) 00463 { 00464 case DRAW_SELECTION: 00465 mousePressPoint = p; 00466 mouseDragPoint = p; 00467 cropMaxDimen = -1.0; 00468 emit aspectRatioChanged(); 00469 break; 00470 case MOVE_SELECTION: 00471 //nothing done until mouse moves 00472 break; 00473 case MOVE_TOP_LEFT_CORNER: 00474 mousePressPoint = bottomRight; 00475 mouseDragPoint = topLeft; 00476 break; 00477 case MOVE_BOTTOM_RIGHT_CORNER: 00478 mousePressPoint = topLeft; 00479 mouseDragPoint = bottomRight; 00480 break; 00481 case MOVE_TOP_RIGHT_CORNER: 00482 mousePressPoint = QPoint( topLeft.x(), bottomRight.y() ); 00483 mouseDragPoint = QPoint( bottomRight.x(), topLeft.y() ); 00484 break; 00485 case MOVE_BOTTOM_LEFT_CORNER: 00486 mousePressPoint = QPoint( bottomRight.x(), topLeft.y() ); 00487 mouseDragPoint = QPoint( topLeft.x(), bottomRight.y() ); 00488 break; 00489 case MOVE_LEFT_SIDE: 00490 mousePressPoint = bottomRight; 00491 mouseDragPoint = topLeft; 00492 break; 00493 case MOVE_RIGHT_SIDE: 00494 mousePressPoint = topLeft; 00495 mouseDragPoint = bottomRight; 00496 break; 00497 case MOVE_TOP_SIDE: 00498 mousePressPoint = bottomRight; 00499 mouseDragPoint = topLeft; 00500 break; 00501 case MOVE_BOTTOM_SIDE: 00502 mousePressPoint = topLeft; 00503 mouseDragPoint = bottomRight; 00504 break; 00505 //no effect 00506 default: 00507 return; 00508 } 00509 00510 //repaint the selection 00511 repaint(false); 00512 emit selectionChanged(); 00513 } 00514 //============================================== 00515 void SelectionInterface::updateCursorShape( QPoint rawP ) 00516 { 00517 //if resizing a selection always use size all cursor 00518 if(SHIFT_Pressed) 00519 { 00520 setCursor( getCursor(SCALE_SELECTION_CURSOR) ); 00521 return; 00522 } 00523 00524 //if ctrl pressed show rotate selection cursor 00525 if(CTRL_Pressed) 00526 { 00527 setCursor( getCursor(ROTATE_CURSOR) ); 00528 return; 00529 } 00530 00531 //if selecting a line the cursor is always the same 00532 if( currentDragMode == DRAW_LINE ) 00533 { 00534 setCursor( getCursor(TARGET_CURSOR) ); 00535 return; 00536 } 00537 00538 //update mouse cursor based on coordinates 00539 currentMouseShape = mouseActionByPosition( rawP ); 00540 switch(currentMouseShape) 00541 { 00542 case DRAW_SELECTION: 00543 setCursor( getCursor(CROSS_CURSOR) ); break; 00544 case MOVE_SELECTION: 00545 setCursor( getCursor(MOVE_SELECTION_CURSOR) ); break; 00546 case MOVE_TOP_LEFT_CORNER: 00547 case MOVE_BOTTOM_RIGHT_CORNER: 00548 setCursor( getCursor(MOVE_TL_CURSOR) ); break; 00549 case MOVE_TOP_RIGHT_CORNER: 00550 case MOVE_BOTTOM_LEFT_CORNER: 00551 setCursor( getCursor(MOVE_TR_CURSOR) ); break; 00552 case MOVE_LEFT_SIDE: 00553 case MOVE_RIGHT_SIDE: 00554 setCursor( getCursor(MOVE_HOR_CURSOR) ); break; 00555 case MOVE_TOP_SIDE: 00556 case MOVE_BOTTOM_SIDE: 00557 setCursor( getCursor(MOVE_VERT_CURSOR) ); break; 00558 break; 00559 default: 00560 setCursor( Qt::ArrowCursor ); 00561 break; 00562 } 00563 } 00564 //============================================== 00565 bool SelectionInterface::scaleSelection( int delta ) 00566 { 00567 //construct topLeft and bottomRight points to make logic easier 00568 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00569 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00570 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00571 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00572 00573 //compute new selection dimension 00574 int curSelectionWidth = bottomRight.x() - topLeft.x() + 1; 00575 int curSelectionHeight = bottomRight.y()- topLeft.y() + 1; 00576 int newSelectionWidth = -1; 00577 int newSelectionHeight = -1; 00578 00579 //adjust in dimension of greater resolution 00580 if( curSelectionWidth > curSelectionHeight ) 00581 { 00582 newSelectionWidth = QMIN( curSelectionWidth + delta, origImageSize.width() ); 00583 newSelectionHeight = (newSelectionWidth * cachedSelectionSize.height()) / cachedSelectionSize.width(); 00584 } 00585 else 00586 { 00587 newSelectionHeight = QMIN( curSelectionHeight + delta, origImageSize.height() ); 00588 newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height(); 00589 } 00590 00591 //if selection width or height already maxed out then ignore attempt to make selection bigger 00592 if(delta > 0 && 00593 ( curSelectionWidth == origImageSize.width() || 00594 curSelectionHeight == origImageSize.height() ) ) 00595 { 00596 return false; 00597 } 00598 00599 //again prevent from growing too big, now along y-axis 00600 if(newSelectionHeight > origImageSize.height()) 00601 { 00602 newSelectionHeight = origImageSize.height(); 00603 newSelectionWidth = (newSelectionHeight * cachedSelectionSize.width()) / cachedSelectionSize.height(); 00604 } 00605 00606 //prevent selection becoming empty 00607 if(newSelectionWidth <= 0 || newSelectionHeight <= 0) 00608 { 00609 newSelectionWidth = curSelectionWidth; 00610 newSelectionHeight = curSelectionHeight; 00611 } 00612 00613 //center new selection over current selection , move if necessary 00614 topLeft = QPoint(QMAX( cachedSelctionCenter.x() - newSelectionWidth/2, 0 ), 00615 QMAX( cachedSelctionCenter.y() - newSelectionHeight/2, 0 )); 00616 bottomRight = QPoint( topLeft.x() + newSelectionWidth - 1, 00617 topLeft.y() + newSelectionHeight - 1 ); 00618 00619 //too far right 00620 if(bottomRight.x() > origImageSize.width() - 1 ) 00621 { 00622 int diff = bottomRight.x() - (origImageSize.width() - 1); 00623 topLeft.setX( topLeft.x() - diff ); 00624 bottomRight.setX( bottomRight.x() - diff ); 00625 00626 //recompute center 00627 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00628 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00629 } 00630 00631 //too far down 00632 if(bottomRight.y() > origImageSize.height() - 1 ) 00633 { 00634 int diff = bottomRight.y() - (origImageSize.height() - 1); 00635 topLeft.setY( topLeft.y() - diff ); 00636 bottomRight.setY( bottomRight.y() - diff ); 00637 00638 //recompute center 00639 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00640 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00641 } 00642 00643 //set new selection 00644 mousePressPoint = topLeft; 00645 mouseDragPoint = bottomRight; 00646 00647 //success 00648 return true; 00649 } 00650 //============================================== 00651 void SelectionInterface::mouseMoveEvent(QMouseEvent *e) 00652 { 00653 //if the SHIFT_Pressed state variable is true but SHIFT is now not pressed 00654 //reset bool and mouse cursor! 00655 if( SHIFT_Pressed && !(e->state() & Qt::ShiftButton) ) 00656 { 00657 SHIFT_Pressed = false; 00658 updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) ); 00659 } 00660 00661 //if the CTRL_Pressed state variable is true but CTRL is now not pressed 00662 //reset bool and mouse cursor! 00663 if( CTRL_Pressed && !(e->state() & Qt::ControlButton) ) 00664 { 00665 CTRL_Pressed = false; 00666 updateCursorShape( ConvertImageToDisplayCoordinate( e->pos() ) ); 00667 } 00668 00669 //if mouse not pressed update mouse cursor if 00670 //mode will change if user presses mouse button 00671 if(currentDragMode == NO_EFFECT) 00672 { 00673 //only update the mouse cursor shape if it will change 00674 if( mouseActionByPosition( e->pos() ) != currentMouseShape ) 00675 updateCursorShape( e->pos() ); 00676 00677 cachedMousePosition = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) ); 00678 } 00679 //if currently in draw line mode update the selected line 00680 else if(currentDragMode == DRAW_LINE) 00681 { 00682 //if the 1st point hasn't been set yet do nothing 00683 if( mousePressPoint.x() == -1 ) 00684 return; 00685 00686 //1st point set, set 2nd point to current mouse position and redraw 00687 mouseDragPoint = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) ); 00688 00689 //repaint the line 00690 repaint(false); 00691 } 00692 //update selection rectangle or selected line 00693 else 00694 { 00695 //get mouse position in original image coordinates 00696 QPoint p = ConvertDisplayToImageCoordinate( cropSelectedPoint(e->pos()) ); 00697 00698 //construct topLeft and bottomRight points to make logic easier 00699 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00700 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00701 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00702 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00703 00704 //if SHIFT pressed and both selction dimensions non-empty then scale selection 00705 if(SHIFT_Pressed && 00706 bottomRight.x() > topLeft.x() && 00707 bottomRight.y() > topLeft.y() ) 00708 { 00709 //update width, prevent from growing beyond image boundaries 00710 int delta = p.x() - cachedMousePosition.x(); 00711 if( !scaleSelection( delta ) ) 00712 { 00713 //cache the current mouse position before returning without change 00714 cachedMousePosition = p; 00715 return; 00716 } 00717 } 00718 //if draging the entire selection, update x and y coordinates for 00719 //both mousePress and mouseDrag points and update the dragSelectionPoint 00720 else if( currentDragMode == MOVE_SELECTION ) 00721 { 00722 //compute offset 00723 QPoint offset( p.x() - cachedMousePosition.x(), 00724 p.y() - cachedMousePosition.y() ); 00725 00726 //construct topLeft and bottomRight points to make logic easier 00727 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00728 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00729 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00730 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00731 00732 //clip offset so selected area is always within image boundaries 00733 00734 //left 00735 if(offset.x() < 0 && topLeft.x() + offset.x() < 0 ) 00736 offset.setX( -topLeft.x() ); 00737 00738 //right 00739 if(offset.x() > 0 && bottomRight.x() + offset.x() >= origImageSize.width() ) 00740 offset.setX( origImageSize.width() - 1 - bottomRight.x() ); 00741 00742 //top 00743 if(offset.y() < 0 && topLeft.y() + offset.y() < 0 ) 00744 offset.setY( -topLeft.y() ); 00745 00746 //bottom 00747 if(offset.y() > 0 && bottomRight.y() + offset.y() >= origImageSize.height() ) 00748 offset.setY( origImageSize.height() - 1 - bottomRight.y() ); 00749 00750 //update press and drag points 00751 mousePressPoint+= offset; 00752 mouseDragPoint+= offset; 00753 00754 //recompute selection center 00755 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00756 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00757 } 00758 //if moving any corner or drawing the original selection, 00759 //update x and y coords of drag point 00760 else if( currentDragMode == DRAW_SELECTION || 00761 currentDragMode == MOVE_TOP_LEFT_CORNER || 00762 currentDragMode == MOVE_TOP_RIGHT_CORNER || 00763 currentDragMode == MOVE_BOTTOM_LEFT_CORNER || 00764 currentDragMode == MOVE_BOTTOM_RIGHT_CORNER ) 00765 { 00766 mouseDragPoint.setX( p.x() ); 00767 mouseDragPoint.setY( p.y() ); 00768 cropMaxDimen = -1.0; 00769 00770 //cache selection size and center, necessary for computing next size 00771 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1, 00772 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1); 00773 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00774 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00775 00776 00777 emit aspectRatioChanged(); 00778 } 00779 //else if moving the left or right sides just update the x coordinate of 00780 //the drag point 00781 else if( currentDragMode == MOVE_LEFT_SIDE || 00782 currentDragMode == MOVE_RIGHT_SIDE ) 00783 { 00784 mouseDragPoint.setX( p.x() ); 00785 cropMaxDimen = -1.0; 00786 emit aspectRatioChanged(); 00787 00788 //cache selection size and center, necessary for computing next size 00789 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1, 00790 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1); 00791 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00792 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00793 } 00794 //else if moving the top or bottom sides just update the x coordinate of 00795 //the drag point 00796 else if( currentDragMode == MOVE_TOP_SIDE || 00797 currentDragMode == MOVE_BOTTOM_SIDE ) 00798 { 00799 mouseDragPoint.setY( p.y() ); 00800 cropMaxDimen = -1.0; 00801 emit aspectRatioChanged(); 00802 00803 //cache selection size and center, necessary for computing next size 00804 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1, 00805 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1); 00806 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00807 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00808 00809 } 00810 00811 //cache current mouse position 00812 cachedMousePosition = p; 00813 00814 //repaint the selection 00815 repaint(false); 00816 emit selectionChanged(); 00817 00818 //only update the mouse cursor shape if it will change 00819 if( mouseActionByPosition( e->pos() ) != currentMouseShape ) 00820 updateCursorShape( e->pos() ); 00821 } 00822 } 00823 //============================================== 00824 void SelectionInterface::mouseReleaseEvent(QMouseEvent *e) 00825 { 00826 //if in draw line mode 00827 if( currentDragMode == DRAW_LINE ) 00828 { 00829 //get mouse location in image space 00830 QPoint p = ConvertDisplayToImageCoordinate( e->pos() ); 00831 00832 //if first point has not been set set it now 00833 if( mousePressPoint.x() == -1 ) 00834 { 00835 mousePressPoint = p; 00836 repaint(false); 00837 } 00838 //else first point has been set then we're setting the 2nd point, emit the selected line 00839 else 00840 { 00841 //get two points on line 00842 QPoint p1 = mousePressPoint; 00843 QPoint p2 = p; 00844 00845 //reset mode, press and drag points so there is no selection 00846 currentDragMode = NO_EFFECT; 00847 selectNone(); 00848 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 00849 00850 //emit the selected line 00851 emit lineSelected( p1, p2 ); 00852 } 00853 return; 00854 } 00855 00856 //disable move moving from having an effect on the selection 00857 currentDragMode = NO_EFFECT; 00858 00859 //construct topLeft and bottomRight points to make logic easier 00860 QPoint topLeft( QMIN(mousePressPoint.x(), mouseDragPoint.x()), 00861 QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 00862 QPoint bottomRight( QMAX(mousePressPoint.x(), mouseDragPoint.x()), 00863 QMAX(mousePressPoint.y(), mouseDragPoint.y()) ); 00864 00865 //convert selection region to display space to check for tiny selections to ignore 00866 topLeft = ConvertImageToDisplayCoordinate( topLeft ); 00867 bottomRight = ConvertImageToDisplayCoordinate( bottomRight ); 00868 00869 //if selection is very small reset to select nothing 00870 if( bottomRight.x() - topLeft.x() + 1 < MINIMUM_SELECTION_SIZE || 00871 bottomRight.y() - topLeft.y() + 1 < MINIMUM_SELECTION_SIZE ) { selectNone(); } 00872 } 00873 //============================================== 00874 QPoint SelectionInterface::ConvertDisplayToImageCoordinate( QPoint p ) 00875 { 00876 QPoint newPoint = p; 00877 00878 //remove display offset 00879 int xOffset = (width() - scaledImage.width() ) / 2; 00880 int yOffset = (height() - scaledImage.height() ) / 2; 00881 newPoint.setX( newPoint.x() - xOffset ); 00882 newPoint.setY( newPoint.y() - yOffset ); 00883 00884 //if coordinate is at max set new value explicitly to avoid roundoff error, 00885 //otherwise scale to full image dimensions 00886 if(newPoint.x() == scaledImage.width() - 1) 00887 newPoint.setX( origImageSize.width() - 1); 00888 else 00889 newPoint.setX( (int) (0.5 + ((double)(newPoint.x() * (origImageSize.width()-1))) / (scaledImage.width()-1) ) ); 00890 00891 if(newPoint.y() == scaledImage.height() - 1) 00892 newPoint.setY( origImageSize.height() - 1); 00893 else 00894 newPoint.setY( (int) (0.5 + ((double)(newPoint.y() * (origImageSize.height()-1))) / (scaledImage.height()-1) ) ); 00895 00896 //return point in image coordinates 00897 return newPoint; 00898 } 00899 //============================================== 00900 QPoint SelectionInterface::ConvertImageToDisplayCoordinate( QPoint p ) 00901 { 00902 QPoint newPoint = p; 00903 00904 //if coordinate is at max set new value explicitly to avoid roundoff error, 00905 //otherwise scale to full image dimensions 00906 if(newPoint.x() == origImageSize.width() - 1) 00907 newPoint.setX( scaledImage.width() - 1); 00908 else 00909 newPoint.setX( (newPoint.x() * (scaledImage.width()-1)) / (origImageSize.width()-1) ); 00910 00911 if(newPoint.y() == origImageSize.height() - 1) 00912 newPoint.setY( scaledImage.height() - 1); 00913 else 00914 newPoint.setY( (newPoint.y() * (scaledImage.height()-1)) / (origImageSize.height()-1) ); 00915 00916 //add display offset 00917 int xOffset = (width() - scaledImage.width() ) / 2; 00918 int yOffset = (height() - scaledImage.height() ) / 2; 00919 newPoint.setX( newPoint.x() + xOffset ); 00920 newPoint.setY( newPoint.y() + yOffset ); 00921 00922 //return point in image coordinates 00923 return newPoint; 00924 } 00925 //============================================== 00926 QPoint SelectionInterface::cropSelectedPoint(QPoint p) 00927 { 00928 int xOffset = (width() - scaledImage.width() ) / 2; 00929 int yOffset = (height() - scaledImage.height() ) / 2; 00930 00931 QPoint croppedPoint; 00932 croppedPoint.setX( QMIN( QMAX(xOffset, p.x()), xOffset + scaledImage.width() - 1 ) ); 00933 croppedPoint.setY( QMIN( QMAX(yOffset, p.y()), yOffset + scaledImage.height() - 1 ) ); 00934 return croppedPoint; 00935 } 00936 //============================================== 00937 bool SelectionInterface::selectionEmpty() 00938 { 00939 return ( 00940 mousePressPoint.x() == -1 || 00941 mouseDragPoint.x() - mousePressPoint.x() == 0 || 00942 mouseDragPoint.y() - mousePressPoint.y() == 0 00943 ); 00944 } 00945 //============================================== 00946 void SelectionInterface::selectAll() 00947 { 00948 mousePressPoint.setX( 0 ); 00949 mousePressPoint.setY( 0 ); 00950 mouseDragPoint.setX( origImageSize.width() - 1 ); 00951 mouseDragPoint.setY( origImageSize.height() - 1); 00952 00953 //cache selection size and center, necessary for computing next size 00954 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1, 00955 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1); 00956 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00957 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00958 00959 cropMaxDimen = -1.0; 00960 repaint(false); 00961 emit selectionChanged(); 00962 emit aspectRatioChanged(); 00963 } 00964 //============================================== 00965 void SelectionInterface::selectNone() 00966 { 00967 mousePressPoint = QPoint(-1,-1); 00968 mouseDragPoint = QPoint(-1,-1); 00969 cropMaxDimen = -1.0; 00970 repaint(false); 00971 emit selectionChanged(); 00972 emit aspectRatioChanged(); 00973 } 00974 //============================================== 00975 void SelectionInterface::setSelection(QPoint topLeft, QPoint bottomRight, 00976 double cropMaxDimen) 00977 { 00978 mousePressPoint = topLeft; 00979 mouseDragPoint = bottomRight; 00980 00981 this->cropMaxDimen = cropMaxDimen; 00982 00983 //cache selection size and center, necessary for computing next size 00984 cachedSelectionSize = QSize( QABS( mouseDragPoint.x() - mousePressPoint.x() )+1, 00985 QABS( mouseDragPoint.y() - mousePressPoint.y() )+1); 00986 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 00987 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 00988 00989 repaint(false); 00990 emit selectionChanged(); 00991 } 00992 //============================================== 00993 void SelectionInterface::getSelection(QPoint &topLeft, QPoint &bottomRight) 00994 { 00995 //if none selected just return immediately 00996 if(mousePressPoint.x() == -1) 00997 { 00998 topLeft.setX(-1); topLeft.setY(-1); 00999 bottomRight.setX(-1); bottomRight.setY(-1); 01000 return; 01001 } 01002 01003 //set coordinates based on raw selection 01004 topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) ); 01005 topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 01006 bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) ); 01007 bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) ); 01008 } 01009 //============================================== 01010 void SelectionInterface::getDisplaySize(int &width, int &height) 01011 { 01012 width = scaledImage.width(); 01013 height = scaledImage.height(); 01014 } 01015 //============================================== 01016 void SelectionInterface::keyPressEvent(QKeyEvent *e) 01017 { 01018 //if currently drawing a line, allow the user 01019 //to escape the current acction by hiting escape, all other 01020 //key presses are ignored 01021 if( currentDragMode == DRAW_LINE ) 01022 { 01023 if(e->key() == Qt::Key_Escape ) 01024 { 01025 //reset mode, press and drag points so there is no selection, and mouse cursor 01026 currentDragMode = NO_EFFECT; 01027 selectNone(); 01028 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01029 01030 //emit an invalid line 01031 emit lineSelected( QPoint(-1,-1), QPoint(-1,-1) ); 01032 } 01033 01034 return; 01035 } 01036 01037 //if user pressed SHIFT button and selection non-empty 01038 //then note state change, 01039 //this will effect resizing selections during drag events 01040 if(e->key() == Qt::Key_Shift && !selectionEmpty() ) 01041 { 01042 SHIFT_Pressed = true; 01043 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01044 return; 01045 } 01046 01047 //if user pressed CTRL button and selection non-empty 01048 //then note state change, 01049 //this will effect mouse clicks by rotating the current selection 01050 if(e->key() == Qt::Key_Control && !selectionEmpty() && !SHIFT_Pressed ) 01051 { 01052 CTRL_Pressed = true; 01053 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01054 return; 01055 } 01056 01057 //ignore keypress if selection is empty 01058 if(mousePressPoint.x() == -1 || 01059 mousePressPoint.x() - mouseDragPoint.x() == 0 || 01060 mousePressPoint.y() - mouseDragPoint.y() == 0) 01061 { 01062 e->ignore(); 01063 return; 01064 } 01065 01066 //ignore keypresses while mouse button is down since 01067 //intended behavious is unclear 01068 if( currentDragMode != NO_EFFECT ) 01069 { 01070 e->ignore(); 01071 return; 01072 } 01073 01074 //------- 01075 //if += / -_ keys are pressed scale selection 01076 if( e->key() == Qt::Key_Plus || 01077 e->key() == Qt::Key_Equal || 01078 e->key() == Qt::Key_Minus || 01079 e->key() == Qt::Key_Underscore ) 01080 { 01081 int delta = 2*QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width(); 01082 01083 delta = 1; 01084 01085 //negate delta if decreasing size 01086 if( e->key() == Qt::Key_Minus || 01087 e->key() == Qt::Key_Underscore ) 01088 delta = -delta; 01089 01090 if( scaleSelection( delta ) ) 01091 { 01092 //repaint the selection 01093 repaint(false); 01094 emit selectionChanged(); 01095 } 01096 return; 01097 } 01098 //------- 01099 01100 //find topleft and bottom right of current selection 01101 QPoint topLeft, bottomRight; 01102 topLeft.setX( QMIN(mousePressPoint.x(), mouseDragPoint.x()) ); 01103 topLeft.setY( QMIN(mousePressPoint.y(), mouseDragPoint.y()) ); 01104 bottomRight.setX( QMAX( mousePressPoint.x(), mouseDragPoint.x()) ); 01105 bottomRight.setY( QMAX( mousePressPoint.y(), mouseDragPoint.y()) ); 01106 01107 //compute the number of pixels in the image correspond to one display pixel 01108 //this is the unit by which the selection will be moved 01109 int moveBy = 0; 01110 if( e->key() == Qt::Key_Left || 01111 e->key() == Qt::Key_Right ) 01112 { 01113 moveBy = QMAX( origImageSize.width(), scaledImage.width() ) / scaledImage.width(); 01114 } 01115 else 01116 { 01117 moveBy = QMAX( origImageSize.height(), scaledImage.height() ) / scaledImage.height(); 01118 } 01119 01120 //boundary checked moved by value. must be decalred outside switch statement below 01121 int dx = 0; 01122 int dy = 0; 01123 switch( e->key() ) 01124 { 01125 case Qt::Key_Left: 01126 dx = QMAX( topLeft.x() - moveBy, 0) - topLeft.x(); 01127 break; 01128 case Qt::Key_Right: 01129 dx = QMIN( bottomRight.x() + moveBy, origImageSize.width() - 1) - bottomRight.x(); 01130 break; 01131 case Qt::Key_Up: 01132 dy = QMAX( topLeft.y() - moveBy, 0) - topLeft.y(); 01133 break; 01134 case Qt::Key_Down: 01135 dy = QMIN( bottomRight.y() + moveBy, origImageSize.height() - 1) - bottomRight.y(); 01136 break; 01137 default: 01138 e->ignore(); 01139 return; 01140 } 01141 01142 //shift by dx 01143 mousePressPoint.setX( mousePressPoint.x() + dx ); 01144 mouseDragPoint.setX( mouseDragPoint.x() + dx ); 01145 01146 //shift by dy 01147 mousePressPoint.setY( mousePressPoint.y() + dy ); 01148 mouseDragPoint.setY( mouseDragPoint.y() + dy ); 01149 01150 //recompute center 01151 cachedSelctionCenter = QPoint( ( mouseDragPoint.x() + mousePressPoint.x() )/2, 01152 ( mouseDragPoint.y() + mousePressPoint.y() )/2 ); 01153 01154 //only bother with repaint and updating cursor shape if shift actually occured 01155 if(dx != 0 || dy != 0) 01156 { 01157 repaint(false); 01158 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01159 } 01160 } 01161 //============================================== 01162 void SelectionInterface::keyReleaseEvent(QKeyEvent *e) 01163 { 01164 //if user released SHIFT button then note state change, 01165 //this will effect resizing selections during drag events 01166 if(e->key() == Qt::Key_Shift) 01167 { 01168 SHIFT_Pressed = false; 01169 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01170 } 01171 //if user released CTRL button then note state change, 01172 //this will effect mouse clicks 01173 else if(e->key() == Qt::Key_Control) 01174 { 01175 CTRL_Pressed = false; 01176 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01177 } 01178 //unhandled key press: pass up the object tree 01179 else { e->ignore(); } 01180 } 01181 //============================================== 01182 void SelectionInterface::enterDrawLineMode() 01183 { 01184 //set the current mode 01185 currentDragMode = DRAW_LINE; 01186 01187 //during draw line mode ignore control and shift keys, they are only useful for adjusting 01188 //selections, not lines 01189 SHIFT_Pressed = false; 01190 CTRL_Pressed = false; 01191 01192 //reset 1st point 01193 mousePressPoint = QPoint( -1, -1 ); 01194 mouseDragPoint = QPoint( -1, -1 ); 01195 01196 //repaint and reset the mouse cursor 01197 updateCursorShape( ConvertImageToDisplayCoordinate(cachedMousePosition) ); 01198 repaint(false); 01199 } 01200 //============================================== 01201

Generated on Sun Mar 4 19:42:56 2007 for AlbumShaper by doxygen 1.3.7