00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qlayout.h>
00013 #include <qlabel.h>
00014 #include <qfont.h>
00015 #include <qframe.h>
00016 #include <qsize.h>
00017 #include <qtoolbutton.h>
00018 #include <qimage.h>
00019 #include <qcursor.h>
00020 #include <qapplication.h>
00021 #include <math.h>
00022 #include <qtooltip.h>
00023 #include <qhgroupbox.h>
00024 #include <qpushbutton.h>
00025 #include <qcombobox.h>
00026 #include <math.h>
00027
00028
00029 #include "../clickableLabel.h"
00030 #include "editingInterface.h"
00031 #include "selectionInterface.h"
00032 #include "histogramEditor.h"
00033 #include "grainEditor.h"
00034 #include "../statusWidget.h"
00035 #include "../layoutWidget.h"
00036 #include "../window.h"
00037 #include "../titleWidget.h"
00038 #include "../dialogs/questionDialog.h"
00039 #include "../../config.h"
00040 #include "../../backend/album.h"
00041 #include "../../backend/subalbum.h"
00042 #include "../../backend/photo.h"
00043 #include "../../backend/tools/fileTools.h"
00044 #include "../../backend/tools/imageTools.h"
00045
00046 #include "../../backend/enhancements/color.h"
00047 #include "../../backend/enhancements/contrast.h"
00048 #include "../../backend/enhancements/redEye.h"
00049 #include "../../backend/enhancements/tilt.h"
00050
00051 #include "../../backend/manipulations/blackWhite.h"
00052 #include "../../backend/manipulations/crop.h"
00053 #include "../../backend/manipulations/emboss.h"
00054 #include "../../backend/manipulations/invert.h"
00055 #include "../../backend/manipulations/painting.h"
00056 #include "../../backend/manipulations/pointillism.h"
00057 #include "../../backend/manipulations/sepia.h"
00058
00059 #include "../../configuration/configuration.h"
00060
00061 #define EFFECT_PREVIEW_WIDTH 107
00062 #define EFFECT_PREVIEW_HEIGHT 80
00063
00064
00065 EditingInterface::EditingInterface(QWidget *parent, const char* name )
00066 : QWidget(parent,name)
00067 {
00068
00069 QFont smallerFont = font();
00070 smallerFont.setPointSize( smallerFont.pointSize() - 1 );
00071
00072 setFocusPolicy(QWidget::StrongFocus);
00073
00074
00075 photo = NULL;
00076
00077
00078 layout = (LayoutWidget*)parent;
00079
00080
00081
00082 QFrame* photoFrame = new QFrame(this, "photoFrame" );
00083
00084
00085 QFrame* controlsFrame = new QFrame(this, "controlsFrame");
00086
00087
00088 QGridLayout* mainGrid = new QGridLayout( this, 3, 3, 0 );
00089 mainGrid->addWidget( photoFrame, 0, 1 );
00090 mainGrid->setRowStretch(0, 1);
00091 mainGrid->addMultiCellWidget( controlsFrame, 1,1, 0,2 );
00092 mainGrid->setRowSpacing( 2, WIDGET_SPACING );
00093
00094
00095 previousButton = new ClickableLabel( photoFrame, "previousButton" );
00096 previousButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/previous.png") );
00097 connect( previousButton, SIGNAL(clicked()), SLOT(showPrevPhoto()) );
00098
00099
00100 selectionInterface = new SelectionInterface( photoFrame, "selectionInterface" );
00101 connect( selectionInterface, SIGNAL( selectionChanged() ), this, SLOT( handleSelectionChanged() ) );
00102 connect( selectionInterface, SIGNAL( aspectRatioChanged() ), this, SLOT( handleAspectRatioChanged() ) );
00103 connect( selectionInterface, SIGNAL( ctrlClick() ), this, SLOT( rotateSelection() ) );
00104
00105
00106 nextButton = new ClickableLabel( photoFrame, "nextButton" );
00107 nextButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/next.png") );
00108 connect( nextButton, SIGNAL(clicked()), SLOT(showNextPhoto()) );
00109
00110
00111 QGridLayout* selectionGrid = new QGridLayout( photoFrame, 1, 5, 0 );
00112 selectionGrid->setColSpacing( 0, WIDGET_SPACING );
00113 selectionGrid->addWidget( previousButton, 0, 1, Qt::AlignCenter );
00114 selectionGrid->addWidget( selectionInterface, 0, 2 );
00115 selectionGrid->setColStretch( 2, 1 );
00116 selectionGrid->addWidget( nextButton, 0, 3, Qt::AlignCenter );
00117 selectionGrid->setColSpacing( 4, WIDGET_SPACING );
00118 selectionGrid->setSpacing( WIDGET_SPACING );
00119
00120
00121 QHGroupBox* frameControls = new QHGroupBox( tr("Frame"), controlsFrame, "frameControls" );
00122 frameControls->setAlignment( Qt::AlignHCenter );
00123 frameControls->setInsideMargin( WIDGET_SPACING );
00124
00125 QHGroupBox* enhanceControls = new QHGroupBox( tr("Enhance"), controlsFrame, "enhanceControls" );
00126 enhanceControls->setAlignment( Qt::AlignHCenter );
00127 enhanceControls->setInsideMargin( WIDGET_SPACING );
00128
00129 QHGroupBox* manipulateControls = new QHGroupBox( tr("Manipulate"), controlsFrame, "applyEffect" );
00130 manipulateControls->setAlignment( Qt::AlignHCenter );
00131 manipulateControls->setInsideMargin( WIDGET_SPACING );
00132
00133
00134 QGridLayout* controlsGrid = new QGridLayout( controlsFrame, 1, 5, 0 );
00135 controlsGrid->addWidget( frameControls, 0, 1 );
00136 controlsGrid->addWidget( enhanceControls, 0, 2 );
00137 controlsGrid->addWidget( manipulateControls, 0, 3 );
00138
00139 controlsGrid->setSpacing( WIDGET_SPACING );
00140 controlsGrid->setColSpacing(0, WIDGET_SPACING );
00141 controlsGrid->setColStretch(0, 1);
00142 controlsGrid->setColSpacing(4, WIDGET_SPACING );
00143 controlsGrid->setColStretch(4, 1);
00144
00145
00146
00147
00148 QFrame* frameControlsFrame = new QFrame( frameControls );
00149
00150
00151
00152 QFrame* rotateFlipFrame = new QFrame( frameControlsFrame );
00153
00154 QToolButton* rotateRightButton = new QToolButton( rotateFlipFrame, "rotateRight" );
00155 rotateRightButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/rotate90.png") );
00156 rotateRightButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00157 connect( rotateRightButton, SIGNAL(clicked()), SLOT(rotateRight()) );
00158 QToolTip::add( rotateRightButton, tr("Rotate clockwise") );
00159
00160 QToolButton* rotateLeftButton = new QToolButton( rotateFlipFrame, "rotateLeft" );
00161 rotateLeftButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/rotate270.png") );
00162 rotateLeftButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00163 connect( rotateLeftButton, SIGNAL(clicked()), SLOT(rotateLeft()) );
00164 QToolTip::add( rotateLeftButton, tr("Rotate counterclockwise") );
00165
00166 QToolButton* flipHorizontalButton = new QToolButton( rotateFlipFrame, "flipHorizontal" );
00167 flipHorizontalButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/flipHorizontally.png") );
00168 flipHorizontalButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00169 connect( flipHorizontalButton, SIGNAL(clicked()), SLOT(flipHorizontal()) );
00170 QToolTip::add( flipHorizontalButton, tr("Flip horizontally") );
00171
00172 QToolButton* flipVerticalButton = new QToolButton( rotateFlipFrame, "flipVertical" );
00173 flipVerticalButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/flipVertically.png") );
00174 flipVerticalButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00175 connect( flipVerticalButton, SIGNAL(clicked()), SLOT(flipVertical()) );
00176 QToolTip::add( flipVerticalButton, tr("Flip vertically") );
00177
00178 correctTiltButton = new QToolButton( rotateFlipFrame, "correctTilt" );
00179 correctTiltButton->setIconSet( QPixmap(QString(IMAGE_PATH)+"buttonIcons/correctTilt.png") );
00180 correctTiltButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00181
00182 connect( correctTiltButton, SIGNAL(clicked()), SLOT(startCorrectTilt()) );
00183
00184 connect( selectionInterface, SIGNAL(lineSelected(QPoint, QPoint)),
00185 this, SLOT(finishCorrectTilt( QPoint, QPoint)) );
00186
00187 QToolTip::add( correctTiltButton, tr("Correct tilt") );
00188
00189
00190 QGridLayout* rotateFlipGrid = new QGridLayout( rotateFlipFrame, 1, 5, 0 );
00191 rotateFlipGrid->setSpacing(TIGHT_WIDGET_SPACING);
00192 rotateFlipGrid->addWidget( rotateRightButton, 0, 0 );
00193 rotateFlipGrid->addWidget( rotateLeftButton, 0, 1 );
00194 rotateFlipGrid->addWidget( flipHorizontalButton, 0, 2 );
00195 rotateFlipGrid->addWidget( flipVerticalButton, 0, 3 );
00196 rotateFlipGrid->addWidget( correctTiltButton, 0, 4 );
00197
00198
00199 aspectRatios = new QComboBox( frameControlsFrame );
00200 aspectRatios->setFont( smallerFont );
00201 connect( aspectRatios, SIGNAL(activated(int)), this, SLOT(selectAspectRatio()) );
00202 aspectRatioValues = new QSize[8];
00203 maxDimensions = new double[8];
00204 int curAspectRatio = 0;
00205
00206 aspectRatios->insertItem( tr("Custom") );
00207 maxDimensions[curAspectRatio] = -1.0;
00208 aspectRatioValues[curAspectRatio++] = QSize( -1, -1 );
00209
00210 aspectRatios->insertItem( tr("Photo (3.5 x 5)") );
00211 maxDimensions[curAspectRatio] = 5.0;
00212 aspectRatioValues[curAspectRatio++] = QSize( 10, 7 );
00213
00214 aspectRatios->insertItem( tr("Photo (4 x 6)") );
00215 maxDimensions[curAspectRatio] = 6.0;
00216 aspectRatioValues[curAspectRatio++] = QSize( 6, 4 );
00217
00218 aspectRatios->insertItem( tr("Photo (5 x 7)") );
00219 maxDimensions[curAspectRatio] = 7.0;
00220 aspectRatioValues[curAspectRatio++] = QSize( 7, 5 );
00221
00222 aspectRatios->insertItem( tr("Photo (8 x 10)") );
00223 maxDimensions[curAspectRatio] = 10.0;
00224 aspectRatioValues[curAspectRatio++] = QSize( 10, 8 );
00225
00226 aspectRatios->insertItem( tr("Postcard") );
00227 maxDimensions[curAspectRatio] = 6.0;
00228 aspectRatioValues[curAspectRatio++] = QSize( 6, 4 );
00229
00230 aspectRatios->insertItem( tr("Wallet") );
00231 maxDimensions[curAspectRatio] = 3.0;
00232 aspectRatioValues[curAspectRatio++] = QSize( 2, 3 );
00233
00234 aspectRatios->insertItem( tr("Desktop") );
00235 displayResolutionIndex = curAspectRatio;
00236 maxDimensions[curAspectRatio] = -1.0;
00237 aspectRatioValues[curAspectRatio++] = qApp->desktop()->screenGeometry().size();
00238
00239
00240
00241 connect( qApp->desktop(), SIGNAL( resized(int)), this, SLOT(screenResolutionChanged()) );
00242
00243 QToolTip::add( aspectRatios, tr("Select region for cropping using a particular aspect ratio") );
00244
00245 QLabel* aspectRatioLabel = new QLabel( tr("Aspect Ratio"), frameControlsFrame );
00246 aspectRatioLabel->setFont( smallerFont );
00247
00248
00249
00250 cropButton = new QToolButton( frameControlsFrame );
00251 QIconSet cropIcon;
00252 cropIcon.setPixmap( QString(IMAGE_PATH)+"buttonIcons/crop.png",
00253 QIconSet::Automatic,
00254 QIconSet::Normal );
00255
00256 cropIcon.setPixmap( QString(IMAGE_PATH)+"buttonIcons/crop_disabled.png",
00257 QIconSet::Automatic,
00258 QIconSet::Disabled );
00259 cropButton->setIconSet( cropIcon );
00260 connect( cropButton, SIGNAL(clicked()), SLOT(crop()) );
00261 QToolTip::add( cropButton, tr("Crop photo to selected region") );
00262
00263 QLabel* cropLabel = new QLabel( tr("Crop"), frameControlsFrame );
00264 cropLabel->setFont( smallerFont );
00265
00266
00267
00268
00269 QGridLayout* frameControlsGrid = new QGridLayout( frameControlsFrame, 3, 2, 0 );
00270 frameControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
00271 frameControlsGrid->addMultiCellWidget( rotateFlipFrame, 0,0, 0,1 );
00272 frameControlsGrid->addWidget( aspectRatios, 1, 0, Qt::AlignHCenter );
00273 frameControlsGrid->addWidget( cropButton, 1, 1, Qt::AlignHCenter );
00274 frameControlsGrid->addWidget( aspectRatioLabel, 2, 0, Qt::AlignHCenter );
00275 frameControlsGrid->addWidget( cropLabel, 2, 1, Qt::AlignHCenter );
00276
00277
00278
00279
00280 QFrame* enhanceControlsFrame = new QFrame( enhanceControls );
00281
00282
00283 int numLargeButtons = 3;
00284 int curButtonIndex=0;
00285 ClickableLabel** largeButtons = new ClickableLabel*[numLargeButtons];
00286
00287
00288
00289
00290 QFrame* autoEnhanceControlsFrame = new QFrame( enhanceControlsFrame );
00291
00292
00293 ClickableLabel* enhanceColorButton = largeButtons[curButtonIndex] =
00294 new ClickableLabel( autoEnhanceControlsFrame );
00295 largeButtons[curButtonIndex]->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/improveColorBalance.png") );
00296 connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(colorBalance()) );
00297 QToolTip::add( largeButtons[curButtonIndex], tr("Enhance color balance") );
00298 curButtonIndex++;
00299
00300 QLabel* enhanceColorLabel = new QLabel( tr("Color"), autoEnhanceControlsFrame );
00301 enhanceColorLabel->setFont( smallerFont );
00302
00303
00304 ClickableLabel* enhanceContrastButton = largeButtons[curButtonIndex] =
00305 new ClickableLabel( autoEnhanceControlsFrame );
00306 largeButtons[curButtonIndex]->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/enhanceContrast.png") );
00307 connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(enhanceContrast()) );
00308 QToolTip::add( largeButtons[curButtonIndex], tr("Enhance contrast") );
00309 curButtonIndex++;
00310
00311 QLabel* enhanceContrastLabel = new QLabel( tr("Contrast"), autoEnhanceControlsFrame );
00312 enhanceContrastLabel->setFont( smallerFont );
00313
00314
00315 redEyeReductionButton = largeButtons[curButtonIndex] = new ClickableLabel( autoEnhanceControlsFrame );
00316 redEyeReductionButton->setEnabled( false );
00317
00318 largeButtons[curButtonIndex]->setPixmap( QPixmap( QString(IMAGE_PATH)+"buttonIcons/redEyeReduction.png" ) );
00319 connect( largeButtons[curButtonIndex], SIGNAL(clicked()), SLOT(removeRedeye()) );
00320 QToolTip::add( largeButtons[curButtonIndex], tr("Remove red-eye") );
00321 curButtonIndex++;
00322
00323 QLabel* removeRedyEyeLabel = new QLabel( tr("Red Eye"), autoEnhanceControlsFrame );
00324 removeRedyEyeLabel->setFont( smallerFont );
00325
00326
00327 QGridLayout* autoEnhanceControlsGrid = new QGridLayout( autoEnhanceControlsFrame, 2, 3, 0 );
00328 autoEnhanceControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
00329 autoEnhanceControlsGrid->addWidget( enhanceColorButton, 0, 0, Qt::AlignHCenter );
00330 autoEnhanceControlsGrid->addWidget( enhanceColorLabel, 1, 0, Qt::AlignHCenter );
00331
00332 autoEnhanceControlsGrid->addWidget( enhanceContrastButton, 0, 1, Qt::AlignHCenter );
00333 autoEnhanceControlsGrid->addWidget( enhanceContrastLabel, 1, 1, Qt::AlignHCenter );
00334
00335 autoEnhanceControlsGrid->addWidget( redEyeReductionButton, 0, 2, Qt::AlignHCenter );
00336 autoEnhanceControlsGrid->addWidget( removeRedyEyeLabel, 1, 2, Qt::AlignHCenter );
00337
00338
00339 QFrame* manualEnhanceControlsFrame = new QFrame( enhanceControlsFrame );
00340
00341
00342 ClickableLabel* tuneLevelsButton = new ClickableLabel( manualEnhanceControlsFrame );
00343 tuneLevelsButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/tuneLevels.png") );
00344 connect( tuneLevelsButton, SIGNAL(clicked()), SLOT(tuneLevels()) );
00345 QToolTip::add( tuneLevelsButton, tr("Fine tune brightness, contrast, and colors") );
00346
00347 QLabel* tuneLevelsLabel = new QLabel( tr("Levels..."), manualEnhanceControlsFrame );
00348 tuneLevelsLabel->setFont( smallerFont );
00349
00350
00351 ClickableLabel* adjustGrainButton = new ClickableLabel( manualEnhanceControlsFrame );
00352 adjustGrainButton->setPixmap( QPixmap(QString(IMAGE_PATH)+"buttonIcons/adjustGrain.png") );
00353 connect( adjustGrainButton, SIGNAL(clicked()), SLOT(adjustGrain()) );
00354 QToolTip::add( adjustGrainButton, tr("Blur or sharpen image") );
00355
00356 QLabel* adjustGrainLabel = new QLabel( tr("Grain..."), manualEnhanceControlsFrame );
00357 adjustGrainLabel->setFont( smallerFont );
00358
00359
00360 QGridLayout* manualEnhanceControlsGrid = new QGridLayout( manualEnhanceControlsFrame, 2, 3, 0 );
00361 manualEnhanceControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
00362 manualEnhanceControlsGrid->addWidget( tuneLevelsButton, 0, 0, Qt::AlignHCenter );
00363 manualEnhanceControlsGrid->addWidget( tuneLevelsLabel, 1, 0, Qt::AlignHCenter );
00364 manualEnhanceControlsGrid->setColSpacing( 1, WIDGET_SPACING );
00365 manualEnhanceControlsGrid->addWidget( adjustGrainButton, 0, 2, Qt::AlignHCenter );
00366 manualEnhanceControlsGrid->addWidget( adjustGrainLabel, 1, 2, Qt::AlignHCenter );
00367
00368
00369
00370 QGridLayout* enhanceControlsGrid = new QGridLayout( enhanceControlsFrame, 4, 2, 0 );
00371 enhanceControlsGrid->setSpacing(WIDGET_SPACING);
00372 enhanceControlsGrid->addWidget( autoEnhanceControlsFrame, 0, 0, Qt::AlignHCenter );
00373 enhanceControlsGrid->addWidget( manualEnhanceControlsFrame, 1, 0, Qt::AlignHCenter );
00374 enhanceControlsGrid->setRowStretch( 0, 1 );
00375 enhanceControlsGrid->setRowStretch( 3, 1 );
00376
00377
00378
00379
00380 QFrame* manipulateControlsFrame = new QFrame( manipulateControls, "manipulateControlsFrame" );
00381
00382
00383 effectsList = new QComboBox( manipulateControlsFrame );
00384 effectsList->setFont( smallerFont );
00385 connect( effectsList, SIGNAL(activated(int)), this, SLOT(selectEffect()) );
00386 int effectIndex = 0;
00387
00388 effectsList->insertItem( tr("B + W") );
00389 BW_EFFECT = effectIndex++;
00390
00391 effectsList->insertItem( tr("Sepia") );
00392 SEPIA_EFFECT = effectIndex++;
00393
00394 effectsList->insertItem( tr("Invert") );
00395 INVERT_EFFECT = effectIndex++;
00396
00397 effectsList->insertItem( tr("Emboss") );
00398 EMBOSS_EFFECT = effectIndex++;
00399
00400 effectsList->insertItem( tr("Painting") );
00401 PAINTING_EFFECT = effectIndex++;
00402
00403
00404
00405 POINTILLISM_EFFECT = -1;
00406
00407
00408 applyEffectButton = new QPushButton( tr("Apply"), manipulateControlsFrame );
00409 applyEffectButton->setFont( smallerFont );
00410 connect( applyEffectButton, SIGNAL(clicked()), SLOT(applyEffect()) );
00411
00412
00413 effectPreview = new QLabel( manipulateControlsFrame );
00414
00415
00416 QGridLayout* manipulateControlsGrid = new QGridLayout( manipulateControlsFrame, 2, 2, 0 );
00417 manipulateControlsGrid->setSpacing(TIGHT_WIDGET_SPACING);
00418 manipulateControlsGrid->addWidget( effectsList, 0, 0 );
00419 manipulateControlsGrid->addWidget( applyEffectButton, 1, 0, Qt::AlignHCenter );
00420 manipulateControlsGrid->addMultiCellWidget( effectPreview, 0,1, 1,1, Qt::AlignHCenter );
00421
00422
00423
00424 manipulateControlsGrid->setColSpacing(1, 85 );
00425 }
00426
00427 EditingInterface::~EditingInterface() { }
00428
00429 Photo* EditingInterface::getPhoto() { return photo; }
00430
00431 void EditingInterface::setPhoto(Subalbum* collection, Photo* photo)
00432 {
00433
00434 this->collection = collection;
00435 this->photo = photo;
00436
00437
00438 previousButton->setInvisible( photo->getPrev() == NULL );
00439 nextButton->setInvisible( photo->getNext() == NULL );
00440
00441
00442 aspectRatios->setCurrentItem(0);
00443 effectsList->setCurrentItem(0);
00444
00445
00446 selectionInterface->setPhoto( photo->getImageFilename() );
00447
00448
00449 effectPreviewImageFilename = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() +
00450 "/effectPreviewImage.jpg";
00451 scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00452 selectEffect();
00453
00454
00455 getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00456
00457
00458 selectionInterface->getDisplaySize( displayWidth, displayHeight );
00459
00460
00461 cropButton->setEnabled( false );
00462 redEyeReductionButton->setEnabled( false );
00463 }
00464
00465 void EditingInterface::showPrevPhoto()
00466 {
00467 Photo* prevPhoto = photo->getPrev();
00468
00469 if( prevPhoto != NULL &&
00470 prevPhoto != photo )
00471 { showNextPrevFirstLastPhoto( prevPhoto ); }
00472 }
00473
00474 void EditingInterface::showNextPhoto()
00475 {
00476 Photo* nextPhoto = photo->getNext();
00477
00478 if( nextPhoto != NULL &&
00479 nextPhoto != photo )
00480 { showNextPrevFirstLastPhoto( nextPhoto ); }
00481 }
00482
00483 void EditingInterface::showFirstPhoto()
00484 {
00485 Photo* firstPhoto = collection->getFirst();
00486
00487 if(firstPhoto != photo)
00488 { showNextPrevFirstLastPhoto( firstPhoto ); }
00489 }
00490
00491 void EditingInterface::showLastPhoto()
00492 {
00493 Photo* lastPhoto = collection->getLast();
00494
00495 if(lastPhoto != photo)
00496 { showNextPrevFirstLastPhoto( lastPhoto ); }
00497 }
00498
00499 void EditingInterface::showNextPrevFirstLastPhoto( Photo* newPhoto )
00500 {
00501
00502 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00503 qApp->processEvents();
00504
00505
00506 photo = newPhoto;
00507
00508
00509 previousButton->setInvisible( photo->getPrev() == NULL );
00510 nextButton->setInvisible( photo->getNext() == NULL );
00511
00512
00513 selectionInterface->setPhoto( photo->getImageFilename() );
00514
00515
00516 effectPreviewImageFilename = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/effectPreviewImage.jpg";
00517 scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00518 selectEffect();
00519
00520
00521 getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00522
00523
00524 selectionInterface->getDisplaySize( displayWidth, displayHeight );
00525
00526
00527 if(aspectRatios->currentItem() != 0)
00528 { selectAspectRatio(); }
00529 else
00530 { selectionInterface->setSelection( QPoint(-1,-1), QPoint(-1, -1) ); }
00531
00532
00533 emit photoModified();
00534
00535
00536 qApp->restoreOverrideCursor();
00537 qApp->processEvents();
00538 }
00539
00540 void EditingInterface::rotateRight()
00541 {
00542 rotateFlip( ROTATE_90 );
00543 }
00544
00545 void EditingInterface::rotateLeft()
00546 {
00547 rotateFlip( ROTATE_270 );
00548 }
00549
00550 void EditingInterface::flipHorizontal()
00551 {
00552 rotateFlip( FLIP_H );
00553 }
00554
00555 void EditingInterface::flipVertical()
00556 {
00557 rotateFlip( FLIP_V );
00558 }
00559
00560 void EditingInterface::rotateFlip( TRANSFORM_CODE rotationFlipType )
00561 {
00562
00563 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00564 qApp->processEvents();
00565
00566
00567 layout->getWindow()->getStatus()->grabInput();
00568
00569
00570 QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
00571 transformImage( photo->getImageFilename(), editedImagePath, rotationFlipType );
00572
00573
00574 photo->setImage( editedImagePath );
00575
00576
00577 bool aspectRatioChanged = ( rotationFlipType == ROTATE_90 || rotationFlipType == ROTATE_270 );
00578 selectionInterface->setPhoto( editedImagePath, aspectRatioChanged );
00579
00580
00581 getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00582
00583
00584 selectionInterface->getDisplaySize( displayWidth, displayHeight );
00585
00586
00587 if( aspectRatioChanged )
00588 {
00589 selectAspectRatio();
00590 }
00591
00592
00593 scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00594 selectEffect();
00595
00596
00597 emit photoModified();
00598
00599
00600 layout->getWindow()->getStatus()->releaseInput();
00601
00602
00603 qApp->restoreOverrideCursor();
00604 qApp->processEvents();
00605 }
00606
00607 void EditingInterface::screenResolutionChanged()
00608 {
00609
00610 aspectRatioValues[displayResolutionIndex] = qApp->desktop()->screenGeometry().size();
00611
00612
00613 if(aspectRatios->currentItem() == displayResolutionIndex )
00614 { selectAspectRatio(); }
00615 }
00616
00617 void EditingInterface::crop()
00618 {
00619
00620 QPoint topLeft, bottomRight;
00621 if (!findSelection(topLeft, bottomRight) )
00622 return;
00623
00624
00625 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00626
00627
00628 layout->getWindow()->getStatus()->grabInput();
00629
00630
00631 applyImageUpdate( cropImage( photo->getImageFilename(), topLeft, bottomRight ),
00632 true );
00633
00634
00635 layout->getWindow()->getStatus()->releaseInput();
00636
00637
00638 qApp->restoreOverrideCursor();
00639 }
00640
00641 void EditingInterface::enhanceContrast()
00642 {
00643
00644 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00645 qApp->processEvents();
00646
00647
00648 layout->getWindow()->getStatus()->grabInput();
00649
00650
00651 applyImageUpdate( enhanceImageContrast( photo->getImageFilename(),
00652 layout->getWindow()->getStatus() ),
00653 false );
00654
00655
00656 layout->getWindow()->getStatus()->releaseInput();
00657
00658
00659 qApp->restoreOverrideCursor();
00660 qApp->processEvents();
00661 }
00662
00663 void EditingInterface::colorBalance()
00664 {
00665
00666 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00667 qApp->processEvents();
00668
00669
00670 layout->getWindow()->getStatus()->grabInput();
00671
00672
00673 applyImageUpdate( improveColorBalance( photo->getImageFilename(),
00674 layout->getWindow()->getStatus() ),
00675 false );
00676
00677
00678 layout->getWindow()->getStatus()->releaseInput();
00679
00680
00681 qApp->restoreOverrideCursor();
00682 qApp->processEvents();
00683 }
00684
00685 void EditingInterface::removeRedeye()
00686 {
00687
00688 QPoint topLeft, bottomRight;
00689 if (!findSelection(topLeft, bottomRight) )
00690 return;
00691
00692
00693 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00694 qApp->processEvents();
00695
00696
00697 layout->getWindow()->getStatus()->grabInput();
00698
00699
00700 applyImageUpdate( removeRedeyeRegions( photo->getImageFilename(),
00701 topLeft, bottomRight,
00702 layout->getWindow()->getStatus() ),
00703 true );
00704
00705
00706 layout->getWindow()->getStatus()->releaseInput();
00707
00708
00709 qApp->restoreOverrideCursor();
00710 qApp->processEvents();
00711 }
00712
00713 void EditingInterface::tuneLevels()
00714 {
00715
00716
00717 HistogramEditor editor( photo->getImageFilename(), this);
00718 if( editor.exec() )
00719 {
00720
00721 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00722 qApp->processEvents();
00723
00724
00725 layout->getWindow()->getStatus()->grabInput();
00726
00727
00728 applyImageUpdate( editor.getModifiedImage(), false );
00729
00730
00731 layout->getWindow()->getStatus()->releaseInput();
00732
00733
00734 qApp->restoreOverrideCursor();
00735 qApp->processEvents();
00736 }
00737 }
00738
00739 void EditingInterface::adjustGrain()
00740 {
00741
00742
00743 GrainEditor editor( photo->getImageFilename(), this);
00744 if( editor.exec() )
00745 {
00746
00747 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00748 qApp->processEvents();
00749
00750
00751 layout->getWindow()->getStatus()->grabInput();
00752
00753
00754 applyImageUpdate( editor.getModifiedImage(), false );
00755
00756
00757 layout->getWindow()->getStatus()->releaseInput();
00758
00759
00760 qApp->restoreOverrideCursor();
00761 qApp->processEvents();
00762 }
00763 }
00764
00765 void EditingInterface::selectEffect()
00766 {
00767
00768 QImage* editedImage = applyEffect( effectPreviewImageFilename );
00769
00770
00771 effectPreview->setPixmap( QPixmap(*editedImage) );
00772 delete editedImage;
00773 editedImage = NULL;
00774 }
00775
00776 void EditingInterface::applyEffect()
00777 {
00778
00779 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00780 qApp->processEvents();
00781 applyEffectButton->setEnabled(false);
00782
00783
00784 layout->getWindow()->getStatus()->grabInput();
00785
00786
00787 QImage* editedImage = applyEffect( photo->getImageFilename(), true );
00788 applyImageUpdate( editedImage, false );
00789
00790
00791 layout->getWindow()->getStatus()->releaseInput();
00792
00793
00794 qApp->restoreOverrideCursor();
00795 qApp->processEvents();
00796 applyEffectButton->setEnabled(true);
00797 }
00798
00799 QImage* EditingInterface::applyEffect(QString filename, bool useBusyIndicators)
00800 {
00801
00802
00803 StatusWidget* status = NULL;
00804 if(useBusyIndicators) status = layout->getWindow()->getStatus();
00805
00806
00807 QImage* effectedImage = NULL;
00808
00809 if( effectsList->currentItem() == BW_EFFECT )
00810 {
00811 effectedImage = blackWhiteEffect( filename, status );
00812 }
00813 else if( effectsList->currentItem() == SEPIA_EFFECT )
00814 {
00815 effectedImage = sepiaEffect( filename, status );
00816 }
00817 else if( effectsList->currentItem() == INVERT_EFFECT )
00818 {
00819 effectedImage = invertEffect( filename, status );
00820 }
00821 else if( effectsList->currentItem() == EMBOSS_EFFECT )
00822 {
00823 effectedImage = embossEffect( filename, status );
00824 }
00825 else if( effectsList->currentItem() == PAINTING_EFFECT )
00826 {
00827 effectedImage = oilPaintingEffect( filename, status );
00828 }
00829 else if( effectsList->currentItem() == POINTILLISM_EFFECT )
00830 {
00831 effectedImage = pointillismEffect( filename, status );
00832 }
00833
00834
00835 if(useBusyIndicators)
00836 {
00837 status->setStatus( "" );
00838 qApp->processEvents();
00839 }
00840
00841
00842 return effectedImage;
00843 }
00844
00845 void EditingInterface::applyImageUpdate(QImage* editedImage, bool resetSelection)
00846 {
00847
00848
00849 if(editedImage == NULL)
00850 {
00851
00852
00853
00854
00855
00856
00857 if(resetSelection)
00858 {
00859 selectionInterface->selectNone();
00860 }
00861
00862 return;
00863 }
00864
00865
00866 QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
00867
00868
00869
00870
00871
00872 editedImage->save( editedImagePath, "JPEG", 95 );
00873 delete editedImage;
00874 editedImage = NULL;
00875
00876
00877 photo->setImage( editedImagePath );
00878
00879
00880 selectionInterface->setPhoto( editedImagePath, resetSelection );
00881
00882
00883 getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00884
00885
00886 selectionInterface->getDisplaySize( displayWidth, displayHeight );
00887
00888
00889 scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00890 selectEffect();
00891
00892
00893 emit photoModified();
00894 }
00895
00896 void EditingInterface::returnAction()
00897 {
00898
00899 layout->organize();
00900 }
00901
00902 bool EditingInterface::findSelection(QPoint& topLeft, QPoint& bottomRight)
00903 {
00904
00905 selectionInterface->getSelection(topLeft, bottomRight);
00906
00907
00908 if(topLeft.x() >= bottomRight.x() ||
00909 topLeft.y() >= bottomRight.y())
00910 return false;
00911
00912
00913 return true;
00914 }
00915
00916 void EditingInterface::handleSelectionChanged()
00917 {
00918
00919 QPoint topLeft, bottomRight;
00920 bool selectionPresent = findSelection(topLeft,bottomRight);
00921
00922 cropButton->setEnabled( selectionPresent );
00923 redEyeReductionButton->setEnabled( selectionPresent );
00924 }
00925
00926 void EditingInterface::handleAspectRatioChanged()
00927 {
00928
00929 aspectRatios->setCurrentItem(0);
00930 }
00931
00932 void EditingInterface::selectAll(QPoint& topLeft, QPoint& bottomRight)
00933 {
00934 topLeft.setX(0);
00935 topLeft.setY(0);
00936 bottomRight.setX(imageWidth - 1);
00937 bottomRight.setY(imageHeight - 1);
00938 }
00939
00940 void EditingInterface::keyPressEvent( QKeyEvent *e )
00941 {
00942
00943 switch( e->key() )
00944 {
00945
00946 case Qt::Key_Escape:
00947 returnAction();
00948 break;
00949 case Qt::Key_Prior:
00950 showPrevPhoto();
00951 break;
00952 case Qt::Key_Next:
00953 showNextPhoto();
00954 break;
00955 case Qt::Key_Home:
00956 showFirstPhoto();
00957 break;
00958 case Qt::Key_End:
00959 showLastPhoto();
00960 break;
00961 case Qt::Key_R:
00962 if(e->state() & Qt::ControlButton)
00963 rotateRight();
00964 break;
00965 case Qt::Key_L:
00966 if(e->state() & Qt::ControlButton)
00967 rotateLeft();
00968 break;
00969 case Qt::Key_F:
00970 if(e->state() & Qt::ControlButton)
00971 {
00972 if( e->state() & Qt::AltButton )
00973 flipVertical();
00974 else
00975 flipHorizontal();
00976 }
00977 break;
00978 default:
00979 e->ignore();
00980 }
00981 }
00982
00983 bool EditingInterface::currentPhotoRevertable()
00984 {
00985 if(photo == NULL)
00986 return false;
00987 else
00988 return photo->revertPossible();
00989 }
00990
00991 void EditingInterface::revertCurrentPhoto()
00992 {
00993
00994 if( ! currentPhotoRevertable() ) return;
00995
00996
00997 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00998
00999
01000 layout->getWindow()->getStatus()->grabInput();
01001
01002
01003
01004 int origWidth, origHeight;
01005 getImageSize( photo->originalImageFilename(), origWidth, origHeight );
01006 bool resetSelection = (origWidth != imageWidth) || (origHeight != imageHeight);
01007
01009 photo->revertPhoto();
01010
01011
01012 selectionInterface->setPhoto( photo->getImageFilename(), resetSelection );
01013
01014
01015 getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
01016
01017
01018 selectionInterface->getDisplaySize( displayWidth, displayHeight );
01019
01020
01021 scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
01022 selectEffect();
01023
01024
01025 emit photoModified();
01026
01027
01028 layout->getWindow()->getStatus()->releaseInput();
01029
01030
01031 qApp->restoreOverrideCursor();
01032 }
01033
01034 void EditingInterface::setFocus()
01035 {
01036
01037 selectionInterface->setFocus();
01038 }
01039
01040 void EditingInterface::rotateSelection()
01041 {
01042
01043 if(aspectRatios->currentItem() == 0)
01044 {
01045
01046 QPoint curTopLeft, curBottomRight;
01047 selectionInterface->getSelection(curTopLeft, curBottomRight);
01048
01049
01050 QPoint selectionCenter = QPoint( ( curTopLeft.x() + curBottomRight.x() ) / 2,
01051 ( curTopLeft.y() + curBottomRight.y() ) / 2 );
01052
01053
01054 int newWidth = curBottomRight.y() - curTopLeft.y() + 1;
01055 int newHeight =curBottomRight.x() - curTopLeft.x() + 1;
01056 calcScaledImageDimensions( newWidth, newHeight,
01057 imageWidth, imageHeight,
01058 newWidth, newHeight );
01059
01060
01061 QPoint topLeft = QPoint( selectionCenter.x() - newWidth/2,
01062 selectionCenter.y() - newHeight/2 );
01063 QPoint bottomRight = QPoint( topLeft.x() + newWidth - 1,
01064 topLeft.y() + newHeight - 1 );
01065
01066
01067 if(topLeft.x() < 0)
01068 {
01069 bottomRight.setX( bottomRight.x() - topLeft.x() );
01070 topLeft.setX( 0 );
01071 }
01072
01073 if(topLeft.y() < 0)
01074 {
01075 bottomRight.setY( bottomRight.y() - topLeft.y() );
01076 topLeft.setY( 0 );
01077 }
01078
01079 if(bottomRight.x() >= imageWidth )
01080 {
01081 topLeft.setX( topLeft.x() - ( bottomRight.x() - imageWidth + 1 ) );
01082 bottomRight.setX( imageWidth - 1 );
01083 }
01084
01085 if(bottomRight.y() >= imageHeight )
01086 {
01087 topLeft.setY( topLeft.y() - ( bottomRight.y() - imageHeight + 1 ) );
01088 bottomRight.setY( imageHeight - 1 );
01089 }
01090
01091
01092 selectionInterface->setSelection(topLeft, bottomRight);
01093 }
01094
01095
01096 else
01097 {
01098 selectAspectRatio( true );
01099 }
01100 }
01101
01102 void EditingInterface::selectAspectRatio()
01103 {
01104
01105 if( aspectRatios->currentItem() == 0 ) return;
01106
01107
01108
01109 selectAspectRatio(false);
01110 }
01111
01112 void EditingInterface::selectAspectRatio(bool rotateCurAspectRatio)
01113 {
01114
01115 QSize aspectRatio = aspectRatioValues[ aspectRatios->currentItem() ];
01116
01117
01118 if( rotateCurAspectRatio )
01119 {
01120
01121
01122 QPoint curTopLeft, curBottomRight;
01123 selectionInterface->getSelection(curTopLeft, curBottomRight);
01124 if(
01125 ( aspectRatio.width() > aspectRatio.height() &&
01126 curBottomRight.x() - curTopLeft.x() > curBottomRight.y() - curTopLeft.y() ) ||
01127 ( aspectRatio.width() < aspectRatio.height() &&
01128 curBottomRight.x() - curTopLeft.x() < curBottomRight.y() - curTopLeft.y() )
01129 )
01130 {
01131 aspectRatio = QSize( aspectRatio.height(), aspectRatio.width() );
01132 }
01133 }
01134
01135
01136 int selectedWidth = 0;
01137 int selectedHeight = 0;
01138
01139
01140 if(aspectRatios->currentItem() == displayResolutionIndex)
01141 {
01142
01143 selectedWidth = aspectRatio.width();
01144 selectedHeight = aspectRatio.height();
01145 calcScaledImageDimensions( selectedWidth, selectedHeight,
01146 imageWidth, imageHeight,
01147 selectedWidth, selectedHeight );
01148 }
01149
01150 else
01151 {
01152
01153 selectedWidth = imageWidth;
01154 selectedHeight = (int) (((double) (imageWidth * aspectRatio.height()) ) / aspectRatio.width() );
01155 calcScaledImageDimensions( selectedWidth, selectedHeight,
01156 imageWidth, imageHeight,
01157 selectedWidth, selectedHeight );
01158
01159 }
01160
01161
01162 QPoint topLeft, bottomRight;
01163 topLeft.setX( (imageWidth - selectedWidth) / 2 );
01164 topLeft.setY( (imageHeight - selectedHeight) / 2 );
01165 bottomRight.setX( topLeft.x() + selectedWidth - 1 );
01166 bottomRight.setY( topLeft.y() + selectedHeight - 1 );
01167
01168
01169 selectionInterface->setSelection(topLeft, bottomRight, maxDimensions[aspectRatios->currentItem()] );
01170 }
01171
01172 void EditingInterface::startCorrectTilt()
01173 {
01174
01175
01176 correctTiltButton->setEnabled( false );
01177 selectionInterface->enterDrawLineMode();
01178 }
01179
01180 void EditingInterface::finishCorrectTilt( QPoint p1, QPoint p2 )
01181 {
01182
01183 if( p1.x() == -1 || p2.x() == -1 )
01184 {
01185
01186 correctTiltButton->setEnabled( true );
01187 return;
01188 }
01189
01190
01191 qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
01192
01193
01194 layout->getWindow()->getStatus()->grabInput();
01195
01196
01197 QImage* rotatedImage = correctImageTilt( photo->getImageFilename(), p1, p2,
01198 layout->getWindow()->getStatus() );
01199 applyImageUpdate( rotatedImage, true );
01200
01201
01202 correctTiltButton->setEnabled( true );
01203
01204
01205 layout->getWindow()->getStatus()->releaseInput();
01206
01207
01208 qApp->restoreOverrideCursor();
01209 }
01210
01211
01212