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

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( QPixmap image, QString details ) : QCustomEvent( UPDATE_PREVIEW_DETAILS )
00044   {
00045     this->image = image;
00046     this->details = details;
00047   }
00048 
00049   //returns the preview image
00050   QPixmap getImage() const { return image; }
00051   
00052   //returns the file details string
00053   QString getDetails() const { return details; }
00054 
00055 private:
00056   QPixmap 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     QPixmap scaledPixmap = QPixmap(NULL);
00112     if( validExtension )
00113     {
00114       QImage scaledImage;
00115       scaleImage(filename, scaledImage, MIN_WIDTH, MIN_HEIGHT );
00116       scaledPixmap.convertFromImage( scaledImage );
00117     }
00118     //------------------------------------------
00119     //Get image resolution
00120     QString imageRes = "";
00121     if(validExtension)
00122     {
00123       QSize res;
00124       getImageSize( filename, res );
00125       imageRes = QString("%1 x %2").arg(res.width()).arg(res.height());
00126     }
00127     //------------------------------------------
00128     //Determine file size and construct a nicely formatted size string
00129     QString fileSize = "?";
00130     QFileInfo info;
00131     info.setFile( filename );
00132     int sizeOnDisk = info.size();
00133     
00134     if(sizeOnDisk < 1024)
00135       fileSize = QString("%1 Byte%2").arg(sizeOnDisk).arg( sizeOnDisk == 0 || sizeOnDisk > 1 ? "s" : "");
00136     else if( sizeOnDisk/1024 < 1024)
00137       //    fileSize = QString("%1 Kb").arg( ((float)*sizeOnDisk)/1024 );
00138       fileSize = QString("%1 Kb").arg( ((float)((100*sizeOnDisk)/1024))/100 );
00139     else if( sizeOnDisk/(1024*1024) < 1024)
00140       fileSize = QString("%1 Mb").arg( ((float)((100*sizeOnDisk)/(1024*1024)))/100 );
00141     else
00142       fileSize = QString("%1 Gigs").arg( ((float)((100*sizeOnDisk)/(1024*1024*1024)))/100 );   
00143     //------------------------------------------
00144     //Setup image details string  
00145     QString fileDetails = QString("%1 %2, %3")
00146                                   .arg(imageRes)
00147                                   .arg(extension)
00148                                   .arg(fileSize);
00149     //------------------------------------------
00150     //Post UPDATE_PREVIEW_DETAILS event
00151     UpdatePreviewEvent* upe = new UpdatePreviewEvent( scaledPixmap, fileDetails );
00152     QApplication::postEvent( previewWidget, upe );
00153     //------------------------------------------
00154     //get lock
00155     lockingMutex.lock();
00156     
00157     //if the queue is empty we're done!
00158     if( queue.isNull() )
00159     {
00160       updating = false;
00161       lockingMutex.unlock();
00162       return; 
00163     }
00164     //clear queue and process pending job
00165     else
00166     {
00167       filename = queue;
00168       queue = QString::null;
00169       lockingMutex.unlock();
00170     }
00171     
00172   } //end while(true)
00173 }
00174 //================================
00175 FilePreview::FilePreview(QWidget* parent) : QWidget(parent) 
00176 {
00177   //create widgets for display preview image and details
00178   filePreview = new QLabel( this );  
00179   fileDetails = new QLabel( this );  
00180   
00181   QGridLayout* grid = new QGridLayout( this, 4, 3 );
00182   grid->setRowStretch( 0, 1 );
00183   grid->addWidget( filePreview, 1, 1, Qt::AlignHCenter );
00184   grid->addWidget( fileDetails, 2, 1, Qt::AlignHCenter );
00185   grid->setRowStretch( 3, 1 );
00186 
00187   grid->setColStretch( 0, 1 );
00188   grid->setColStretch( 2, 1 );
00189  
00190   //create a generator thread that will be used for actually generating 
00191   //preview images and constructing details strings
00192   generatorThread = new GeneratePreviewThread(this);
00193 }
00194 //==============================================
00195 FilePreview::~FilePreview()
00196 {
00197   //make sure generator thread is done!
00198   generatorThread->wait();
00199   delete generatorThread;
00200   generatorThread = NULL;
00201 }
00202 //==============================================
00203 QSize FilePreview::minimumSizeHint () const
00204 {
00205   QFontMetrics fm( font() );
00206   return QSize(MIN_WIDTH, MIN_HEIGHT + 2*fm.height() );
00207 }
00208 //==============================================
00209 void FilePreview::customEvent( QCustomEvent * e )
00210 {
00211   //handle UpdatePrevewEvents that are sent from the worker thread
00212   //by update the preview image and details that are shown
00213   if ( e->type() == UPDATE_PREVIEW_DETAILS ) 
00214   {  
00215     UpdatePreviewEvent* upe = (UpdatePreviewEvent*)e;
00216     filePreview->setPixmap( upe->getImage() );
00217     fileDetails->setText( upe->getDetails() );
00218   }
00219 }
00220 //==============================================
00221 void FilePreview::updatePreview( const QString& filename )
00222 {
00223   //handle requests to update the preview information by asking
00224   //the generator thread to handle them. by using
00225   //an auxiallary thread we can process requests very quickly while
00226   //any current work being done to generate an image preview continues
00227   if( generatorThread != NULL)
00228   {
00229     generatorThread->start( filename );
00230   }
00231 }
00232 //==============================================
00233 AddPhotosDialog::AddPhotosDialog(QString path, QWidget *parent, const char* name ) :
00234                                  QFileDialog(path,
00235                                  tr("Images") + " (*.gif *.jpg *.jpeg *.png *.xpm *.GIF *.JPG *.JPEG *.PNG *.XPM)",
00236                                  parent,name)
00237  {
00238    //setup filter filter and modes
00239    setMode( QFileDialog::ExistingFiles );
00240    setViewMode( QFileDialog::List );
00241  
00242    filePreview = new FilePreview();
00243    setContentsPreviewEnabled( true );
00244    setContentsPreview( filePreview, filePreview );
00245    setPreviewMode( QFileDialog::Contents );
00246    
00247    //create label and checkbox asking user if they want to
00248    //set image descriptions from filenames
00249    setDescriptions = new QCheckBox( tr("Use filenames for descriptions."), this );
00250    setDescriptions->setChecked( false );
00251    addWidgets( NULL, setDescriptions, NULL );
00252 
00253    //set window description
00254   setCaption( tr("Add Photos") );
00255   
00256   connect( this, SIGNAL( fileHighlighted(const QString&)),
00257            this, SLOT( updatePreview(const QString&)) );
00258 }
00259 //==============================================
00260 QStringList AddPhotosDialog::getFilenames(bool& setDescriptionsBool)
00261 {
00262   if( exec() == QDialog::Accepted )
00263   {
00264     setDescriptionsBool = setDescriptions->isChecked();
00265     return selectedFiles();
00266   }
00267   else {  return QStringList(); }
00268 }
00269 //==============================================
00270 void AddPhotosDialog::updatePreview(const QString& filename)
00271 {
00272   filePreview->updatePreview( filename ); 
00273 }
00274 //==============================================

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