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 //==============================================
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 //==============================================
420  QImage adjustedImage )
421 {
422  this->origImage = origImage;
423  this->adjustedImage = adjustedImage;
424  repaint(false);
425 }
426 //==============================================
428 {
429  this->adjustedImage = adjustedImage;
430  repaint(false);
431 }
432 //==============================================
433 
PREVIEW_MOUSE_MODE mouseMode
current mouse move mode
#define TEXT_INSET
SplitViewInterface(QWidget *parent=0, const char *name=0)
Creates layout.
int width
Definition: blur.cpp:79
PREVIEW_MODE previewMode
Current display setting (adjusted or split screen)
QImage & getOrigImage()
returns orig image object
double displayToWorld(int coordinate)
convert display coordinates to world coordinates (double from 0.0 - 1.0)
bool nearSplitPoint(QPoint p)
determines if mouse is near split point
QString originalString
Original and adjusted strings.
QImage adjustedImage
Scaled adjusted image.
void setImages(QImage origImage, QImage adjustedImage)
const QCursor & getCursor(CUSTOM_CURSOR_TYPE type)
Definition: cursors.cpp:52
virtual QSize minimumSizeHint() const
void mouseReleaseEvent(QMouseEvent *)
void mouseMoveEvent(QMouseEvent *e)
double dragOffset
x (or y) coordinate of split between drawn adjusted and original images
bool forceDrawLabel
Draw original/adjusted lables outside of split view mode?
float * buffer
Definition: blur.cpp:80
void setPreviewMode(PREVIEW_MODE mode, bool forceDrawLabel=false)
Sets preview mode.
PREVIEW_MODE
current preview mode
#define TEXT_BACKGROUND_MARGIN
#define DRAG_THRESHOLD
int worldToDisplay(double coordinate)
convert world coordinates to display coordinates (int from 0 to origImage width-1) ...
QImage origImage
Scaled original image.
void mousePressEvent(QMouseEvent *e)
void paintEvent(QPaintEvent *e)
void setAdjustedImage(QImage adjustedImage)
sets adjusted image and repaints
QFont textFont
Larger font used for drawing text.
PREVIEW_MOUSE_MODE currentMouseShape
current mouse shape.
int height
Definition: blur.cpp:79