addPhotosDialog.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 <qlabel.h>
00013 #include <qfiledialog.h>
00014 #include <qcheckbox.h>
00015 #include <qlayout.h>
00016 #include <qpixmap.h>
00017 #include <qimage.h>
00018 #include <qlayout.h>
00019 #include <qfileinfo.h>
00020 #include <qmutex.h>
00021 #include <qthread.h>
00022 #include <qevent.h>
00023 #include <qapplication.h>
00024 
00025 //Projectwide includes
00026 #include "addPhotosDialog.h"
00027 #include "../../config.h"
00028 #include "../../backend/tools/imageTools.h"
00029 
00030 #define MIN_WIDTH 240
00031 #define MIN_HEIGHT 180
00032 
00033 #define UPDATE_PREVIEW_DETAILS QEvent::User
00034 
00035 //================================
00036 //Qt requires us to pass information for GUI posting from the worker thread to the 
00037 //GUI thread via events as opposed to directly posting the events ourselves. in order
00038 //to update the file preview we'll construct custom UpdatePreviewEvents that contain
00039 //the updated preview image and file details.
00040 class UpdatePreviewEvent : public QCustomEvent
00041 {
00042 public:
00043   UpdatePreviewEvent( QImage image, QString details ) : QCustomEvent( UPDATE_PREVIEW_DETAILS )
00044   {
00045     this->image = image;
00046     this->details = details;
00047   }
00048 
00049   //returns the preview image
00050   QImage getImage() const { return image; }
00051   
00052   //returns the file details string
00053   QString getDetails() const { return details; }
00054 
00055 private:
00056   QImage image;
00057   QString details;
00058 };
00059 //================================
00060 GeneratePreviewThread::GeneratePreviewThread( FilePreview* previewWidget )
00061 {
00062   //we'll need to store a previewWidget handle to 
00063   //posting update events when updates are
00064   //ready to be shown
00065   this->previewWidget = previewWidget;
00066 
00067   //by default worker thread isn't busy yet
00068   updating = false;
00069   queue = QString::null;
00070 }
00071 //================================
00072 void GeneratePreviewThread::start( QString filename )
00073 {
00074   //get lock
00075   lockingMutex.lock();
00076   
00077   //if currently animating then append job to queue
00078   if(updating)
00079   {
00080     queue = filename;
00081     lockingMutex.unlock();
00082     return; 
00083   }
00084   //else set animating to true, actually initiate job
00085   else
00086   {
00087     updating = true;
00088     this->filename = filename;
00089     lockingMutex.unlock();
00090     QThread::start();
00091   }
00092 }
00093 //================================
00094 void GeneratePreviewThread::run()
00095 {
00096   //since it is possible for another job
00097   //to be added to the queue while processing this one, it is necessary
00098   //to loop until the queue is empty
00099   while(true)
00100   {
00101     //------------------------------------------
00102     //Get image type extension and convert to caps  
00103     QString extension = QFileInfo(filename).extension(false).upper();
00104     bool validExtension = ( (extension.compare("GIF") == 0) ||
00105                             (extension.compare("JPG") == 0) ||
00106                             (extension.compare("JPEG") == 0) ||
00107                             (extension.compare("PNG") == 0) ||
00108                             (extension.compare("XPM") == 0) );
00109     //------------------------------------------
00110     //Scale the image to fit nicely on the screen, aka < 300x225
00111     QImage scaledImage;
00112     if( validExtension )
00113     {
00114       scaleImage(filename, scaledImage, MIN_WIDTH, MIN_HEIGHT );
00115     }
00116     //------------------------------------------
00117     //Get image resolution
00118     QString imageRes = "";
00119     if(validExtension)
00120     {
00121       QSize res;
00122       getImageSize( filename, res );
00123       imageRes = QString("%1 x %2").arg(res.width()).arg(res.height());
00124     }
00125     //------------------------------------------
00126     //Determine file size and construct a nicely formatted size string
00127     QString fileSize = "?";
00128     QFileInfo info;
00129     info.setFile( filename );
00130     int sizeOnDisk = info.size();
00131     
00132     if(sizeOnDisk < 1024)
00133       fileSize = QString("%1 Byte%2").arg(sizeOnDisk).arg( sizeOnDisk == 0 || sizeOnDisk > 1 ? "s" : "");
00134     else if( sizeOnDisk/1024 < 1024)
00135       //    fileSize = QString("%1 Kb").arg( ((float)*sizeOnDisk)/1024 );
00136       fileSize = QString("%1 Kb").arg( ((float)((100*sizeOnDisk)/1024))/100 );
00137     else if( sizeOnDisk/(1024*1024) < 1024)
00138       fileSize = QString("%1 Mb").arg( ((float)((100*sizeOnDisk)/(1024*1024)))/100 );
00139     else
00140       fileSize = QString("%1 Gigs").arg( ((float)((100*sizeOnDisk)/(1024*1024*1024)))/100 );   
00141     //------------------------------------------
00142     //Setup image details string  
00143     QString fileDetails = QString("%1 %2, %3")
00144                                   .arg(imageRes)
00145                                   .arg(extension)
00146                                   .arg(fileSize);
00147     //------------------------------------------
00148     //Post UPDATE_PREVIEW_DETAILS event
00149     UpdatePreviewEvent* upe = new UpdatePreviewEvent( scaledImage, fileDetails );
00150     QApplication::postEvent( previewWidget, upe );
00151     //------------------------------------------
00152     //get lock
00153     lockingMutex.lock();
00154     
00155     //if the queue is empty we're done!
00156     if( queue.isNull() )
00157     {
00158       updating = false;
00159       lockingMutex.unlock();
00160       return; 
00161     }
00162     //clear queue and process pending job
00163     else
00164     {
00165       filename = queue;
00166       queue = QString::null;
00167       lockingMutex.unlock();
00168     }
00169     
00170   } //end while(true)
00171 }
00172 //================================
00173 FilePreview::FilePreview(QWidget* parent) : QWidget(parent) 
00174 {
00175   //create widgets for display preview image and details
00176   filePreview = new QLabel( this );  
00177   fileDetails = new QLabel( this );  
00178   
00179   QGridLayout* grid = new QGridLayout( this, 4, 3 );
00180   grid->setRowStretch( 0, 1 );
00181   grid->addWidget( filePreview, 1, 1, Qt::AlignHCenter );
00182   grid->addWidget( fileDetails, 2, 1, Qt::AlignHCenter );
00183   grid->setRowStretch( 3, 1 );
00184 
00185   grid->setColStretch( 0, 1 );
00186   grid->setColStretch( 2, 1 );
00187  
00188   //create a generator thread that will be used for actually generating 
00189   //preview images and constructing details strings
00190   generatorThread = new GeneratePreviewThread(this);
00191 }
00192 //==============================================
00193 FilePreview::~FilePreview()
00194 {
00195   //make sure generator thread is done!
00196   generatorThread->wait();
00197   delete generatorThread;
00198   generatorThread = NULL;
00199 }
00200 //==============================================
00201 QSize FilePreview::minimumSizeHint () const
00202 {
00203   QFontMetrics fm( font() );
00204   return QSize(MIN_WIDTH, MIN_HEIGHT + 2*fm.height() );
00205 }
00206 //==============================================
00207 void FilePreview::customEvent( QCustomEvent * e )
00208 {
00209   //handle UpdatePrevewEvents that are sent from the worker thread
00210   //by update the preview image and details that are shown
00211   if ( e->type() == UPDATE_PREVIEW_DETAILS ) 
00212   {  
00213     UpdatePreviewEvent* upe = (UpdatePreviewEvent*)e;
00214 
00215     if( !upe->getImage().isNull() )
00216     {
00217       QPixmap scaledPixmap;
00218       scaledPixmap.convertFromImage( upe->getImage() );
00219       filePreview->setPixmap( scaledPixmap );
00220     }
00221     
00222     fileDetails->setText( upe->getDetails() );
00223   }
00224 }
00225 //==============================================
00226 void FilePreview::updatePreview( const QString& filename )
00227 {
00228   //handle requests to update the preview information by asking
00229   //the generator thread to handle them. by using
00230   //an auxiallary thread we can process requests very quickly while
00231   //any current work being done to generate an image preview continues
00232   if( generatorThread != NULL)
00233   {
00234     generatorThread->start( filename );
00235   }
00236 }
00237 //==============================================
00238 AddPhotosDialog::AddPhotosDialog(QString path, QWidget *parent, const char* name ) :
00239                                  QFileDialog(path,
00240                                  tr("Images") + " (*.gif *.jpg *.jpeg *.png *.xpm *.GIF *.JPG *.JPEG *.PNG *.XPM)",
00241                                  parent,name)
00242  {
00243    //setup filter filter and modes
00244    setMode( QFileDialog::ExistingFiles );
00245    setViewMode( QFileDialog::List );
00246  
00247    filePreview = new FilePreview();
00248    setContentsPreviewEnabled( true );
00249    setContentsPreview( filePreview, filePreview );
00250    setPreviewMode( QFileDialog::Contents );
00251    
00252    //create label and checkbox asking user if they want to
00253    //set image descriptions from filenames
00254    setDescriptions = new QCheckBox( tr("Use filenames for descriptions."), this );
00255    setDescriptions->setChecked( false );
00256    addWidgets( NULL, setDescriptions, NULL );
00257 
00258    //set window description
00259   setCaption( tr("Add Photos") );
00260   
00261   connect( this, SIGNAL( fileHighlighted(const QString&)),
00262            this, SLOT( updatePreview(const QString&)) );
00263 }
00264 //==============================================
00265 QStringList AddPhotosDialog::getFilenames(bool& setDescriptionsBool)
00266 {
00267   if( exec() == QDialog::Accepted )
00268   {
00269     setDescriptionsBool = setDescriptions->isChecked();
00270     return selectedFiles();
00271   }
00272   else {  return QStringList(); }
00273 }
00274 //==============================================
00275 void AddPhotosDialog::updatePreview(const QString& filename)
00276 {
00277   filePreview->updatePreview( filename ); 
00278 }
00279 //==============================================

Generated on Wed Jan 24 05:38:05 2007 for AlbumShaper by  doxygen 1.5.1