AlbumShaper  1.0a3
splitViewInterface.cpp
Go to the documentation of this file.
1 //==============================================
2 // copyright : (C) 2003-2005 by Will Stokes
3 //==============================================
4 // This program is free software; you can redistribute it
5 // and/or modify it under the terms of the GNU General
6 // Public License as published by the Free Software
7 // Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //==============================================
10 
11 //Systemwide includes
12 #include <qpainter.h>
13 #include <qcursor.h>
14 //Added by qt3to4:
15 #include <QPixmap>
16 #include <QMouseEvent>
17 #include <QPaintEvent>
18 
19 //Projectwide includes
20 #include "splitViewInterface.h"
21 #include "../cursors.h"
22 #include "../../backend/tools/imageTools.h"
23 
24 #define TEXT_BACKGROUND_MARGIN 2
25 #define TEXT_INSET 4
26 
27 //a mouse press within DRAG_THRESHOLD will move split point
28 #define DRAG_THRESHOLD 8
29 
30 //==============================================
31 SplitViewInterface::SplitViewInterface( QWidget *parent, const char* name ) :
32  QWidget (parent, name )
33 {
34  //setup split point
35  dragOffset = 0.5;
38 
39  //set default mode to adjusted image
41 
42  //don't force draw labels by default. this is useful when
43  //the user pressed the Ctrl button or other key to toggle between opposite views
44  //and drop down menu for choosing display type disagrees with actuall image being shown.
45  forceDrawLabel = false;
46 
47  //setup strings and fonts
48  originalString = QString( tr("Original") );
49  adjustedString = QString( tr("Adjusted") );
50 
51  textFont = this->font();
52  textFont.setPointSize( textFont.pointSize() + 7 );
53 
54  //watch mouse movements in order to drag selection
55  //watch mouse movements in order to move split point between adjusted and original image
56  setMouseTracking(true);
57 
58  //accept focus when clicked on
59  setFocusPolicy( Qt::ClickFocus );
60 }
61 //==============================================
62 void SplitViewInterface::paintEvent(QPaintEvent *e)
63 {
64  //if orig image not setup yet then return immediately
65  if(origImage.isNull()) { return; }
66 
67  //if viewing adjusted or split view and adjusted image is null bail
68  if(
70  adjustedImage.isNull()
71  )
72  { return; }
73 
74  //create buffer to draw in
75  QPixmap buffer( size() );
76 
77  //create a painter pointing to the buffer
78  QPainter bufferPainter( &buffer );
79 
80  //turn off clipping to make painting operations faster
81  bufferPainter.setClipping(false);
82 
83  //initialize buffer with background brush
84  bufferPainter.fillRect( buffer.rect(), backgroundBrush() );
85 
86  //setup pen color
87  QPen pen;
88  pen.setStyle( Qt::SolidLine );
89  pen.setColor( Qt::white );
90  pen.setWidth( 2 );
91  bufferPainter.setPen( pen);
92 
93  int xOffset = (width() - origImage.width()) / 2;
94  int yOffset = (height() - origImage.height()) / 2;
95 
96  //setup font metrics
97  bufferPainter.setFont( textFont );
98  QFontMetrics fm( textFont );
99 
100  //paint the adjusted image
102  {
103  bufferPainter.drawImage( QPoint(xOffset, yOffset), adjustedImage );
104 
105  //"Adjusted" label
106  if(forceDrawLabel)
107  {
108  int x = xOffset + (origImage.width()-fm.width(adjustedString))/2;
109  int y = yOffset + fm.ascent() + TEXT_INSET;
110 
111  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
112  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
113  fm.width(adjustedString) + 2*TEXT_BACKGROUND_MARGIN,
114  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
115  QBrush(Qt::darkGray) );
116  bufferPainter.drawText( x, y,
117  adjustedString );
118  }
119  }
120  //paint the original image
121  else if(previewMode == ORIGINAL_IMAGE)
122  {
123  bufferPainter.drawImage( QPoint(xOffset, yOffset), origImage );
124 
125  //"Original" label
126  if(forceDrawLabel)
127  {
128  int x = xOffset + (origImage.width()-fm.width(originalString))/2;
129  int y = yOffset + fm.ascent() + TEXT_INSET;
130 
131  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
132  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
133  fm.width(originalString) + 2*TEXT_BACKGROUND_MARGIN,
134  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
135  QBrush(Qt::darkGray) );
136  bufferPainter.drawText( x, y,
137  originalString );
138  }
139  }
140  //if using split view also draw line down center and original image on left
141  else if(previewMode == SPLIT_VIEW ||
143  {
144  //determine what left/right or top/bottom strings are
145  QString label1, label2;
146  if(previewMode == SPLIT_VIEW)
147  {
148  label1 = originalString;
149  label2 = adjustedString;
150  }
151  else
152  {
153  label2 = originalString;
154  label1 = adjustedString;
155  }
156 
157  //find split point in screen coordinates
158  int halfWay = worldToDisplay( dragOffset );
159 
160  //paint the original image
161  bufferPainter.drawImage( QPoint(xOffset, yOffset), origImage );
162 
163  //-------
164  if(origImage.width() > origImage.height() )
165  {
166  //paint the adjusted image
167  if(previewMode == SPLIT_VIEW)
168  {
169  bufferPainter.drawImage( xOffset + halfWay,
170  yOffset,
172  halfWay,0,
173  origImage.width() - halfWay,
174  origImage.height() );
175  }
176  else
177  {
178  bufferPainter.drawImage( xOffset,
179  yOffset,
181  0,0,
182  halfWay,
183  origImage.height() );
184  }
185 
186 
187  //paint white line
188  bufferPainter.drawLine( xOffset + halfWay,
189  yOffset,
190  xOffset + halfWay,
191  yOffset + origImage.height() );
192 
193  //Left label
194  int x = xOffset + (halfWay-fm.width(label1))/2;
195  int y = yOffset + fm.ascent() + TEXT_INSET;
196 
197  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
198  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
199  fm.width(label1) + 2*TEXT_BACKGROUND_MARGIN,
200  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
201  QBrush(Qt::darkGray) );
202  bufferPainter.drawText( x, y,
203  label1 );
204 
205  //Right label
206  x = xOffset + halfWay + (origImage.width() - halfWay - fm.width(label2))/2;
207 
208  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
209  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
210  fm.width(label2) + 2*TEXT_BACKGROUND_MARGIN,
211  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
212  QBrush(Qt::darkGray) );
213  bufferPainter.drawText( x, y,
214  label2 );
215  }
216  //-------
217  else
218  {
219  //paint the adjusted image
220  if(previewMode == SPLIT_VIEW)
221  {
222  bufferPainter.drawImage( xOffset,
223  yOffset + halfWay,
225  0,halfWay,
226  origImage.width(),
227  origImage.height()-halfWay );
228  }
229  else
230  {
231  bufferPainter.drawImage( xOffset,
232  yOffset,
234  0,0,
235  origImage.width(),
236  halfWay );
237  }
238 
239  //paint white line
240  bufferPainter.drawLine( xOffset,
241  yOffset + halfWay,
242  xOffset + origImage.width(),
243  yOffset + halfWay );
244 
245  //Top label
246  int x = xOffset + (origImage.width()-fm.width(label1))/2;
247  int y = yOffset + fm.ascent() + TEXT_INSET;
248 
249  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
250  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
251  fm.width(label1) + 2*TEXT_BACKGROUND_MARGIN,
252  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
253  QBrush(Qt::darkGray) );
254  bufferPainter.drawText( x, y,
255  label1 );
256 
257  //Bottom label
258  x = xOffset + (origImage.width()-fm.width(label2))/2;
259  y = yOffset + halfWay + fm.height();
260 
261  bufferPainter.fillRect( QRect(x - TEXT_BACKGROUND_MARGIN,
262  y - TEXT_BACKGROUND_MARGIN - fm.ascent(),
263  fm.width(label2) + 2*TEXT_BACKGROUND_MARGIN,
264  fm.height() + 2*TEXT_BACKGROUND_MARGIN),
265  QBrush(Qt::darkGray) );
266  bufferPainter.drawText( x, y,
267  label2 );
268  }
269  //-------
270  }
271 
272  //end painter
273  bufferPainter.end();
274 
275  //blit buffer to screen
276  bitBlt( this,
277  e->rect().x(), e->rect().y(),
278  &buffer,
279  e->rect().x(), e->rect().y(),
280  e->rect().width(), e->rect().height() );
281 }
282 //==============================================
283 void SplitViewInterface::setPreviewMode( PREVIEW_MODE mode, bool forceDrawLabel )
284 {
285  //set mode and repaint
286  previewMode = mode;
287  this->forceDrawLabel = forceDrawLabel;
288  repaint(false);
289 }
290 //==============================================
292 {
293  //always false if not in split view mode
294  if( previewMode != SPLIT_VIEW )
295  return false;
296 
297  //compute painting offset and get important mouse coordinate
298  int paintingOffset;
299  int mousePos;
300  if(origImage.width() > origImage.height())
301  {
302  paintingOffset = (width() - origImage.width()) / 2;
303  mousePos = p.x();
304  }
305  else
306  {
307  paintingOffset = (height() - origImage.height()) / 2;
308  mousePos = p.y();
309  }
310 
311  //convert drag offset to display coordinates
312  int displayCoor = worldToDisplay( dragOffset) + paintingOffset;
313 
314  //check if within threshold of split point
315  return ( mousePos > displayCoor - DRAG_THRESHOLD &&
316  mousePos < displayCoor + DRAG_THRESHOLD);
317 }
318 //==============================================
320 {
321  //if within threshold of split point enter drag split mode
322  if( nearSplitPoint(e->pos()) )
324 }
325 //==============================================
327 {
328  //if not dragging split point update mosue cursor
330  {
331  if( !nearSplitPoint(e->pos()) && currentMouseShape == DRAG_SPLIT )
332  {
334  setCursor( Qt::ArrowCursor );
335  }
336  else if( nearSplitPoint(e->pos()) && currentMouseShape == NO_EFFECT_ON_SPLIT )
337  {
339  if( origImage.width() > origImage.height() )
340  {
341  setCursor( getCursor(MOVE_HOR_CURSOR) );
342  }
343  else
344  {
345  setCursor( getCursor(MOVE_VERT_CURSOR) );
346  }
347  }
348 
349  return;
350  }
351 
352  //compute painting offset, get important mouse
353  //coordinate and clamp to valid range
354  QFontMetrics fm( textFont );
355  int paintingOffset;
356  int mousePos;
357  if(origImage.width() > origImage.height())
358  {
359  paintingOffset = (width() - origImage.width()) / 2;
360  mousePos = e->pos().x();
361  mousePos = QMAX( mousePos, paintingOffset + 4*TEXT_BACKGROUND_MARGIN + fm.width(originalString) );
362  mousePos = QMIN( mousePos, paintingOffset + origImage.width() -
364  }
365  else
366  {
367  paintingOffset = (height() - origImage.height()) / 2;
368  mousePos = e->pos().y();
369  mousePos = QMAX( mousePos, paintingOffset + 4*TEXT_BACKGROUND_MARGIN + fm.height() );
370  mousePos = QMIN( mousePos, paintingOffset + origImage.height() -
371  fm.height() - 2*TEXT_BACKGROUND_MARGIN - 2*TEXT_INSET);
372  }
373 
374  //update location of split point and repaint
375  dragOffset = displayToWorld(mousePos - paintingOffset);
376  repaint(false);
377 }
378 //==============================================
380 {
381  //disable dragging
383 
384  //update mouse cursor if necessary
385  if( !nearSplitPoint(e->pos()) && currentMouseShape == DRAG_SPLIT )
386  {
388  setCursor( Qt::ArrowCursor );
389  }
390 }
391 //==============================================
392 double SplitViewInterface::displayToWorld( int coordinate )
393 {
394  if( origImage.width() > origImage.height() )
395  { return ((double) (coordinate+1))/origImage.width(); }
396  else
397  { return ((double) (coordinate+1))/origImage.height(); }
398 }
399 //==============================================
400 int SplitViewInterface::worldToDisplay( double coordinate )
401 {
402  if( origImage.width() > origImage.height() )
403  { return (int) (coordinate*(origImage.width() -1) ); }
404  else
405  { return (int) (coordinate*(origImage.height()-1) ); }
406 }
407 //==============================================
409 {
410  QFontMetrics fm( textFont );
411  int w = 5*TEXT_BACKGROUND_MARGIN + fm.width(originalString) + fm.width(adjustedString);
412  int h = 2*TEXT_BACKGROUND_MARGIN + fm.height();
413  return QSize( w, h );
414 }
415 //==============================================
417 { return origImage; }
418 //==============================================
419 void SplitViewInterface::setImages( QImage origImage,
420  QImage adjustedImage )
421 {
422  this->origImage = origImage;
423  this->adjustedImage = adjustedImage;
424  repaint(false);
425 }
426 //==============================================
427 void SplitViewInterface::setAdjustedImage( QImage adjustedImage )
428 {
429  this->adjustedImage = adjustedImage;
430  repaint(false);
431 }
432 //==============================================
433 
int width
Definition: blur.cpp:79
int height
Definition: blur.cpp:79
float * buffer
Definition: blur.cpp:80
PREVIEW_MOUSE_MODE mouseMode
current mouse move mode
int worldToDisplay(double coordinate)
convert world coordinates to display coordinates (int from 0 to origImage width-1)
virtual QSize minimumSizeHint() const
bool nearSplitPoint(QPoint p)
determines if mouse is near split point
QString originalString
Original and adjusted strings.
double displayToWorld(int coordinate)
convert display coordinates to world coordinates (double from 0.0 - 1.0)
void mousePressEvent(QMouseEvent *e)
bool forceDrawLabel
Draw original/adjusted lables outside of split view mode?
QImage adjustedImage
Scaled adjusted image.
void paintEvent(QPaintEvent *e)
double dragOffset
x (or y) coordinate of split between drawn adjusted and original images
QFont textFont
Larger font used for drawing text.
QImage & getOrigImage()
returns orig image object
void setImages(QImage origImage, QImage adjustedImage)
QImage origImage
Scaled original image.
PREVIEW_MODE previewMode
Current display setting (adjusted or split screen)
SplitViewInterface(QWidget *parent=0, const char *name=0)
Creates layout.
void mouseReleaseEvent(QMouseEvent *)
void mouseMoveEvent(QMouseEvent *e)
void setAdjustedImage(QImage adjustedImage)
sets adjusted image and repaints
PREVIEW_MOUSE_MODE currentMouseShape
current mouse shape.
void setPreviewMode(PREVIEW_MODE mode, bool forceDrawLabel=false)
Sets preview mode.
const QCursor & getCursor(CUSTOM_CURSOR_TYPE type)
Definition: cursors.cpp:52
@ MOVE_VERT_CURSOR
Definition: cursors.h:21
@ MOVE_HOR_CURSOR
Definition: cursors.h:20
#define TEXT_INSET
#define DRAG_THRESHOLD
#define TEXT_BACKGROUND_MARGIN
@ DRAG_SPLIT
@ NO_EFFECT_ON_SPLIT
PREVIEW_MODE
current preview mode
@ SPLIT_VIEW
@ ORIGINAL_IMAGE
@ ADJUSTED_IMAGE
@ INV_SPLIT_VIEW