AlbumShaper  1.0a3
subalbumPreviewWidget.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 <qpixmap.h>
13 #include <qstring.h>
14 #include <qpainter.h>
15 #include <q3iconview.h>
16 #include <qfontmetrics.h>
17 #include <qapplication.h>
18 //Added by qt3to4:
19 #include <QDropEvent>
20 #include <Q3ValueList>
21 
22 //Projectwide includes
23 #include "subalbumPreviewWidget.h"
24 #include "subalbumsIconView.h"
25 #include "../backend/subalbum.h"
26 #include "../backend/photo.h"
27 #include "../backend/tools/imageTools.h"
28 #include "subalbumsWidget.h"
29 #include "layoutWidget.h"
30 #include "subalbumWidget.h"
31 #include "photoPreviewWidget.h"
32 #include "../backend/tools/guiTools.h"
33 
34 #include "../backend/album.h"
35 
36 //==============================================
38  : Q3IconViewItem(parent,
39  clipText( salbum->getName(), 2, parent->getTextWidth()),
40  *salbum->getRepresentativeImage(MEDIUM) )
41 {
42  mousedOver = false;
43  this->parent = parent;
44  subalbum = salbum;
45 
46  //initialize item rectangle
48 }
49 //==============================================
51 {
52  return subalbum;
53 }
54 //==============================================
55 void SubalbumPreviewWidget::paintFocus( QPainter*, const QColorGroup& ) { }
56 //==============================================
57 void SubalbumPreviewWidget::paint( QPainter *p )
58 {
59  paintItem( p, QColorGroup() );
60 }
61 //==============================================
62 void SubalbumPreviewWidget::paintItem( QPainter* p, const QColorGroup&)
63 {
64  QColor lightLightBlue( 152, 180, 226 );
65  QColor darkLightBlue(193, 210, 238);
66  QColor darkBlue(35, 75, 139);
67  QColor background = darkLightBlue;
68 
69  //resize old static buffer to new needed size, fill with widget background color
70  static QPixmap buffer;
71  QRect r = rect();
72  QSize newSize = r.size().expandedTo(buffer.size() );
73  buffer.resize(newSize);
74  buffer.fill( background );
75 
76  //construct painter for buffer
77  QPainter bufferPainter(&buffer);
78  bufferPainter.translate( -r.x(), -r.y() );
79 
80  //turn off clipping to make painting operations faster
81  bufferPainter.setClipping(false);
82 
83  //paint mouse over or actual selection color
84  bool paintRect = false;
85  QColor paintColor;
86  if(isSelected()) { paintColor = darkBlue; paintRect = true; }
87  else if(mousedOver) { paintColor = lightLightBlue; paintRect = true; }
88 
89  if(paintRect)
90  {
91  //first paint alpha blended edges
92 
93  //-------------------------
94  //top and bottom edges
95  QRect r2 = r;
96  r2.setLeft( r.left() + 4);
97  r2.setRight( r.right() - 4);
98  r2.setTop( r.top() );
99  r2.setBottom( r.bottom() );
100  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.40 ) );
101 
102  r2.setLeft( r2.left() + 1);
103  r2.setRight( r2.right() - 1);
104  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.67 ) );
105  //-------------------------
106  //inner top and bottom edges
107  r2.setLeft( r2.left() - 3);
108  r2.setRight( r2.right() + 3);
109  r2.setTop( r2.top() + 1 );
110  r2.setBottom( r2.bottom() - 1);
111  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.40 ) );
112 
113  r2.setLeft( r2.left() + 1);
114  r2.setRight( r2.right() - 1);
115  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.67 ) );
116  //-------------------------
117  //left and right inner edges
118  r2.setLeft( r2.left() - 2);
119  r2.setRight( r2.right() + 2);
120  r2.setTop( r2.top() + 1 );
121  r2.setBottom( r2.bottom() - 1);
122  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.40) );
123 
124  r2.setTop( r2.top() + 1);
125  r2.setBottom( r2.bottom() - 1);
126  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.67) );
127  //-------------------------
128  // middle region
129  r2.setLeft( r2.left() - 1 );
130  r2.setRight( r2.right() + 1 );
131  r2.setTop( r2.top() + 1);
132  r2.setBottom( r2.bottom() - 1);
133  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.40) );
134 
135  r2.setTop( r2.top() + 1);
136  r2.setBottom( r2.bottom() - 1);
137  bufferPainter.fillRect( r2, blendColors( paintColor, background, 0.67) );
138  //-------------------------
139  //second paint inner selection
140  r2 = r;
141  r2.setLeft( r.left() + 1);
142  r2.setRight( r.right() - 1);
143  r2.setTop( r.top() + 4 );
144  r2.setBottom( r.bottom() - 4);
145  bufferPainter.fillRect( r2, paintColor );
146 
147  r2.setLeft( r2.left() + 1);
148  r2.setRight( r2.right() - 1);
149  r2.setTop( r2.top() - 2 );
150  r2.setBottom( r2.bottom() + 2 );
151  bufferPainter.fillRect( r2, paintColor );
152 
153  r2.setLeft( r2.left() + 2);
154  r2.setRight( r2.right() - 2);
155  r2.setTop( r2.top() - 1 );
156  r2.setBottom( r2.bottom() + 1 );
157  bufferPainter.fillRect( r2, paintColor );
158  }
159 
160  //paint pixmap
161  bufferPainter.drawPixmap( x()+4 , y() + 4, *pixmap());
162 
163  //paint text
164  int align = Qt::AlignLeft | Qt::AlignTop | Qt::TextWrapAnywhere;
165  if(isSelected())
166  bufferPainter.setPen( Qt::white );
167  else
168  bufferPainter.setPen( Qt::black );
169  bufferPainter.drawText( x() + 4 + pixmapRect().width(),
170  y() + 4,
171  textRect().width(), textRect().height(),
172  align, text() );
173 
174  //draw buffer to screen
175  p->drawPixmap( x(), y(), buffer );
176 }
177 //==============================================
178 void SubalbumPreviewWidget::dropped( QDropEvent *e, const Q3ValueList<Q3IconDragItem> & )
179 {
180  //if source is not from the application then ignore
181  if(e->source() == NULL)
182  return;
183 
184  //if source of drop event is from this widget when user is attempting to
185  //rearrange subalbums, move currently selected item to
186  //approximately where the cursor is before rearranging items
187  if(e->source()->parentWidget() == parent)
188  {
189  if(e->pos().y() < (y() + (height()/2)))
190  {
191  parent->currentItem()->move(x(), y() - 1);
192  }
193  else
194  {
195  parent->currentItem()->move(x(), y() + (height()/2) + 1);
196  }
197  }
198  //else check to see if user dropped photo(s) on subalbum
199  else
200  {
201  //if the source of the items is the current subalbum icon view and
202  //this is a different subalbum then
203  //move photos from that subalbum to this one
204  if(
205  !isSelected() &&
206  (
207  e->source()->parentWidget() ==
208  ((LayoutWidget*)(parent->parentWidget()->parentWidget()))->getSubalbum()->getPhotos()
209  )
210  )
211  {
212  //iterate over all selected photos, inserting each
213  //into this subalbum, removing from old subalbum,
214  //and deleting old photo widgets
215  SubalbumWidget* oldSubalbumWidget = ((LayoutWidget*)(parent->parentWidget()->parentWidget()))->getSubalbum();
216  Subalbum* oldSubalbum = oldSubalbumWidget->getSubalbum();
217  Q3IconViewItem* current = oldSubalbumWidget->getPhotos()->firstItem();
218  while(current != NULL)
219  {
220  //found a selected photo
221  if(current->isSelected())
222  {
223  //get pointer to photo
224  Photo* photo = ((PhotoPreviewWidget*)current)->getPhoto();
225 
226  //remove photo from that subalbum
227  oldSubalbum->photoMoved(photo);
228 
229  //add photo to this subalbum
230  subalbum->addPhoto(photo);
231 
232  //delete photo widget and rearrange photos
233  Q3IconViewItem* temp = current;
234  current = current->nextItem();
235  delete temp;
236  }
237  else
238  {
239  current = current->nextItem();
240  }
241  } //end while
242 
243  //reannarge photos once all photos have been removed
244  oldSubalbumWidget->getPhotos()->arrangeItemsInGrid();
245  }
246  }
247 }
248 //==============================================
249 bool SubalbumPreviewWidget::acceptDrop( const QMimeSource *) const
250 {
251  return true;
252 }
253 //==============================================
255 {
256  if(pos().y() >= i->pos().y())
257  { return 1; }
258  else
259  { return -1; }
260 }
261 //==============================================
262 QPixmap* SubalbumPreviewWidget::createSubalbumPixmap( QString imageName )
263 {
264  //load image
265  QImage icon(imageName);
266 
267  //if null then bail immediately
268  if( icon.isNull() )
269  return NULL;
270 
271  //----------------------------------------------
272  //resize image based on text properties. Find ideal hight
273  QFontMetrics fm( qApp->font() );
274 
275  //ideal image height is two text lines, 1 pixel inbetween
276  int idealImageHeight = fm.leading() + 2*fm.height();
277 
278  //ideal image width assuming 4:3 aspect ratio
279  int idealImageWidth = (4 * idealImageHeight ) / 3;
280  //----------------------------------------------
281  //resize image to fit within bounding rectangle, pad and center as necessary
282  int actualImageWidth = 0;
283  int actualImageHeight = 0;
284  calcScaledImageDimensions( icon.width(), icon.height(),
285  idealImageWidth, idealImageHeight,
286  actualImageWidth, actualImageHeight );
287 
288  //if off by one pixel fudge it so icon perfectly cenetered
289  if(actualImageHeight == idealImageHeight - 1)
290  {
291  actualImageHeight = idealImageHeight;
292  }
293 
294  QImage scaledIcon= icon.smoothScale( actualImageWidth, actualImageHeight );
295  QImage* paddedScaledIcon = new QImage(idealImageWidth, idealImageHeight, scaledIcon.depth());
296  paddedScaledIcon->setAlphaBuffer(true);
297 
298  //make entire image transparent
299  int x, y;
300  for(x=0; x< idealImageWidth; x++)
301  {
302  for(y=0; y<idealImageHeight; y++)
303  {
304  paddedScaledIcon->setPixel(x,y, qRgba(255, 255, 255,0) );
305  }
306  }
307 
308  //paint image in center of padded region
309  int xDiff = idealImageWidth - actualImageWidth;
310  int yDiff = idealImageHeight - actualImageHeight;
311  int x2 = 0;
312  for(x= xDiff/2; x < (xDiff/2) + actualImageWidth; x++)
313  {
314  int y2 = 0;
315  for(y= yDiff/2; y < (yDiff/2) + actualImageHeight; y++)
316  {
317  paddedScaledIcon->setPixel(x, y, scaledIcon.pixel(x2, y2));
318  y2++;
319  }
320  x2++;
321  }
322 
323  //clip corners if image takes up full width
324  if(xDiff == 0)
325  {
326  paddedScaledIcon->setPixel(0, 0, qRgba(255, 0,0,0) );
327  paddedScaledIcon->setPixel(idealImageWidth-1, 0, qRgba(255, 0,0,0) );
328  paddedScaledIcon->setPixel(0, idealImageHeight-1, qRgba(255, 0,0,0) );
329  paddedScaledIcon->setPixel(idealImageWidth-1, idealImageHeight-1, qRgba(255, 0,0,0) );
330  }
331 
332  QPixmap* padddedScaledPix = new QPixmap( paddedScaledIcon->width(), paddedScaledIcon->height() );
333  padddedScaledPix->convertFromImage( *paddedScaledIcon );
334  delete paddedScaledIcon;
335  return padddedScaledPix;
336  //----------------------------------------------
337 }
338 //==============================================
339 void SubalbumPreviewWidget::calcRect( const QString & text_ )
340 {
341  //setup default dimensions
342  Q3IconViewItem::calcRect( text_ );
343 
344  //update using init method
346 }
347 //==============================================
349 {
350  //reset pixmap rect
351  QRect pr = pixmapRect();
352  int prWidth = pr.width();
353  int prHeight = pr.height();
354  pr.setTopLeft( QPoint(3,3) );
355  pr.setBottomRight( QPoint(pr.left()+prWidth, pr.top()+prHeight) );
356  setPixmapRect( pr );
357 
358  //reset text rect
359  int textWidth = parent->getTextWidth();
360  QRect tr = textRect();
361  tr.setTop( pixmapRect().top() );
362  tr.setBottom( pixmapRect().bottom() );
363  tr.setLeft( pixmapRect().right() + 2 );
364  tr.setRight( tr.left() + textWidth );
365  setTextRect( tr );
366 
367  //reset item rect using pixmap and text rect dimensions
368  int itemW = 3 + pixmapRect().width() + (tr.left() - pr.right()) + textRect().width() + 3;
369  int itemH = 3 + pixmapRect().height() + 3;
370  setItemRect( QRect( pixmapRect().left() - 3, pixmapRect().top() - 3, itemW, itemH ) );
371 }
372 //==============================================
373 void SubalbumPreviewWidget::setText ( const QString & text )
374 {
375  Q3IconViewItem::setText( clipText(text, 2, parent->getTextWidth()), false );
376 }
377 //==============================================
379 {
380  mousedOver = val;
381 }
382 //==============================================
383 QColor SubalbumPreviewWidget::blendColors( QColor a, QColor b, double alpha)
384 {
385  double alpha2 = 1-alpha;
386  return QColor( (int)(alpha*a.red() + alpha2*b.red()),
387  (int)(alpha*a.green() + alpha2*b.green()),
388  (int)(alpha*a.blue() + alpha2*b.blue()) );
389 }
390 //==============================================
#define MEDIUM
Definition: album.h:18
int width
Definition: blur.cpp:79
int height
Definition: blur.cpp:79
float * buffer
Definition: blur.cpp:80
Displays list of subalbums and a particular subalbum layout.
Definition: layoutWidget.h:40
Displays photo thumbnail and description.
A photo consists of a full size image, a smaller slide show image, a very small thumbnail image,...
Definition: photo.h:45
void paintItem(QPainter *p, const QColorGroup &cg)
Subalbum * getSubalbum()
Returns subalbum pointer.
bool acceptDrop(const QMimeSource *e) const
void dropped(QDropEvent *e, const Q3ValueList< Q3IconDragItem > &lst)
void setText(const QString &text)
Subalbum * subalbum
Pointer to subalbum backend object.
QColor blendColors(QColor a, QColor b, double alpha)
bool mousedOver
is the mouse over the widget
static QPixmap * createSubalbumPixmap(QString imageName)
SubalbumsIconView * parent
parent icon view
int compare(Q3IconViewItem *i) const
SubalbumPreviewWidget(SubalbumsIconView *parent, Subalbum *salbum)
Sets subalbum pointer.
void paintFocus(QPainter *p, const QColorGroup &cg)
void calcRect(const QString &text_=QString::null)
Displays subalbum layout.
Q3IconView * getPhotos()
Returns pointer to icon view.
Subalbum * getSubalbum()
returns a pointer to the backend subalbum
A subalbum contains photos.
Definition: subalbum.h:49
bool addPhoto(QString fileName, bool replaceDescription=false, Photo *newPhoto=NULL)
Adds a new photo to the Subalbum and appends it to the end, returns TRUE if successful.
Definition: subalbum.cpp:198
void photoMoved(Photo *val)
Removes a specified photo without deleting the object.
Definition: subalbum.cpp:484
Extension of iconview, used to list all subalbums in album. Supports drag-n-drop within iconview such...
QString clipText(QString string, int lines, int lineWidth)
clip text to fit within numer of lines and max width
Definition: guiTools.cpp:72
void calcScaledImageDimensions(int origWidth, int origHeight, int idealWidth, int idealHeight, int &width, int &height)
Computes scale of image dimensions while respecting aspect ratio, equivalent to a QImage::scaleMin wi...
Definition: imageTools.cpp:39
long b
Definition: jpegInternal.h:125