Main Page   Compound List   File List   Compound Members   File Members  

album.cpp

Go to the documentation of this file.
00001 //==============================================
00002 //  copyright            : (C) 2003 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 //  As a special exception, Will Stokes gives permission to 
00011 //  link this program with Qt non-commercial edition, and 
00012 //  distribute the resulting executable, without including the 
00013 //  source code for the Qt non-commercial edition in the 
00014 //  source distribution. 
00015 //==============================================
00016 
00017 //Systemwide includes
00018 #include <qimage.h>
00019 #include <qpixmap.h>
00020 #include <qstring.h>
00021 #include <time.h>
00022 #include <qfile.h>
00023 #include <qfileinfo.h>
00024 #include <qtextstream.h>
00025 #include <qdom.h>
00026 #include <qdir.h>
00027 
00028 //Projectwide includes
00029 #include "album.h"
00030 #include "subalbum.h"
00031 #include "photo.h"
00032 #include "imageTools.h"
00033 #include "xmlTools.h"
00034 #include "md5.h"
00035 #include "../gui/saveDialog.h"
00036 #include "../gui/loadDialog.h"
00037 #include "../gui/subalbumPreviewWidget.h"
00038 #include "../config.h"
00039 
00040 #include <iostream.h>
00041 //==============================================
00043 Album::Album()
00044 {
00045   //set strings to default values
00046   name = "";
00047   description ="";
00048   author = "";
00049 
00050   //by default no representative image
00051   smallRepresentativeImage = new QPixmap( QString(IMAGE_PATH)+"notSpecified.png" );
00052   largeRepresentativeImage = NULL;
00053   
00054   //no Subalbums by default
00055   firstSubalbum = NULL;
00056   lastSubalbum = NULL;
00057 
00058   //set last modification date to today
00059   updateModificationDate();
00060   
00061   //no subalbums
00062   numSubalbums = 0;
00063   numLoadedSubalbums = 0;
00064   
00065   //not previously saved by default
00066   savedToDisk = false;
00067   
00068   //construct temp directory to save images to
00069   QDir rootDir( QDir::homeDirPath() );
00070   if(!rootDir.exists( ".albumShaper" ))
00071   {
00072     rootDir.mkdir( ".albumShaper" );
00073   }
00074   rootDir.cd( ".albumShaper" );
00075   if(!rootDir.exists( "tmp" ))
00076   {
00077     rootDir.mkdir( "tmp" );
00078   }
00079   saveLocation = QDir::homeDirPath() + "/.albumShaper/tmp";  
00080 }
00081 //==============================================
00083 Album::~Album()    
00084 {
00085   //delete representative image
00086   delete smallRepresentativeImage;
00087   delete largeRepresentativeImage;
00088   
00089   //delete subalbums  
00090   Subalbum* current = firstSubalbum;
00091   Subalbum* temp;
00092   while(current != NULL)
00093   {
00094     temp = current->getNext();
00095     delete current;
00096     current = temp;
00097   }
00098 } 
00099 //==============================================
00101 void Album::setName(QString val)
00102 {
00103   name = val;
00104 }
00105 //==============================================
00107 QString Album::getName()
00108 {
00109   return QString(name);
00110 }
00111 //==============================================
00113 void Album::setDescription(QString val)
00114 {
00115   description = val;
00116 }
00117 //==============================================
00119 QString Album::getDescription()
00120 {
00121   return QString(description);
00122 }
00123 //==============================================
00125 void Album::setAuthor(QString val)
00126 {
00127   author = val;
00128 }
00129 //==============================================
00131 QString Album::getAuthor()
00132 {
00133   return QString(author);
00134 }
00135 //==============================================
00137 void Album::setRepresentativeImages(QImage* rawImage)
00138 {
00139   //---------------------------------------------------------    
00140   //delete representative images
00141   delete smallRepresentativeImage;
00142   delete largeRepresentativeImage;
00143   //---------------------------------------------------------    
00144   //compute representative image sizes
00145   int smallRepWidth = 0;
00146   int smallRepHeight = 0;
00147   int largeRepWidth = 0;
00148   int largeRepHeight = 0;
00149   resizeImage( rawImage->width(), rawImage->height(),
00150                107, 80,
00151                smallRepWidth, smallRepHeight);
00152   resizeImage( rawImage->width(), rawImage->height(),
00153                500, 320,
00154                largeRepWidth, largeRepHeight);
00155   //---------------------------------------------------------    
00156   //create various representative images
00157   //---------------------------------------------------------    
00158   //copy and scale small version
00159   QImage thumbnailSmall = rawImage->smoothScale( smallRepWidth, smallRepHeight );
00160   thumbnailSmall.setAlphaBuffer(true);
00161   smallRepresentativeImage = new QPixmap( smallRepWidth, smallRepHeight );
00162   smallRepresentativeImage->convertFromImage( thumbnailSmall );  
00163 
00164   //copy and scale large version
00165   QImage thumbnailLarge = rawImage->smoothScale( largeRepWidth, largeRepHeight );
00166   thumbnailLarge.setAlphaBuffer(true);
00167   largeRepresentativeImage = new QPixmap( largeRepWidth, largeRepHeight );
00168   largeRepresentativeImage->convertFromImage( thumbnailLarge );  
00169 }
00170 //==============================================
00172 QPixmap* Album::getRepresentativeImage(int size)
00173 {
00174   if(size == SMALL)
00175     return smallRepresentativeImage;
00176   else if(size == LARGE)
00177     return largeRepresentativeImage;
00178   else
00179     return NULL;
00180 }
00181 //==============================================
00183 Subalbum* Album::getFirstSubalbum()
00184 {
00185   return firstSubalbum;
00186 }
00187 //==============================================
00189 Subalbum* Album::getLastSubalbum()
00190 {
00191   return lastSubalbum;
00192 }
00193 //==============================================
00194 void Album::appendSubalbum(Subalbum* val)
00195 {
00196   numSubalbums++;
00197   
00198   //first subalbum
00199   if(firstSubalbum == NULL)
00200   {
00201     firstSubalbum = val;
00202     lastSubalbum = val;
00203   }
00204   //append to end of list
00205   else
00206   {
00207     lastSubalbum->setNext( val );
00208     lastSubalbum = val;
00209   }
00210 }
00211 //==============================================
00212 void Album::removeSubalbum(Subalbum* val)
00213 {
00214   //search through linked list and remove item
00215   Subalbum* prev = NULL;
00216   Subalbum* current = firstSubalbum;
00217   while(current != NULL)
00218   {
00219     //found it! remove it
00220     if(current == val)
00221     { 
00222       //update first pointer
00223       if(firstSubalbum == val)
00224         firstSubalbum = val->getNext();
00225       
00226       //update last pointer
00227       if(lastSubalbum == val) 
00228         lastSubalbum = prev;
00229 
00230       //update next pointer
00231       if(prev != NULL)
00232         prev->setNext( current->getNext() );
00233             
00234       //delete object
00235       delete val;
00236       val = NULL;
00237       numSubalbums--;
00238       return;
00239     }
00240     
00241     prev = current;
00242     current = current->getNext();
00243   }
00244 
00245 }
00246 //==============================================
00248 int Album::getModificationYear()
00249 {
00250   return modificationYear;
00251 }
00252 //==============================================
00254 int Album::getModificationMonth()
00255 {
00256   return modificationMonth;
00257 }
00258 //==============================================
00260 int Album::getModificationDay()
00261 {
00262   return modificationDay;
00263 }
00264 //==============================================
00266 void Album::updateModificationDate()
00267 {
00268   //set last modification date to today
00269   struct tm *newtime;
00270   time_t aclock;
00271 
00272   //get time in seconds
00273   time( &aclock ); 
00274 
00275   //convert to tm form
00276   newtime = localtime( &aclock );
00277 
00278   //set year, month, and day
00279   modificationYear = newtime->tm_year + 1900;
00280   modificationMonth = newtime->tm_mon + 1;
00281   modificationDay = newtime->tm_mday;
00282 }
00283 //==============================================
00284 void Album::importFromDisk(LoadDialog* dialog, QString fileName)
00285 {
00286   dialog->printMessage("Parsing XML");
00287   
00288   //open file
00289   QFile albumFile( fileName );
00290   if( !albumFile.open( IO_ReadOnly ) )
00291   {
00292     cout << "Error! Unable to open file!\n";
00293     return;
00294   }
00295   
00296   //parse dom
00297   QDomDocument albumDom;
00298   if( !albumDom.setContent( &albumFile ) )
00299   {
00300     cout << "Error! Unable to construct DOM!\n";
00301     return;  
00302   }
00303 
00304   //close file
00305   albumFile.close();
00306 
00307   //get main directory all other files and subdirectories are in  
00308   QString rootDir = QFileInfo(albumFile).dirPath(TRUE);
00309   saveLocation = rootDir + "/img";
00310   
00311   
00312   //if representative image exists load
00313   QImage repImage(rootDir + "/img/album.jpg");
00314   if(!repImage.isNull())
00315   {
00316     setRepresentativeImages(&repImage);  
00317   }  
00318 
00319   int subalbumNum = 0;
00320   
00321   //get root node and start parsing DOM
00322   QDomElement root = albumDom.documentElement();
00323   QDomNode node = root.firstChild();
00324   QDomText val;  
00325   while( !node.isNull() )
00326   {
00327     //------------------------------------------------------------
00328     //album name
00329     if( node.isElement() && node.nodeName() == "name" )
00330     { 
00331       val = node.firstChild().toText();
00332       if(!val.isNull())
00333         name = val.nodeValue();
00334     }
00335     //------------------------------------------------------------
00336     //album description
00337     else if( node.isElement() && node.nodeName() == "description" )
00338     { 
00339       val = node.firstChild().toText();
00340       if(!val.isNull())
00341         description = val.nodeValue();
00342     }
00343     //------------------------------------------------------------
00344     //album author
00345     else if( node.isElement() && node.nodeName() == "author" )
00346     { 
00347       val = node.firstChild().toText();
00348       if(!val.isNull())
00349         author = val.nodeValue();
00350     }
00351     //------------------------------------------------------------
00352     //album modification date
00353     else if( node.isElement() && node.nodeName() == "modified" )
00354     {     
00355       QDomNode childNode = node.firstChild();
00356       bool ok;
00357       int intVal;
00358       while( !childNode.isNull() )
00359       {
00360         //------------------------------------------------------------
00361         if( childNode.isElement() && childNode.nodeName() == "year" )
00362         {
00363           val = childNode.firstChild().toText();
00364           if(!val.isNull())
00365           {  
00366             intVal = val.nodeValue().toInt( &ok );
00367             if(ok)
00368               modificationYear = intVal;
00369             else
00370               cout << "Error parsing modification year!\n";
00371           }
00372         }        
00373         //------------------------------------------------------------
00374         else if( childNode.isElement() && childNode.nodeName() == "month" )
00375         {
00376           val = childNode.firstChild().toText();
00377           if(!val.isNull())
00378           {
00379             intVal = val.nodeValue().toInt( &ok );
00380             if(ok)
00381               modificationMonth = intVal;
00382             else
00383               cout << "Error parsing modification month!\n";
00384           }
00385         }        
00386         //------------------------------------------------------------
00387         else if( childNode.isElement() && childNode.nodeName() == "day" )
00388         {
00389           val = childNode.firstChild().toText();
00390           if(!val.isNull())
00391           {
00392             intVal = val.nodeValue().toInt( &ok );
00393             if(ok)
00394               modificationDay = intVal;
00395             else
00396               cout << "Error parsing modification day!\n";
00397           }
00398         }        
00399         //------------------------------------------------------------
00400         //advance to next node   
00401         childNode = childNode.nextSibling();
00402         //------------------------------------------------------------
00403       }
00404     }
00405     //------------------------------------------------------------
00406     //subalbum
00407     else if( node.isElement() && node.nodeName() == "subalbum" )
00408     {
00409       //increase counter    
00410       subalbumNum++;
00411 
00412       //create new subalbum
00413       Subalbum* salbum = new Subalbum(this, numSubalbums+1);
00414       
00415       //populate it
00416       salbum->importFromDisk( &node, subalbumNum, dialog, (rootDir + "/") );
00417       
00418       //append it to list of subalbums
00419       appendSubalbum(salbum);
00420     }
00421     //------------------------------------------------------------
00422     //advance to next node   
00423     node = node.nextSibling();
00424     //------------------------------------------------------------
00425   }
00426 
00427   //reset number of loaded subalbums  
00428   numLoadedSubalbums = numSubalbums;
00429 
00430   dialog->printMessage("Done!");
00431    
00432   //save load directory name and loaded/saved bit
00433   saveLocation = rootDir;
00434   savedToDisk = true;
00435 }
00436 //==============================================
00437 void Album::exportToDisk(SaveDialog* dialog, QString dirName)
00438 {
00439   saveLocation = dirName;
00440   exportToDisk(dialog, true);
00441 }
00442 //==============================================
00443 void Album::exportToDisk(SaveDialog* dialog, bool forceSave)
00444 {
00445   //------------------------------------------
00446   //create subdirs
00447   QDir localDir(saveLocation);
00448   //img dirs
00449   localDir.mkdir("img");
00450   //subalbum dirs
00451   localDir.setPath(saveLocation + "/img");
00452   int i;
00453   for(i=1; i <= numSubalbums; i++)
00454   {
00455     QString dirName = QString("%1") .arg(i);
00456     localDir.mkdir(dirName);
00457   }
00458   //------------------------------------------    
00459   //checks worked, go ahead with export
00460   exportSublabumsToHTML(dialog);
00461   exportTopLevelImages();
00462   exportSubalbumImages(dialog, forceSave);
00463   reorderSubalbumImages(dialog);
00464   removeStagnantImages(dialog);
00465   exportToXML(dialog);
00466   exportToHTML(dialog);
00467   //------------------------------------------
00468   //remove files from temp folder
00469   QDir tmpDir(QDir::homeDirPath() + "/.albumShaper/tmp" );
00470   QStringList strLst = tmpDir.entryList();
00471   QStringList::iterator it;
00472   for(it = strLst.begin(); it != strLst.end(); it++)
00473   {
00474       tmpDir.remove(*it);
00475   }
00476   //------------------------------------------
00477   //print done message
00478   savedToDisk = true;
00479   dialog->printMessage("Done!");
00480   //------------------------------------------
00481 }
00482 //==============================================
00483 void Album::exportToXML(SaveDialog* dialog)
00484 {
00485   //print dialog message
00486   dialog->printMessage("XML Layout");
00487   
00488   //update modification date
00489   updateModificationDate();
00490   
00491   //create/open xml file
00492   QFile* xml = new QFile(saveLocation + "/Album.xml");
00493   if(xml->open(IO_WriteOnly))
00494   {
00495     QTextStream stream( xml );
00496    
00497     //write album information
00498     stream << "<album>\n";
00499     stream << "  <name>" << fixXMLString(name) << "</name>\n";
00500     stream << "  <description>" << fixXMLString(description) << "</description>\n";
00501     stream << "  <author>" << fixXMLString(author) << "</author>\n";  
00502     stream << "  <modified>\n";
00503     stream << "    <year>" << modificationYear << "</year>\n";
00504     stream << "    <month>" << modificationMonth << "</month>\n";
00505     stream << "    <day>" << modificationDay << "</day>\n";
00506     stream << "  </modified>\n";
00507    
00508     //write subalbums
00509     Subalbum* current = firstSubalbum;
00510     while(current != NULL)
00511     {
00512       current->exportToXML(stream);
00513       current = current->getNext();
00514     }
00515   
00516     //end album
00517     stream << "</album>\n";    
00518     xml->close(); 
00519   }
00520   else
00521     cout << "error opening file!\n";
00522 }
00523 //==============================================
00524 void Album::exportToHTML(SaveDialog* dialog)
00525 {
00526   //print dialog message
00527   dialog->printMessage("Album HTML");
00528   
00529   //update modification date
00530   updateModificationDate();
00531   
00532   //create/open html file
00533   QFile* html = new QFile(saveLocation + "/Album.html");
00534   if(html->open(IO_WriteOnly))
00535   {
00536     QTextStream stream( html );
00537     stream << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";    
00538     stream << "<html>\n";
00539     stream << "  <head>\n";
00540     stream << "    <style type=\"text/html\">\n";
00541     stream << "      <!--\n";
00542     stream << "      A{text-decoration:none}\n";
00543     stream << "      -->\n";
00544     stream << "    </style>\n";
00545     stream << "    <style type=\"text/css\">\n";
00546     stream << "     <!--\n";
00547     stream << "     h3 {font-size: 12pt; font-weight: bold; text-align: center}\n";
00548     stream << "     h4 {font-size: 10pt; font-weight: normal; text-align: center}\n";
00549     stream << "     h4.ital {font-size: 10pt; font-weight: normal; text-align: center}\n";
00550     stream << "      -->\n";
00551     stream << "    </style>\n";    
00552     stream << "    <title>" << name << "</title>\n";
00553     stream << "    <meta name=\"generator\" content=\"Album Shaper (c.) Will Stokes\">\n";
00554     stream << "  </head>\n";
00555     stream << "  <body>\n";
00556     
00557     if(getRepresentativeImage(LARGE) != NULL)
00558     {
00559       stream << "    <center>\n";
00560       stream << "      <img src=\"img/album.jpg\" alt=\"Representative Album Image\">\n";
00561       stream << "    </center>\n";
00562     }
00563     stream << "    <center>\n";
00564     stream << "      <table>\n";
00565     stream << "        <tr>\n";
00566     if(largeRepresentativeImage != NULL)
00567     {
00568       stream << "          <td width=\"" << largeRepresentativeImage->width() << "\">\n";
00569     }
00570     else    
00571     {
00572       stream << "          <td width=\"450\">\n";
00573     }
00574     stream << "            <h3>\n";
00575     stream << "              " << name << "\n";
00576     stream << "            </h3>\n";
00577     stream << "            <h4>\n";
00578     stream << "              " << description << "\n";
00579     stream << "            </h4>\n";
00580     stream << "          </td>\n";
00581     stream << "        </tr>\n";
00582     stream << "      </table>\n";
00583     stream << "    </center>\n";
00584     
00585     int subalbumNumber = 0;
00586     
00587     //write subalbum thumbnails
00588     Subalbum* current = firstSubalbum;
00589     if(current != NULL)
00590     {
00591       stream << "    <center>\n";
00592       stream << "      <table border=\"0\">\n";
00593       while(current != NULL)
00594       {
00595         Subalbum* backupCurrent = current;
00596         int backupNumber = subalbumNumber;
00597         
00598         //---------------------------------------
00599         //Print row of images
00600         //---------------------------------------
00601         int n = 3;
00602         stream << "        <tr>\n";
00603         while(current != NULL && n > 0)
00604         {
00605           n--;
00606           subalbumNumber++;          
00607           stream << "          <td valign=\"bottom\" width=\"" << THUMBNAIL_WIDTH << "\">\n";
00608           if(current->getRepresentativeImage(LARGE) != NULL )
00609           {
00610             stream << "            <center>\n";
00611             stream << "              <script type=\"text/javascript\" language=\"JavaScript\">\n";
00612             stream << "              <!-- HIDE FROM OLD BROWSERS\n";
00613             stream << "              document.write(\"<a href=\\\"subalbum_" << subalbumNumber << "_slideshow.html\\\">\")\n";
00614             stream << "              document.write(\"  <img alt=\\\"Subalbum " << subalbumNumber << "\\\" src=\\\"img/" << subalbumNumber << "_thumb.jpg\\\">\")\n";
00615             stream << "              document.write(\"</a>\")\n";
00616             stream << "              -->\n";
00617             stream << "              </script>\n";
00618             stream << "              <noscript>\n";
00619             stream << "                <a href=\"subalbum_" << subalbumNumber << "_thumbs.html\">\n";
00620             stream << "                  <img alt=\"Subalbum " << subalbumNumber << "\" src=\"img/" << subalbumNumber << "_thumb.jpg\">\n";
00621             stream << "                </a>\n";
00622             stream << "              </noscript>\n";
00623             stream << "            </center>\n";
00624           }
00625           stream << "          </td>\n";
00626           current = current->getNext();
00627         }
00628         while(n != 0 && subalbumNumber > 2)
00629         {
00630           stream << "          <td width=\"" << THUMBNAIL_WIDTH << "\"></td>\n";
00631           n--;
00632         }
00633         //---------------------------------------
00634         //Print row of image descriptions
00635         //---------------------------------------
00636         current = backupCurrent;
00637         subalbumNumber = backupNumber;
00638         n = 3;
00639         stream << "        <tr>\n";
00640         while(current != NULL && n > 0)
00641         {          
00642           subalbumNumber++;
00643           stream << "          <td valign=\"top\" width=\"" << THUMBNAIL_WIDTH << "\">\n";
00644           stream << "            <center>\n";
00645           stream << "              <script type=\"text/javascript\" language=\"JavaScript\">\n";
00646           stream << "              <!-- HIDE FROM OLD BROWSERS\n";
00647           stream << "              document.write(\"<a href=\\\"subalbum_" << subalbumNumber << "_slideshow.html\\\">\")\n";
00648           stream << "              document.write(\"  " << current->getName() << "\")\n";
00649           stream << "              document.write(\"</a>\")\n";
00650           stream << "              -->\n";
00651           stream << "              </script>\n";
00652           stream << "              <noscript>\n";
00653           stream << "                <a href=\"subalbum_" << subalbumNumber << "_thumbs.html\">\n";
00654           stream << "                  " << current->getName() << "\n";
00655           stream << "                </a>\n";
00656           stream << "              </noscript>\n";
00657           stream << "            </center>\n";
00658           stream << "          </td>\n";
00659           n--;
00660           current = current->getNext();
00661         }
00662         
00663         while(n != 0 && subalbumNumber > 2)
00664         {
00665           stream << "          <td></td>\n";
00666           n--;
00667         }
00668       }
00669       
00670       stream << "      </table>\n";
00671       stream << "    </center>\n";
00672     } //end if
00673   
00674     stream << "    <h4 class=\"ital\">\n";
00675     stream << "      (Generated for " << author << " on " << modificationMonth << "/" << modificationDay;
00676     stream << "/" << modificationYear << " by <a href=\"http://albumshaper.sourceforge.net\">Album Shaper</a>)\n";
00677     stream << "    </h4>\n";
00678     stream << "  </body>\n";
00679     stream << "</html>\n";
00680       
00681     html->close(); 
00682   }
00683   else
00684     cout << "error opening file!\n";
00685 }
00686 //==============================================
00687 void Album::exportSublabumsToHTML(SaveDialog* dialog)
00688 {
00689   int n=0;
00690   Subalbum* current = firstSubalbum;
00691   while(current != NULL)
00692   {
00693     n++;    
00694     
00695     //print dialog message
00696     dialog->printSubalbumHTML( n );
00697     
00698     //export thumbnail album
00699     QString fileName = QString(saveLocation + "/subalbum_%1_thumbs.html") .arg(n);
00700     QFile* thumbHTML = new QFile(fileName);
00701     if(thumbHTML->open(IO_WriteOnly))
00702     {
00703       QTextStream stream( thumbHTML );
00704       current->exportThumbnailHTML( stream, n );
00705       thumbHTML->close(); 
00706     }
00707     
00708     //export slideshow
00709     fileName = QString(saveLocation + "/subalbum_%1_slideshow.html") .arg(n);
00710     QFile* slideshowHTML = new QFile(fileName);
00711     if(slideshowHTML->open(IO_WriteOnly))
00712     {
00713       QTextStream stream( slideshowHTML );
00714       current->exportSlideshowHTML( stream, n );
00715       slideshowHTML->close(); 
00716     }
00717     
00718     //move on to next subalbum
00719     current = current->getNext();  
00720   }  
00721 }
00722 //==============================================
00723 void Album::exportTopLevelImages()
00724 {
00725   //if image set export it
00726   if(getRepresentativeImage(LARGE) != NULL)
00727   {
00728     getRepresentativeImage(LARGE)->save(saveLocation + "/img/album.jpg", "JPEG", 100);
00729   }
00730   //else make sure any previously set images are removed
00731   else
00732   {
00733     QDir rootDir(saveLocation + "/img/");
00734     rootDir.remove("album.jpg");
00735   }
00736   
00737   //export subalbum thumbs
00738   int n=0;
00739   Subalbum* current = firstSubalbum;
00740   while(current != NULL)
00741   {
00742     n++;
00743     //if subalbum has representative image export it
00744     if(current->getRepresentativeImage(LARGE) != NULL )
00745     {
00746       QString fileName = QString(saveLocation + "/img/%1_thumb.jpg" ).arg(n);
00747       current->getRepresentativeImage(LARGE)->save(fileName, "JPEG", 100);
00748     }
00749     //otherwise make sure anyprevious set images are removed
00750     else
00751     {
00752       QDir rootDir(saveLocation + "/img/");
00753       rootDir.remove( QString("%1_thumb.jpg").arg(n) );
00754     }
00755     current = current->getNext();
00756   }  
00757 }
00758 //==============================================
00759 void Album::exportSubalbumImages(SaveDialog* dialog, bool forceSave)
00760 {  
00761   dialog->printMessage("Saving images");
00762 
00763   //iterate over all subalbums
00764   int subalbumNumber=0;
00765   Subalbum* currentSubalbum = firstSubalbum;
00766   while(currentSubalbum != NULL)
00767   {
00768     subalbumNumber++;    
00769     
00770     //iterate over all photos in this subalbum
00771     int photoNumber=0;    
00772     Photo* currentPhoto = currentSubalbum->getFirst();
00773     while(currentPhoto != NULL)
00774     {
00775       photoNumber++;
00776       dialog->printSubalbumPhoto( subalbumNumber, photoNumber );
00777       //---------------------------------------
00778       //if the current photo does not need to be saved then move on
00779       if( !forceSave && !currentPhoto->getNeedsSavingVal() )
00780       {
00781         currentPhoto = currentPhoto->getNext();
00782         continue;
00783       }
00784       //---------------------------------------
00785       //construct a QDir object for the tmp folder
00786       QDir rootDir;
00787       //---------------------------------------
00788       //get initial photo # and subalbum #, used for saving      
00789       int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
00790       int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
00791       //---------------------------------------
00792       //export thumbnail image
00793       QString fileName = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00794       currentPhoto->getImage(THUMBNAIL)->save(fileName, "JPEG", 100);
00795 
00796       //compute and store md5 for thumbnail     
00797       ifstream thumbnailFile(fileName.ascii());
00798       if(thumbnailFile.is_open())
00799       {
00800         currentPhoto->setThumbnailChecksum( getMD5(thumbnailFile) ); 
00801         thumbnailFile.close();
00802       }
00803       //---------------------------------------
00804       //export slideshow image
00805       QString oldName = currentPhoto->getSlideshowFilename();
00806       QString newName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00807 
00808       //if file has been modified move from current location to final location
00809       if( currentPhoto->getNeedsSavingVal() )
00810       {
00811         //attempt to rename file, if fails do explicit copy, then delete prev file
00812          if(!rootDir.rename( oldName, newName))
00813          {
00814            copyFile(oldName, newName);
00815            rootDir.remove(oldName);
00816          }
00817       }
00818       //If file has not been modified we must be doing a save-as and saving has been forced. In this case
00819       //COPY file from current location to final location, DON'T delete previous copy!!!
00820        else
00821        {
00822          copyFile(oldName, newName);
00823        }
00824              
00825       //compute and store md5 for slideshow image
00826       ifstream file(newName.ascii());
00827       if(file.is_open())
00828       {
00829         currentPhoto->setSlideshowChecksum( getMD5(file) ); 
00830         file.close();
00831       }
00832       //---------------------------------------
00833       //export full size image
00834       oldName = currentPhoto->getImageFilename();   
00835       newName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00836       
00837       //if file has been modified move from current location to final location
00838       if( currentPhoto->getNeedsSavingVal() )
00839       {
00840         //attempt to rename file, if fails do explicit copy, then delete prev file
00841          if(!rootDir.rename( oldName, newName))
00842          {
00843            copyFile(oldName, newName);
00844            rootDir.remove(oldName);
00845          }
00846       }
00847       //If file has not been modified we must be doing a save-as and saving has been forced. In this case
00848       //COPY file from current location to final location, DON'T delete previous copy!!!
00849        else
00850        {
00851          copyFile(oldName, newName);
00852        }
00853             
00854       //compute and store md5 for image
00855       ifstream imageFile(newName.ascii());
00856       if(imageFile.is_open())
00857       {
00858         currentPhoto->setImageChecksum( getMD5(imageFile) ); 
00859         imageFile.close();
00860       }
00861       //---------------------------------------
00862       //set new storage locations of files
00863       currentPhoto->setImageFilename( QString(saveLocation + "/img/%1/%2.jpg").arg(initSubalbumNumber).arg(initPhotoNumber) );
00864       currentPhoto->setSlideshowFilename( QString(saveLocation + "/img/%1/%2_slideshow.jpg").arg(initSubalbumNumber).arg(initPhotoNumber) );
00865       //---------------------------------------
00866       //set image as not needing saving
00867       currentPhoto->setNeedsSavingVal(false);
00868       //---------------------------------------
00869       //move on to next photo in subalbum
00870       currentPhoto = currentPhoto->getNext();
00871       //---------------------------------------
00872     }
00873     //---------------------------------------
00874     //move on to next subalbum
00875     currentSubalbum = currentSubalbum->getNext();  
00876   }
00877 }
00878 //==============================================
00879 void Album::reorderSubalbumImages(SaveDialog* dialog)
00880 {
00881   //--------------------------------------------------------
00882   //--------------------------------------------------------
00883   //first pass over all photos, those whose initial and current numbers don't match up
00884   //rename slightly so we don't overwrte them the second time around
00885   //--------------------------------------------------------
00886   //--------------------------------------------------------
00887   dialog->printMessage("Reordering images (pass 1)");
00888   
00889   //iterate over all subalbums
00890   int subalbumNumber=0;
00891   Subalbum* currentSubalbum = firstSubalbum;
00892   while(currentSubalbum != NULL)
00893   {
00894     subalbumNumber++;    
00895     
00896     //iterate over all photos in this subalbum
00897     int photoNumber=0;    
00898     Photo* currentPhoto = currentSubalbum->getFirst();
00899     while(currentPhoto != NULL)
00900     {
00901       photoNumber++;
00902       dialog->printSubalbumPhoto( subalbumNumber, photoNumber );
00903       //---------------------------------------
00904       //get initial photo # and subalbum #, used for checks and moving
00905       int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
00906       int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
00907       //---------------------------------------
00908       //if the current photo has not moved then move on
00909       if( initPhotoNumber == photoNumber &&
00910           initSubalbumNumber == subalbumNumber)
00911       {
00912         currentPhoto = currentPhoto->getNext();
00913         continue;
00914       }
00915       //---------------------------------------
00916       //rename full image, slideshow image, and thumbnail image     
00917       QDir rootDir;
00918       QString oldName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00919       QString newName = QString(saveLocation + "/img/%1/%2_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);     
00920       if(!rootDir.rename( oldName, newName))
00921       {
00922         QImage(oldName).save(newName, "JPEG", 100);
00923         rootDir.remove( oldName );
00924       }
00925       //-----
00926       oldName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00927       newName = QString(saveLocation + "/img/%1/%2_slideshow_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);      
00928       if(!rootDir.rename( oldName, newName))
00929       {
00930         QImage(oldName).save(newName, "JPEG", 100);
00931         rootDir.remove( oldName );
00932       }
00933       //-----
00934       oldName = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00935       newName = QString(saveLocation + "/img/%1/%2_thumb_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);      
00936       if(!rootDir.rename( oldName, newName))
00937       {
00938         QImage(oldName).save(newName, "JPEG", 100);
00939         rootDir.remove( oldName );
00940       }
00941       //---------------------------------------
00942       //move on to next photo in subalbum
00943       currentPhoto = currentPhoto->getNext();
00944       //---------------------------------------
00945     }
00946     //---------------------------------------
00947     //move on to next subalbum
00948     currentSubalbum = currentSubalbum->getNext();  
00949   }
00950 
00951   //--------------------------------------------------------
00952   //--------------------------------------------------------
00953   //second pass over all photos, those whose initial and current numbers don't match up
00954   //rename to their final names and reset initial photo and subalbum numbers
00955   //--------------------------------------------------------
00956   //--------------------------------------------------------
00957   dialog->printMessage("Reordering images (pass 2)");
00958   
00959   //iterate over all subalbums
00960   subalbumNumber=0;
00961   currentSubalbum = firstSubalbum;
00962   while(currentSubalbum != NULL)
00963   {
00964     subalbumNumber++;    
00965     
00966     //iterate over all photos in this subalbum
00967     int photoNumber=0;    
00968     Photo* currentPhoto = currentSubalbum->getFirst();
00969     while(currentPhoto != NULL)
00970     {
00971       photoNumber++;
00972       dialog->printSubalbumPhoto( subalbumNumber, photoNumber );
00973       //---------------------------------------
00974       //get initial photo # and subalbum #, used for checks and moving
00975       int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
00976       int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
00977       //---------------------------------------
00978       //if the current photo has not moved then move on
00979       if( initPhotoNumber == photoNumber &&
00980           initSubalbumNumber == subalbumNumber)
00981       {
00982         currentPhoto = currentPhoto->getNext();
00983         continue;
00984       }
00985       //---------------------------------------
00986       //rename full image, slideshow image, and thumbnail image to their final names
00987       QDir rootDir;
00988       QString oldName = QString(saveLocation + "/img/%1/%2_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00989       QString newName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(subalbumNumber).arg(photoNumber);     
00990       if(!rootDir.rename( oldName, newName))
00991       {
00992         QImage(oldName).save(newName, "JPEG", 100);
00993         rootDir.remove( oldName );
00994       }
00995       //-----
00996       oldName = QString(saveLocation + "/img/%1/%2_slideshow_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
00997       newName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(subalbumNumber).arg(photoNumber);      
00998       if(!rootDir.rename( oldName, newName))
00999       {
01000         QImage(oldName).save(newName, "JPEG", 100);
01001         rootDir.remove( oldName );
01002       }
01003       //-----
01004       oldName = QString(saveLocation + "/img/%1/%2_thumb_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
01005       newName = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(subalbumNumber).arg(photoNumber);      
01006       if(!rootDir.rename( oldName, newName))
01007       {
01008         QImage(oldName).save(newName, "JPEG", 100);
01009         rootDir.remove( oldName );
01010       }
01011       //---------------------------------------
01012       //reset initial photo and subalbum numbers
01013       currentPhoto->setInitialPhotoNumber(photoNumber);
01014       currentPhoto->setInitialSubalbumNumber(subalbumNumber);
01015       //---------------------------------------
01016       //move on to next photo in subalbum
01017       currentPhoto = currentPhoto->getNext();
01018       //---------------------------------------
01019     }
01020     //---------------------------------------
01021     //move on to next subalbum
01022     currentSubalbum = currentSubalbum->getNext();  
01023   }
01024 }
01025 //==============================================
01026 void Album::removeStagnantImages(SaveDialog* dialog)
01027 {
01028   dialog->printMessage("Removing stagnant images");
01029   QDir rootDir(saveLocation + "/img/");
01030   //---------------------------------
01031   //remove stagnant photos in existing subalbums
01032   int subalbumNumber=0;
01033   Subalbum* currentSubalbum = firstSubalbum;
01034   while(currentSubalbum != NULL)
01035   {
01036     subalbumNumber++;    
01037 
01038     int i;
01039     for(i=currentSubalbum->getNumPhotos() + 1;
01040         i <= currentSubalbum->getNumLoadedPhotos();
01041         i++)
01042     {
01043       QString thumbString = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(subalbumNumber).arg(i);
01044       QString slideshowString = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(subalbumNumber).arg(i);
01045       QString imageString = QString(saveLocation + "/img/%1/%2.jpg" ).arg(subalbumNumber).arg(i);
01046       rootDir.remove(thumbString);
01047       rootDir.remove(slideshowString);
01048       rootDir.remove(imageString);
01049     }
01050     
01051     //reset number of loaded photos since old photos removed now
01052     currentSubalbum->resetNumLoadedPhotos();
01053     
01054     //move on to next subalbum
01055     currentSubalbum = currentSubalbum->getNext();  
01056   }
01057   //---------------------------------
01058   //remove stagnant subalbums and all their contents
01059   int i;
01060   for(i=numSubalbums+1; i<=numLoadedSubalbums; i++)
01061   {
01062     //get filelist for directory
01063     QDir imageDir(  QString(saveLocation + "/img/%1/").arg(i) );
01064     QStringList list = imageDir.entryList( QDir::Files );
01065     
01066     //remove each file in directory
01067     for ( QStringList::Iterator file = list.begin(); file != list.end(); ++file ) 
01068     {
01069       rootDir.remove( QString(saveLocation + "/img/%1/" + *file).arg(i) );
01070     }
01071     
01072     //remove directory
01073     rootDir.rmdir( QString("%1").arg(i) );
01074     
01075     //remove thumbnail image
01076     rootDir.remove( QString(saveLocation + "/img/%1_thumb.jpg").arg(i) );
01077     
01078     //remove slideshow and thumbnail html pages
01079     rootDir.remove( QString(saveLocation + "/subalbum_%1_thumbs.html").arg(i) );    
01080     rootDir.remove( QString(saveLocation + "/subalbum_%1_slideshow.html").arg(i) );        
01081   }
01082   
01083   //reset number of loaded subalbums since stagnant directories removed now
01084   numLoadedSubalbums = numSubalbums;
01085   //---------------------------------
01086 }  
01087 //==============================================
01088 bool Album::prevSave()
01089 {
01090   return savedToDisk;
01091 }
01092 //==============================================
01093 void Album::syncSubalbumList(SubalbumPreviewWidget* item)
01094 {
01095   //base case, no items
01096   if(item == NULL)
01097   {
01098     firstSubalbum = NULL;
01099     lastSubalbum = NULL;
01100     return;
01101   }
01102   
01103   //set first and last pointers
01104   firstSubalbum = item->getSubalbum();
01105   firstSubalbum->setNext(NULL);
01106   lastSubalbum = firstSubalbum;
01107     
01108   //set all next pointers
01109   while(item->nextItem() != NULL)
01110   {
01111     item->getSubalbum()->setNext( ((SubalbumPreviewWidget*)item->nextItem())->getSubalbum() );
01112     item = (SubalbumPreviewWidget*)item->nextItem();
01113     lastSubalbum = item->getSubalbum();
01114     lastSubalbum->setNext(NULL);
01115   }
01116 }
01117 //==============================================
01118 QString Album::getSaveLocation()
01119 {
01120   return saveLocation;
01121 }
01122 //==============================================
01123 int Album::getNumSubalbums()
01124 {
01125   return numSubalbums;
01126 }
01127 //==============================================

Generated on Tue Jun 10 23:41:20 2003 for AlbumShaper by doxygen 1.3.1