00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qlayout.h>
00013 #include <qlabel.h>
00014 #include <qimage.h>
00015 #include <qpixmap.h>
00016 #include <qtimer.h>
00017 #include <qapplication.h>
00018 #include <qpainter.h>
00019 #include <qtextedit.h>
00020 #include <qcursor.h>
00021
00022
00023 #include "photoDescEdit.h"
00024 #include "photoPreviewWidget.h"
00025 #include "photosIconView.h"
00026 #include "clickableLabel.h"
00027 #include "../config.h"
00028 #include "../backend/photo.h"
00029 #include "../backend/tools/imageTools.h"
00030
00031 #define EDIT_MARGIN 4
00032
00033
00034 #if defined(Q_OS_MACX)
00035 #include "/Developer/Headers/FlatCarbon/MacWindows.h"
00036 #endif
00037
00038
00039 #if defined(Q_OS_WIN)
00040 #include <windows.h>
00041 #include <winuser.h>
00042 #define SPI_GETDROPSHADOW 0x1024
00043 #define SPI_SETDROPSHADOW 0x1025
00044 #endif
00045
00046
00047 PhotoDescEdit::PhotoDescEdit( PhotoPreviewWidget* ppw, bool useAnimation,
00048 QWidget* parent, const char* name ) :
00049 QWidget(parent,name,
00050 Qt::WStyle_Customize |
00051 #if defined(Q_OS_MACX)
00052 Qt::WStyle_Splash )
00053 #else
00054 Qt::WStyle_NoBorder | Qt::WType_Popup )
00055 #endif
00056 {
00057
00058
00059 #if defined(Q_OS_MACX)
00060 ChangeWindowAttributes( (OpaqueWindowPtr*)winId(), kWindowNoShadowAttribute, kWindowNoAttributes );
00061 #endif
00062
00063
00064
00065 #if defined(Q_OS_WIN)
00066 SystemParametersInfo( SPI_GETDROPSHADOW, 0, &dropShadowsEnabled, 0 );
00067 SystemParametersInfo( SPI_SETDROPSHADOW, 0, NULL, 0 );
00068 #endif
00069
00070 this->ppw = ppw;
00071
00072
00073 setWFlags(WNoAutoErase);
00074
00075
00076 getImageSize( ppw->getPhoto()->getThumbnailFilename(), smallWidth, smallHeight );
00077
00078 QRect appRec = qApp->mainWidget()->frameGeometry();
00079 int finalWidth, finalHeight;
00080 int actualFinalWidth, actualFinalHeight;
00081
00082
00083 if(smallWidth > smallHeight )
00084 {
00085 finalWidth = 400;
00086 finalHeight = (finalWidth * smallHeight) / smallWidth;
00087
00088
00089 if(finalWidth +2*EDIT_MARGIN> appRec.width())
00090 {
00091 finalWidth = appRec.width() - 2*EDIT_MARGIN;
00092 finalHeight = (finalWidth * smallHeight) / smallWidth;
00093 }
00094
00095
00096 QFontMetrics fm( qApp->font() );
00097 idealTextSize = 4*fm.height() + 5*fm.leading() + 4;
00098
00099 if(finalHeight + idealTextSize + 2*EDIT_MARGIN > appRec.height() )
00100 {
00101 finalHeight = appRec.height() - idealTextSize - 2*EDIT_MARGIN;
00102 finalWidth = (finalHeight * smallWidth) / smallHeight;
00103 }
00104
00105
00106 if(finalHeight < 0)
00107 {
00108 finalHeight = (appRec.height() - 2*EDIT_MARGIN) / 2;
00109 finalWidth = (finalHeight * smallWidth) / smallHeight;
00110 idealTextSize = finalHeight;
00111 }
00112
00113 actualFinalWidth = finalWidth + 2*EDIT_MARGIN;
00114 actualFinalHeight = finalHeight + idealTextSize + 2*EDIT_MARGIN;
00115
00116
00117 #if defined(Q_OS_MACX)
00118 actualFinalHeight+=2;
00119 #endif
00120 }
00121
00122 else
00123 {
00124 finalHeight = 300;
00125 finalWidth = (finalHeight * smallWidth) / smallHeight;
00126
00127
00128 if(finalHeight + 2*EDIT_MARGIN > appRec.height())
00129 {
00130 finalHeight = appRec.height() - 2*EDIT_MARGIN;
00131 finalWidth = (finalHeight * smallWidth) / smallHeight;
00132 }
00133
00134
00135 QString calibrationString( qApp->translate("PhotoDescEdit", "This is the photo description calibration string.") );
00136 QFontMetrics fm( qApp->font() );
00137 idealTextSize = fm.width( calibrationString );
00138 if(finalWidth + idealTextSize + 2*EDIT_MARGIN > appRec.width() )
00139 {
00140 finalWidth = appRec.width() - idealTextSize - 2*EDIT_MARGIN;
00141 finalHeight = (finalWidth * smallHeight) / smallWidth;
00142 }
00143
00144
00145 if(finalWidth < 0)
00146 {
00147 finalWidth = (appRec.width() - 2*EDIT_MARGIN) / 2;
00148 finalHeight = (finalWidth * smallHeight) / smallWidth;
00149 idealTextSize = finalWidth;
00150 }
00151
00152 actualFinalWidth = finalWidth + idealTextSize + 2*EDIT_MARGIN;
00153 actualFinalHeight = finalHeight + 2*EDIT_MARGIN;
00154 }
00155
00156
00157
00158 int fullWidth, fullHeight;
00159 if(!getImageSize( ppw->getPhoto()->getImageFilename(), fullWidth, fullHeight ) )
00160 {
00161 imageLarge = new QImage( QImage( ppw->getPhoto()->getThumbnailFilename()).
00162 scale(finalWidth,finalHeight, QImage::ScaleFree ));
00163 }
00164
00165 else
00166 {
00167
00168 QImage paddedSSImage( ppw->getPhoto()->getSlideshowFilename() );
00169
00170
00171 int actualWidth, actualHeight;
00172 calcScaledImageDimensions( fullWidth, fullHeight,
00173 paddedSSImage.width(), paddedSSImage.height(),
00174 actualWidth, actualHeight );
00175
00176
00177 int leftOffset = (paddedSSImage.width() - actualWidth) / 2;
00178 int topOffset = (paddedSSImage.height() - actualHeight) / 2;
00179 QImage SSImage( actualWidth, actualHeight, paddedSSImage.depth() );
00180
00181 int x, y;
00182 for(x=0; x<actualWidth; x++)
00183 {
00184 for(y=0; y<actualHeight; y++)
00185 {
00186 SSImage.setPixel( x, y, red.rgb() );
00187 SSImage.setPixel( x, y, paddedSSImage.pixel(x+leftOffset, y+topOffset) );
00188 }
00189 }
00190 imageLarge = new QImage(SSImage.smoothScale(finalWidth,finalHeight, QImage::ScaleFree ));
00191 }
00192
00193
00194 TextEdit tmpTextEdit;
00195 tmpTextEdit.setText( ppw->getPhoto()->getDescription() );
00196
00197 if(smallWidth > smallHeight )
00198 tmpTextEdit.resize( finalWidth, idealTextSize );
00199 else
00200 tmpTextEdit.resize( idealTextSize, finalHeight );
00201
00202 tmpTextEdit.setLineWidth( 0 );
00203 tmpTextEdit.setMargin( 0 );
00204 tmpTextEdit.setMidLineWidth( 0 );
00205 tmpTextEdit.setFrameStyle( QFrame::NoFrame | QFrame::Plain );
00206
00207 tmpTextEdit.setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
00208 tmpTextEdit.constPolish();
00209 tmpTextEdit.polish();
00210
00211 tmpTextEdit.setWordWrap( QTextEdit::FixedPixelWidth );
00212 if(smallWidth > smallHeight )
00213 tmpTextEdit.setWrapColumnOrWidth( finalWidth );
00214 else
00215 tmpTextEdit.setWrapColumnOrWidth( idealTextSize );
00216 tmpTextEdit.updateScrollBars();
00217 tmpTextEdit.constPolish();
00218 tmpTextEdit.polish();
00219
00220 if(smallWidth > smallHeight )
00221 {
00222 if(tmpTextEdit.lines() > 4)
00223 {
00224 tmpTextEdit.setWrapColumnOrWidth( finalWidth - tmpTextEdit.verticalScrollBar()->width() );
00225 tmpTextEdit.updateScrollBars();
00226 tmpTextEdit.constPolish();
00227 tmpTextEdit.polish();
00228 }
00229 }
00230 else
00231 {
00232 QFontMetrics fm( qApp->font() );
00233 if(tmpTextEdit.lines() > idealTextSize / (fm.leading() + fm.height()) )
00234 {
00235 tmpTextEdit.setWrapColumnOrWidth( idealTextSize - tmpTextEdit.verticalScrollBar()->width() );
00236 tmpTextEdit.updateScrollBars();
00237 tmpTextEdit.constPolish();
00238 tmpTextEdit.polish();
00239 }
00240 }
00241
00242
00243 tmpTextEdit.paintNow();
00244 textRectangle = new QImage( QPixmap::grabWidget(&tmpTextEdit).convertToImage() );
00245
00246
00247 initPos = ppw->getPhotoPos();
00248
00249
00250 initPos += QPoint( -EDIT_MARGIN, -EDIT_MARGIN );
00251
00252 int initCenterX = initPos.x() + smallWidth/2;
00253 int initCenterY = initPos.y() + smallHeight/2;
00254
00255 finalPos = QPoint( initCenterX - actualFinalWidth/2, initCenterY - actualFinalHeight/2 );
00256 if(finalPos.x() < appRec.x() )
00257 finalPos.setX( appRec.x() );
00258 if(finalPos.x() + actualFinalWidth > appRec.x() + appRec.width() )
00259 finalPos.setX( appRec.x() + appRec.width()- actualFinalWidth );
00260
00261 if(finalPos.y() < appRec.y() )
00262 finalPos.setY( appRec.y() );
00263 if(finalPos.y() + actualFinalHeight > appRec.y() + appRec.height() )
00264 finalPos.setY( appRec.y() + appRec.height()- actualFinalHeight );
00265
00266
00267 left = QMIN( finalPos.x(), initPos.x() );
00268 top = QMIN( finalPos.y(), initPos.y() );
00269 right = QMAX( finalPos.x() + actualFinalWidth, initPos.x() + smallWidth );
00270 bottom = QMAX( finalPos.y() + actualFinalHeight, initPos.y() + smallHeight );
00271
00272
00273 backgroundImage = new QPixmap( QPixmap::grabWindow(QApplication::desktop()->winId(),
00274 left, top,
00275 right-left, bottom-top) );
00276 setBackgroundMode( Qt::NoBackground );
00277
00278
00279 animationLabel = new QLabel(this, "animationLabel", WNoAutoErase);
00280 animationLabel->setPixmap( *backgroundImage );
00281 animationLabel->setBackgroundMode( Qt::NoBackground );
00282 buffer = new QPixmap( backgroundImage->width(), backgroundImage->height() );
00283
00284 mainGrid = new QGridLayout( this, 1, 2, 0 );
00285 mainGrid->addWidget(animationLabel, 0, 0 );
00286
00287
00288 staticFrame = new QWidget(this);
00289 staticFrame->hide();
00290 staticFrame->setBackgroundMode( Qt::NoBackground );
00291 mainGrid->addWidget(staticFrame, 0, 1 );
00292
00293 staticPhoto = new QLabel( staticFrame, "staticPhoto", WNoAutoErase);
00294 staticPhoto->setPixmap( QPixmap( *imageLarge) );
00295 staticPhoto->setBackgroundMode( Qt::NoBackground );
00296
00297 photoDesc = new TextEdit( staticFrame );
00298 photoDesc->setText( ppw->getPhoto()->getDescription() );
00299
00300 photoDesc->setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
00301 photoDesc->setFrameStyle( QFrame::NoFrame );
00302 photoDesc->setLineWidth( 0 );
00303 photoDesc->setMargin( 0 );
00304 photoDesc->setMidLineWidth( 0 );
00305 photoDesc->setFrameStyle( QFrame::MenuBarPanel | QFrame::Plain );
00306
00307
00308 connect( photoDesc, SIGNAL( finished() ),
00309 this, SLOT( disappear() ) );
00310
00311 QWidget* bw1 = new QWidget(staticFrame);
00312 QWidget* bw2 = new QWidget(staticFrame);
00313 QWidget* bw3 = new QWidget(staticFrame);
00314 QWidget* bw4 = new QWidget(staticFrame);
00315 QColor darkBlue(35, 75, 139);
00316 bw1->setPaletteBackgroundColor( darkBlue );
00317 bw2->setPaletteBackgroundColor( darkBlue );
00318 bw3->setPaletteBackgroundColor( darkBlue );
00319 bw4->setPaletteBackgroundColor( darkBlue );
00320
00321
00322 if(smallWidth > smallHeight )
00323 {
00324 staticGrid = new QGridLayout( staticFrame, 4, 3);
00325
00326 staticGrid->addWidget( staticPhoto, 1, 1 );
00327 staticGrid->addWidget( photoDesc, 2, 1 );
00328
00329 staticGrid->setColSpacing( 2, staticPhoto->width() );
00330 staticGrid->setRowSpacing( 2, idealTextSize );
00331
00332 staticGrid->addMultiCellWidget( bw1, 0, 0, 0, 2 );
00333 staticGrid->addMultiCellWidget( bw2, 1, 2, 0, 0 );
00334 staticGrid->addMultiCellWidget( bw3, 1, 2, 2, 2 );
00335 staticGrid->addMultiCellWidget( bw4, 3, 3, 0, 2 );
00336 staticGrid->setRowSpacing( 0, EDIT_MARGIN );
00337 staticGrid->setRowSpacing( 3, EDIT_MARGIN );
00338 staticGrid->setColSpacing( 0, EDIT_MARGIN );
00339 staticGrid->setColSpacing( 2, EDIT_MARGIN );
00340 }
00341 else
00342 {
00343 staticGrid = new QGridLayout( staticFrame, 3, 4);
00344
00345 staticGrid->addWidget( staticPhoto, 1, 1 );
00346 staticGrid->addWidget( photoDesc, 1, 2 );
00347
00348 staticGrid->setRowSpacing( 1, staticPhoto->height() );
00349 staticGrid->setColSpacing( 2, idealTextSize );
00350
00351 staticGrid->addMultiCellWidget( bw1, 0, 0, 0, 3 );
00352 staticGrid->addWidget( bw2, 1, 0 );
00353 staticGrid->addWidget( bw3, 1, 3 );
00354 staticGrid->addMultiCellWidget( bw4, 2, 2, 0, 3 );
00355 staticGrid->setRowSpacing( 0, EDIT_MARGIN );
00356 staticGrid->setRowSpacing( 2, EDIT_MARGIN );
00357 staticGrid->setColSpacing( 0, EDIT_MARGIN );
00358 staticGrid->setColSpacing( 3, EDIT_MARGIN );
00359 }
00360
00361
00362 initDelay = 130;
00363 accel = 50;
00364 minDelay = 1;
00365
00366 this->useAnimation = useAnimation;
00367 if(useAnimation)
00368 step = 0;
00369 else
00370 step = 100;
00371
00372 mode = STATIC;
00373
00374
00375 timer = new QTimer();
00376 connect(timer, SIGNAL(timeout()), this, SLOT(animate()) );
00377
00378
00379 move( left, top );
00380 show();
00381
00382
00383 mode = APPEARING;
00384 delay = initDelay;
00385 lastTime.start();
00386 animate();
00387 }
00388
00389 PhotoDescEdit::~PhotoDescEdit()
00390 {
00391 delete textRectangle;
00392 delete timer;
00393 delete buffer;
00394 delete backgroundImage;
00395 delete imageLarge;
00396 }
00397
00398 void PhotoDescEdit::animate()
00399 {
00400
00401
00402 currentTime.start();
00403 double ms = lastTime.msecsTo(currentTime);
00404
00405
00406 int inc = (int)(ms/(delay+1));
00407
00408
00409 if(inc != 0)
00410 {
00411 lastTime = currentTime;
00412
00413
00414 step = step + inc;
00415 if(step > 100)
00416 step = 100;
00417
00418
00419 double alpha = ((double)step) / 100.0;
00420 int newX, newY;
00421 int imageW, imageH;
00422 int textDim;
00423 QColor darkBlue(35, 75, 139);
00424 if(mode == APPEARING)
00425 {
00426 newX = (int)((1-alpha)*initPos.x() + alpha*finalPos.x());
00427 newY = (int)((1-alpha)*initPos.y() + alpha*finalPos.y());
00428 imageW = (int)((1-alpha)*smallWidth + alpha*imageLarge->width());
00429 imageH = (int)((1-alpha)*smallHeight + alpha*imageLarge->height());
00430 textDim = (int) (alpha * idealTextSize);
00431 }
00432 else
00433 {
00434 newX = (int)(alpha*initPos.x() + (1-alpha)*finalPos.x());
00435 newY = (int)(alpha*initPos.y() + (1-alpha)*finalPos.y());
00436 imageW = (int)(alpha*smallWidth + (1-alpha)*imageLarge->width());
00437 imageH = (int)(alpha*smallHeight + (1-alpha)*imageLarge->height());
00438 textDim = (int) ((1-alpha) * idealTextSize);
00439 }
00440
00441
00442 QPainter bufferPainter( buffer );
00443 bufferPainter.drawPixmap(0,0, *backgroundImage );
00444
00445
00446 if(smallWidth > smallHeight )
00447 {
00448 bufferPainter.fillRect( newX - left,
00449 newY - top,
00450 imageW + 2*EDIT_MARGIN,
00451 imageH + 2*EDIT_MARGIN + textDim,
00452 darkBlue );
00453
00454 bufferPainter.drawPixmap( newX - left + EDIT_MARGIN,
00455 newY - top + EDIT_MARGIN + imageH,
00456 QPixmap( textRectangle->scale( imageW, textDim ) ) );
00457 }
00458 else
00459 {
00460 bufferPainter.fillRect( newX - left, newY - top,
00461 imageW + 2*EDIT_MARGIN + textDim,
00462 imageH + 2*EDIT_MARGIN,
00463 darkBlue );
00464
00465 bufferPainter.drawPixmap( newX - left + EDIT_MARGIN + imageW,
00466 newY - top + EDIT_MARGIN,
00467 QPixmap( textRectangle->scale( textDim, imageH ) ) );
00468 }
00469
00470
00471 bufferPainter.drawPixmap( newX - left + EDIT_MARGIN,
00472 newY - top + EDIT_MARGIN,
00473 QPixmap( imageLarge->scale( imageW, imageH ) ) );
00474
00475
00476 animationLabel->setPixmap( *buffer );
00477 }
00478
00479
00480 if(step < 100)
00481 {
00482
00483 delay = delay - accel;
00484 if(delay < minDelay) delay = minDelay;
00485
00486
00487 timer->start( delay, TRUE );
00488 }
00489 else
00490 {
00491 if(mode == APPEARING)
00492 {
00493 animationLabel->hide();
00494 staticFrame->show();
00495
00496
00497 photoDesc->setFocus();
00498
00499 mode = STATIC;
00500 }
00501 else
00502 {
00503
00504 #if defined(Q_OS_WIN)
00505 if(dropShadowsEnabled)
00506 SystemParametersInfo( SPI_SETDROPSHADOW, 0, &dropShadowsEnabled, 0 );
00507 else
00508 SystemParametersInfo( SPI_SETDROPSHADOW, 0, NULL, 0 );
00509 #endif //Q_OS_WIN
00510
00511 mode = DISAPPEARED;
00512 hide();
00513 qApp->mainWidget()->repaint(false);
00514 }
00515 }
00516 }
00517
00518 void PhotoDescEdit::disappear()
00519 {
00520 delete textRectangle;
00521 textRectangle = new QImage( QPixmap::grabWidget(photoDesc).convertToImage() );
00522
00523 ppw->getPhoto()->setDescription( photoDesc->text() );
00524 ppw->setText( photoDesc->text() );
00525
00526
00527 staticFrame->hide();
00528 animationLabel->show();
00529
00530 initDelay = 130;
00531 accel = 50;
00532 minDelay = 1;
00533
00534 if(useAnimation)
00535 step = 0;
00536 else
00537 step = 100;
00538
00539 mode = DISAPPEARING;
00540 lastTime.start();
00541 animate();
00542 }
00543
00544 void PhotoDescEdit::hide()
00545 {
00546 if(mode == DISAPPEARED )
00547 {
00548 QWidget::hide();
00549
00550
00551
00552 QIconView* iconView = ppw->iconView();
00553 QIconViewItem* item = iconView->findItem( iconView->viewport()->mapFromGlobal( QCursor::pos() )+=QPoint( iconView->contentsX(), iconView->contentsY() ) );
00554 if(item != NULL && item != ppw )
00555 {
00556 ((PhotosIconView*)item->iconView())->repaintGroup( item );
00557 }
00558 }
00559 else if(mode == STATIC)
00560 {
00561 disappear();
00562 }
00563 }
00564
00565 TextEdit::TextEdit( QWidget* parent, const char* name ) : QTextEdit(parent,name)
00566 {
00567 setHScrollBarMode( QScrollView::AlwaysOff );
00568 setTextFormat( Qt::PlainText );
00569 contextMenu = NULL;
00570 }
00571
00572 void TextEdit::paintNow()
00573 {
00574 constPolish();
00575 repaint( rect(), false );
00576 }
00577
00578 void TextEdit::keyPressEvent ( QKeyEvent * e )
00579 {
00580
00581 if( e->key() == Qt::Key_Escape )
00582 {
00583 emit finished();
00584 }
00585
00586 else if( (e->state() & Qt::ControlButton) && e->key() == Qt::Key_A )
00587 {
00588 selectAll();
00589 }
00590 else
00591 {
00592 QTextEdit::keyPressEvent( e );
00593 }
00594 }
00595
00596 void TextEdit::focusOutEvent ( QFocusEvent * )
00597 {
00598
00599
00600 if( contextMenu == NULL ) emit finished();
00601 }
00602
00603 QPopupMenu* TextEdit::createPopupMenu ( const QPoint& pos )
00604 {
00605
00606 contextMenu = QTextEdit::createPopupMenu( pos );
00607 connect( ((QObject*)contextMenu), SIGNAL(aboutToHide()),
00608 this, SLOT(contextMenuHiding()) );
00609 return contextMenu;
00610 }
00611
00612 void TextEdit::contextMenuHiding()
00613 {
00614
00615 disconnect( ((QObject*)contextMenu), SIGNAL(aboutToHide()),
00616 this, SLOT(contextMenuHiding()) );
00617 contextMenu = NULL;
00618 }
00619