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