Main Page | Namespace List | Class Hierarchy | Class List | 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( 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 Sun Mar 4 19:42:55 2007 for AlbumShaper by doxygen 1.3.7