Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

editingInterface.cpp

Go to the documentation of this file.
00001 //==============================================
00002 //  copyright            : (C) 2003-2005 by Will Stokes
00003 //==============================================
00004 //  This program is free software; you can redistribute it
00005 //  and/or modify it under the terms of the GNU General
00006 //  Public License as published by the Free Software
00007 //  Foundation; either version 2 of the License, or
00008 //  (at your option) any later version.
00009 //==============================================
00010 
00011 //Systemwide includes
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 //Projectwide includes
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   //create a smaller font for drawing various labels and items
00069   QFont smallerFont = font();
00070   smallerFont.setPointSize( smallerFont.pointSize() - 1 );  
00071 
00072   setFocusPolicy(QWidget::StrongFocus);
00073 
00074   //set photo pointer to null by default
00075   photo = NULL;
00076 
00077   //store layout pointer
00078   layout = (LayoutWidget*)parent;
00079 
00080   //----------  
00081   //Construct photo frame that houses photo being edited and prev and next buttons
00082   QFrame* photoFrame = new QFrame(this, "photoFrame" );
00083   
00084   //Construct the frame that houses all the controls
00085   QFrame* controlsFrame = new QFrame(this, "controlsFrame");
00086 
00087   //Place photo fram and control widgets in a top level grid
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   //Previous photo button
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   //Create widget for displaying and selecting regions of the current photo
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   //Next photo button
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   //Place above widgets in grid, allow seletion interface to take up extra room
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   //construct the frames each set of controls is placed in
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   //layout groups of controls
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   //Frame Controls
00147   //----------    
00148   QFrame* frameControlsFrame = new QFrame( frameControls );
00149  
00150   //-----
00151   //rotate and flip buttons
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   //Place buttons in grid
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   //aspect ratio selection and crop controls
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   //connect signal emitted when screen resolution changes 
00240   //so as to update this stored value (and selction if necessary)
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   //Crop button
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   //Place frame controls in a grid
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   //Enhance Controls
00279   //----------    
00280   QFrame* enhanceControlsFrame = new QFrame( enhanceControls );  
00281   
00282   //setup params for large buttons  
00283   int numLargeButtons = 3;
00284   int curButtonIndex=0;
00285   ClickableLabel** largeButtons = new ClickableLabel*[numLargeButtons];
00286   
00287 
00288   //--------------------
00289   //Frame for semi-automatic enhance controls
00290   QFrame* autoEnhanceControlsFrame = new QFrame( enhanceControlsFrame );  
00291 
00292   //Enhance Color
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   //Enhance Contrast
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   //Remove Red-Eye  
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   //Place semi-automatic enhance controls in grid
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   //Frame for more labor intensive enhance controls
00339   QFrame* manualEnhanceControlsFrame = new QFrame( enhanceControlsFrame );  
00340   
00341   //Tune Levels Button
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   //Adjust Grain Button
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   //Place manual enhance controls in grid
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   //Place enhance controls in a grid
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   //Effects Controls
00379   //----------  
00380   QFrame* manipulateControlsFrame = new QFrame( manipulateControls, "manipulateControlsFrame" );
00381   //--  
00382   //Effects
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 //  effectsList->insertItem( tr("Pointillism") );  
00404 //  POINTILLISM_EFFECT = effectIndex++;
00405   POINTILLISM_EFFECT = -1;
00406    
00407   //Apply effect button
00408   applyEffectButton = new QPushButton( tr("Apply"), manipulateControlsFrame );
00409   applyEffectButton->setFont( smallerFont );  
00410   connect( applyEffectButton, SIGNAL(clicked()), SLOT(applyEffect()) );   
00411   
00412   //preview of seleted effect
00413   effectPreview = new QLabel( manipulateControlsFrame );
00414  
00415   //Place effects controls in a grid
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   //make sure preview image always requires EFFECT_PREVIEW_WIDTH width so contorls don't
00423   //move around when rotating photos
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   //store photo and collection object handles
00434   this->collection = collection;
00435   this->photo = photo;
00436 
00437   //update visibility of prev and next buttons
00438   previousButton->setInvisible( photo->getPrev() == NULL );
00439   nextButton->setInvisible( photo->getNext() == NULL );
00440   
00441   //reset combo menu's back to first entries
00442   aspectRatios->setCurrentItem(0);
00443   effectsList->setCurrentItem(0);
00444 
00445   //update view of photo
00446   selectionInterface->setPhoto( photo->getImageFilename() );  
00447  
00448   //created effect preview image  
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   //get full size photo dimensions
00455   getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00456   
00457   //get display size photo dimensions
00458   selectionInterface->getDisplaySize( displayWidth, displayHeight );
00459 
00460   //disable the crop and reset buttons
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   //set busy pointer
00502   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00503   qApp->processEvents();
00504 
00505   //reset photo object handle
00506   photo = newPhoto;
00507 
00508   //update visibility of prev and next buttons
00509   previousButton->setInvisible( photo->getPrev() == NULL );
00510   nextButton->setInvisible( photo->getNext() == NULL );
00511     
00512   //update view of photo
00513   selectionInterface->setPhoto( photo->getImageFilename() );  
00514 
00515   //created effect preview image  
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   //get full size photo dimensions
00521   getImageSize( photo->getImageFilename(), imageWidth, imageHeight );
00522 
00523   //get display size photo dimensions
00524   selectionInterface->getDisplaySize( displayWidth, displayHeight );
00525 
00526   //auto select region if custom not selected, else select nothing
00527   if(aspectRatios->currentItem() != 0)
00528   { selectAspectRatio(); }
00529   else  
00530   { selectionInterface->setSelection( QPoint(-1,-1), QPoint(-1, -1) ); }
00531   
00532   //emit signal that photo state possibly has changed
00533   emit photoModified();
00534   
00535   //remove busy cursor
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   //set busy pointer
00563   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00564   qApp->processEvents();
00565   
00566   //disable user input
00567   layout->getWindow()->getStatus()->grabInput();
00568   
00569   //rotate image, bail if rotation fails
00570   QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
00571   transformImage( photo->getImageFilename(), editedImagePath, rotationFlipType );
00572 
00573   //apply changes to photo
00574   photo->setImage( editedImagePath );
00575   
00576   //Reload photo view
00577   bool aspectRatioChanged = ( rotationFlipType == ROTATE_90 || rotationFlipType == ROTATE_270 );  
00578   selectionInterface->setPhoto( editedImagePath, aspectRatioChanged );  
00579   
00580   //update image dimension variables
00581   getImageSize( photo->getImageFilename(), imageWidth, imageHeight );  
00582   
00583   //get display size photo dimensions
00584   selectionInterface->getDisplaySize( displayWidth, displayHeight );
00585   
00586   //reapply selected aspect ratio selection if aspect ratio changed
00587   if( aspectRatioChanged )
00588   {
00589     selectAspectRatio();      
00590   }
00591   
00592   //update effect preview
00593   scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00594   selectEffect();
00595   
00596   //emit modified signal
00597   emit photoModified();
00598   
00599   //enable user input
00600   layout->getWindow()->getStatus()->releaseInput();
00601 
00602   //remove busy cursor
00603   qApp->restoreOverrideCursor();
00604   qApp->processEvents();
00605 }
00606 //==============================================
00607 void EditingInterface::screenResolutionChanged()
00608 {
00609   //reset display resolution
00610   aspectRatioValues[displayResolutionIndex] = qApp->desktop()->screenGeometry().size();
00611 
00612   //if user is currently constraining the current selection then reset to fit new display resolution
00613   if(aspectRatios->currentItem() == displayResolutionIndex )
00614   { selectAspectRatio(); }
00615 }
00616 //==============================================
00617 void EditingInterface::crop()
00618 {
00619   //find selection, if empty bail!
00620   QPoint topLeft, bottomRight;
00621   if (!findSelection(topLeft, bottomRight) )
00622     return;
00623 
00624   //set busy cursor
00625   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00626 
00627   //disable user input
00628   layout->getWindow()->getStatus()->grabInput();
00629 
00630   //crop image
00631   applyImageUpdate( cropImage( photo->getImageFilename(), topLeft, bottomRight ),
00632                     true );
00633 
00634   //enable user input
00635   layout->getWindow()->getStatus()->releaseInput();
00636 
00637   //remove busy cursor
00638   qApp->restoreOverrideCursor();
00639 }
00640 //==============================================
00641 void EditingInterface::enhanceContrast()
00642 {
00643   //set busy cursor
00644   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00645   qApp->processEvents();
00646 
00647   //disable user input
00648   layout->getWindow()->getStatus()->grabInput();
00649 
00650   //enhance image
00651   applyImageUpdate( enhanceImageContrast( photo->getImageFilename(),
00652                                           layout->getWindow()->getStatus() ),
00653                     false );
00654 
00655   //enable user input
00656   layout->getWindow()->getStatus()->releaseInput();
00657 
00658   //remove busy cursor
00659   qApp->restoreOverrideCursor();
00660   qApp->processEvents();
00661 }
00662 //==============================================
00663 void EditingInterface::colorBalance()
00664 {
00665   //set busy cursor
00666   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00667   qApp->processEvents();
00668 
00669   //disable user input
00670   layout->getWindow()->getStatus()->grabInput();
00671 
00672   //improve color balance
00673   applyImageUpdate( improveColorBalance( photo->getImageFilename(),
00674                                          layout->getWindow()->getStatus() ),
00675                     false );
00676 
00677   //enable user input
00678   layout->getWindow()->getStatus()->releaseInput();
00679 
00680   //remove busy cursor
00681   qApp->restoreOverrideCursor();
00682   qApp->processEvents();
00683 }
00684 //==============================================
00685 void EditingInterface::removeRedeye()
00686 {
00687   //find selection, if empty bail!
00688   QPoint topLeft, bottomRight;
00689   if (!findSelection(topLeft, bottomRight) )
00690     return;
00691 
00692   //set busy cursor
00693   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00694   qApp->processEvents();
00695   
00696   //disable user input
00697   layout->getWindow()->getStatus()->grabInput();
00698 
00699   //remove redeye image
00700   applyImageUpdate( removeRedeyeRegions( photo->getImageFilename(), 
00701                                          topLeft, bottomRight,
00702                                          layout->getWindow()->getStatus() ),
00703                     true );
00704 
00705   //enable user input
00706   layout->getWindow()->getStatus()->releaseInput();
00707 
00708   //remove busy cursor
00709   qApp->restoreOverrideCursor();
00710   qApp->processEvents();
00711 }
00712 //==============================================
00713 void EditingInterface::tuneLevels()
00714 {
00715   //load photo in histogram editor
00716   //if changes took place update image
00717   HistogramEditor editor( photo->getImageFilename(), this);
00718   if( editor.exec() ) 
00719   { 
00720     //set busy cursor
00721     qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00722     qApp->processEvents();
00723 
00724     //disable user input
00725     layout->getWindow()->getStatus()->grabInput();
00726 
00727     //update image    
00728     applyImageUpdate( editor.getModifiedImage(), false ); 
00729 
00730     //enable user input
00731     layout->getWindow()->getStatus()->releaseInput();
00732 
00733     //remove busy cursor
00734     qApp->restoreOverrideCursor();
00735     qApp->processEvents();
00736   }
00737 }
00738 //==============================================
00739 void EditingInterface::adjustGrain()
00740 {
00741   //load photo in grain editor
00742   //if changes took place update image
00743   GrainEditor editor( photo->getImageFilename(), this);
00744   if( editor.exec() ) 
00745   { 
00746     //set busy cursor
00747     qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00748     qApp->processEvents();
00749     
00750     //disable user input
00751     layout->getWindow()->getStatus()->grabInput();
00752 
00753     //update image    
00754     applyImageUpdate( editor.getModifiedImage(), false ); 
00755     
00756     //enable user input
00757     layout->getWindow()->getStatus()->releaseInput();
00758 
00759     //remove busy cursor
00760     qApp->restoreOverrideCursor();
00761     qApp->processEvents();
00762   }
00763 }
00764 //==============================================
00765 void EditingInterface::selectEffect()
00766 {  
00767   //apply effect on preview image
00768   QImage* editedImage = applyEffect( effectPreviewImageFilename );
00769 
00770   //refresh displayed preview image
00771   effectPreview->setPixmap( QPixmap(*editedImage) );
00772   delete editedImage;
00773   editedImage = NULL;  
00774 }
00775 //==============================================
00776 void EditingInterface::applyEffect()
00777 {  
00778   //set busy cursor and disable apply button
00779   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00780   qApp->processEvents();
00781   applyEffectButton->setEnabled(false);
00782 
00783   //disable user input
00784   layout->getWindow()->getStatus()->grabInput();
00785 
00786   //apply effect
00787   QImage* editedImage = applyEffect( photo->getImageFilename(), true );
00788   applyImageUpdate( editedImage, false );
00789   
00790   //enable user input
00791   layout->getWindow()->getStatus()->releaseInput();
00792 
00793   //remove busy cursor and reenable apply button
00794   qApp->restoreOverrideCursor();
00795   qApp->processEvents();
00796   applyEffectButton->setEnabled(true);
00797 } 
00798 //==============================================
00799 QImage* EditingInterface::applyEffect(QString filename, bool useBusyIndicators)
00800 {
00801   //setup pointer to status widget. if status updates are not being provided
00802   //(when the preview interface is being updated) simply leave this pointing to NULL
00803   StatusWidget* status = NULL;
00804   if(useBusyIndicators) status = layout->getWindow()->getStatus();
00805   
00806   //apply effect
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   //remove status bar if present
00835   if(useBusyIndicators)
00836   {
00837     status->setStatus( "" );
00838     qApp->processEvents();
00839   }
00840 
00841   //return effected image
00842   return effectedImage;
00843 }
00844 //==============================================
00845 void EditingInterface::applyImageUpdate(QImage* editedImage, bool resetSelection)
00846 {  
00847   //skip apply step if pointer is null. this usually means
00848   //no modifications were made (for example: no red eyes were detected)
00849   if(editedImage == NULL) 
00850   { 
00851     //sometimes the user instructs the program to modify an image in a way
00852     //where no real changes are actually necessary. case in point, red eye reduction
00853     //on a region where there is no red stuff at all! in order to be consistant, if
00854     //the user is expecting the selection to be reset then always reset it! this
00855     //normally occurs below when resetting the photo but we'll do it here 
00856     //since resetting the photo will not take place
00857     if(resetSelection) 
00858     { 
00859       selectionInterface->selectNone(); 
00860     }
00861     
00862     return; 
00863   }
00864   
00865   //construct edited image path
00866   QString editedImagePath = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() + "/editedImage.jpg";
00867 
00868   //save edited image to temporary location
00869   //TODO: EXIF information is lost at this point, Qt does not support
00870   //storing exif information, but perhaps a 2nd pass can be made on the file
00871   //where exif info is added using libjpeg functions?
00872   editedImage->save( editedImagePath, "JPEG", 95 );
00873   delete editedImage;
00874   editedImage = NULL;
00875     
00876   //apply changes to photo
00877   photo->setImage( editedImagePath );
00878   
00879   //Reload photo view
00880   selectionInterface->setPhoto( editedImagePath, resetSelection );  
00881   
00882   //update image dimension variables
00883   getImageSize( photo->getImageFilename(), imageWidth, imageHeight );  
00884 
00885   //get display size photo dimensions
00886   selectionInterface->getDisplaySize( displayWidth, displayHeight );
00887 
00888   //update effect preview
00889   scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
00890   selectEffect();
00891   
00892   //emit modified signal
00893   emit photoModified();
00894 }
00895 //==============================================
00896 void EditingInterface::returnAction()
00897 {
00898   //exit edit mode
00899   layout->organize();
00900 }
00901 //==============================================
00902 bool EditingInterface::findSelection(QPoint& topLeft, QPoint& bottomRight)
00903 {
00904   //get raw selection in display coordinates
00905   selectionInterface->getSelection(topLeft, bottomRight);
00906 
00907   //if range is empty then retrun false
00908   if(topLeft.x() >= bottomRight.x() ||
00909      topLeft.y() >= bottomRight.y())
00910     return false;
00911   
00912   //return success
00913   return true;
00914 }
00915 //==============================================
00916 void EditingInterface::handleSelectionChanged()
00917 {
00918   //crop button is enabled only when a portion of the image is selected
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   //change aspect ratio combo box to custom
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   //next handle additional keys
00943   switch( e->key() )
00944   {
00945     //apply changes and exit
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   //if current photo not revertable immediately bail
00994   if( ! currentPhotoRevertable() ) return;
00995   
00996   //set busy cursor
00997   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
00998   
00999   //disable user input
01000   layout->getWindow()->getStatus()->grabInput();
01001 
01002   //get current and reverted image sizes and compare to see if size has changed.
01003   //if so reset selected region
01004   int origWidth, origHeight;
01005   getImageSize( photo->originalImageFilename(), origWidth, origHeight );  
01006   bool resetSelection = (origWidth != imageWidth) || (origHeight != imageHeight);
01007   
01009   photo->revertPhoto();
01010 
01011   //Reload photo view
01012   selectionInterface->setPhoto( photo->getImageFilename(), resetSelection );  
01013   
01014   //update image dimension variables
01015   getImageSize( photo->getImageFilename(), imageWidth, imageHeight );  
01016   
01017   //get display size photo dimensions
01018   selectionInterface->getDisplaySize( displayWidth, displayHeight );
01019   
01020   //update effect preview
01021   scaleImage( photo->getImageFilename(), effectPreviewImageFilename, EFFECT_PREVIEW_WIDTH, EFFECT_PREVIEW_HEIGHT );
01022   selectEffect();  
01023   
01024   //emit modified signal
01025   emit photoModified();
01026 
01027   //enable user input
01028   layout->getWindow()->getStatus()->releaseInput();
01029 
01030   //remove busy cursor
01031   qApp->restoreOverrideCursor();
01032 }
01033 //==============================================
01034 void EditingInterface::setFocus()
01035 {
01036   //always pass off focus even to selection interface so it can get key strokes
01037   selectionInterface->setFocus();
01038 }
01039 //==============================================
01040 void EditingInterface::rotateSelection()
01041 {
01042   //rotate custom selection in place, scale/shift if necessary to keep on image
01043   if(aspectRatios->currentItem() == 0)
01044   {
01045     //get cur selection
01046     QPoint curTopLeft, curBottomRight;
01047     selectionInterface->getSelection(curTopLeft, curBottomRight); 
01048 
01049     //find center
01050     QPoint selectionCenter = QPoint( ( curTopLeft.x() + curBottomRight.x() ) / 2,
01051                                      ( curTopLeft.y() + curBottomRight.y() ) / 2 );    
01052 
01053     //scale rotated width/height to fit image
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     //center new selection over old selection
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     //shift selection area to not go outside image boundary
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     //select new region
01092     selectionInterface->setSelection(topLeft, bottomRight);    
01093   }
01094   //else call selectAspectRatio passing true that we're
01095   //using the rotated version of the current aspect ratio
01096   else
01097   { 
01098     selectAspectRatio( true ); 
01099   }
01100 }
01101 //==============================================
01102 void EditingInterface::selectAspectRatio()
01103 {
01104   //if user selected "custom" don't modify current selection
01105   if( aspectRatios->currentItem() == 0 ) return;
01106   
01107   //when the user selects an aspect ratio we 
01108   //always use the default aspect ratio
01109   selectAspectRatio(false);
01110 }
01111 //==============================================
01112 void EditingInterface::selectAspectRatio(bool rotateCurAspectRatio)
01113 {
01114   //get default aspect ratio
01115   QSize aspectRatio = aspectRatioValues[ aspectRatios->currentItem() ];  
01116 
01117   //if we're rotating the current selection, see if the aspect ratio needs to be flipped
01118   if( rotateCurAspectRatio )
01119   {
01120     //if current aspect ratio and default aspect ratio agree then
01121     //swap to use rotated version
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   //determine selected width and height;
01136   int selectedWidth = 0; 
01137   int selectedHeight = 0;
01138   
01139   //display resolution, match exactly or scale down
01140   if(aspectRatios->currentItem() == displayResolutionIndex)
01141   {    
01142     //select region less than or equal to display resolution while maintaining aspect ratio
01143     selectedWidth = aspectRatio.width();
01144     selectedHeight = aspectRatio.height();
01145     calcScaledImageDimensions( selectedWidth, selectedHeight,
01146                                imageWidth, imageHeight,
01147                                selectedWidth, selectedHeight );
01148   }
01149   //else use aspect ratio directly as a ratio
01150   else
01151   {  
01152     //select region using same aspect ratio
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   //center selection
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   //update selection
01169   selectionInterface->setSelection(topLeft, bottomRight, maxDimensions[aspectRatios->currentItem()] );    
01170 } 
01171 //==============================================
01172 void EditingInterface::startCorrectTilt()
01173 {
01174   //instruct user to select a horizontal or vertical line in the image by
01175   //beginning draw line mode in the selection interface
01176   correctTiltButton->setEnabled( false );
01177   selectionInterface->enterDrawLineMode();
01178 }
01179 //==============================================
01180 void EditingInterface::finishCorrectTilt( QPoint p1, QPoint p2 )
01181 {
01182   //if either point is invalid ignore action
01183   if( p1.x() == -1 || p2.x() == -1 )
01184   {
01185     //reenable tilt button
01186     correctTiltButton->setEnabled( true );
01187     return;
01188   }
01189   
01190   //set busy cursor
01191   qApp->setOverrideCursor( QCursor(Qt::WaitCursor));
01192   
01193   //disable user input
01194   layout->getWindow()->getStatus()->grabInput();
01195   
01196   //rotate image by determining correct angle from two points
01197   QImage* rotatedImage = correctImageTilt( photo->getImageFilename(), p1, p2,
01198                                            layout->getWindow()->getStatus() );
01199   applyImageUpdate( rotatedImage, true );
01200   
01201   //reenable tilt button
01202   correctTiltButton->setEnabled( true );
01203 
01204   //enable user input
01205   layout->getWindow()->getStatus()->releaseInput();
01206 
01207   //remove busy cursor
01208   qApp->restoreOverrideCursor();
01209 }
01210 //==============================================
01211 
01212 

Generated on Sat Apr 2 05:44:04 2005 for AlbumShaper by  doxygen 1.3.9.1