AlbumShaper  1.0a3
album.cpp
Go to the documentation of this file.
1 //==============================================
2 // copyright : (C) 2003-2005 by Will Stokes
3 //==============================================
4 // This program is free software; you can redistribute it
5 // and/or modify it under the terms of the GNU General
6 // Public License as published by the Free Software
7 // Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //==============================================
10 
11 //Systemwide includes
12 #include <qimage.h>
13 #include <qpixmap.h>
14 #include <qstring.h>
15 #include <qstringlist.h>
16 #include <time.h>
17 #include <qfile.h>
18 #include <qfileinfo.h>
19 #include <q3textstream.h>
20 #include <qdom.h>
21 #include <qdir.h>
22 #include <qapplication.h>
23 #include <qregexp.h>
24 #include <qdatetime.h>
25 #include <math.h>
26 
27 //Projectwide includes
28 #include "album.h"
29 #include "subalbum.h"
30 #include "photo.h"
31 #include "tools/imageTools.h"
32 #include "tools/fileTools.h"
33 #include "tools/md5.h"
34 #include "tools/xmlTools.h"
35 #include "../config.h"
36 #include "../gui/subalbumPreviewWidget.h"
37 #include "../gui/statusWidget.h"
38 
39 //==============================================
41 Album::Album( QString tmpDir, bool createSubalbum )
42 {
43  //set strings to default values
44  name = "";
45  description ="";
46  author = "";
47  theme = "Slick";
48  this->tmpDir = tmpDir;
49 
50  //by default no representative image
53 
54  //no Subalbums by default
55  firstSubalbum = NULL;
56  lastSubalbum = NULL;
57 
58  //set the creation/modification date to today
61 
62  //no subalbums
63  numSubalbums = 0;
65 
66  //not previously saved by default
67  savedToDisk = false;
68 
69  //set default save location (where images are placed before saving) to the tmp directory
71 
72  if(createSubalbum)
73  {
74  Subalbum* s = new Subalbum( this, 1 );
75  appendSubalbum( s );
76  }
77 
78  //no interesting modifications yet
79  modified = false;
80 
81  nextUniqueID = 0;
82 }
83 //==============================================
85 {
86  //delete representative image
89 
90  //delete subalbums
91  Subalbum* current = firstSubalbum;
92  Subalbum* temp;
93  while(current != NULL)
94  {
95  temp = current->getNext();
96  delete current;
97  current = temp;
98  }
99 
100  //remove all old tmp dir contents and directory itself
101  if(!tmpDir.isNull())
102  {
103  QDir oldTmpDir(tmpDir);
104  QString tmpDirName = oldTmpDir.dirName();
105  QStringList strLst = oldTmpDir.entryList();
106  QStringList::iterator it;
107  for(it = strLst.begin(); it != strLst.end(); it++)
108  {
109  oldTmpDir.remove(tmpDir + "/" + *it);
110  }
111  oldTmpDir.cdUp();
112  oldTmpDir.rmdir( tmpDirName );
113  }
114 }
115 //==============================================
119 
123 
124 QString Album::getName() { return QString(name); }
125 QString Album::getDescription() { return QString(description); }
126 QString Album::getAuthor() { return QString(author); }
127 //==============================================
129 {
130  if(size == SMALL) return smallRepresentativeImage;
131  else if(size == LARGE) return largeRepresentativeImage;
132  else return NULL;
133 }
134 //==============================================
137 //==============================================
138 bool Album::prevSave() { return savedToDisk; }
139 bool Album::albumModified() { return modified; }
140 //==============================================
142 QString Album::getTmpDir() { return tmpDir; }
143 QString Album::getTheme() { return theme; }
145 //==============================================
147 {
148  //compute number of photos and size on disk
149  int numPhotos = 0;
150  Subalbum* curr = firstSubalbum;
151  while(curr != NULL)
152  {
153  numPhotos+= curr->getNumPhotos();
154  curr = curr->getNext();
155  }
156  return numPhotos;
157 }
158 //==============================================
159 void Album::setName(QString val)
160 {
161  if(name != val)
162  {
163  name = val;
164  modified = true;
165  }
166 }
167 //==============================================
168 void Album::setDescription(QString val)
169 {
170  if(description != val)
171  {
172  description = val;
173  modified = true;
174  }
175 }
176 //==============================================
177 void Album::setAuthor(QString val)
178 {
179  if(author != val)
180  {
181  author = val;
182  modified = true;
183  }
184 }
185 //==============================================
186 void Album::setRepresentativeImages(QString imageFilename)
187 {
188  //delete representative images
191 
192  //if being set to null, set back to defaults
193  if(imageFilename.isNull())
194  {
197  }
198  else
199  {
200  //compute representative image sizes
201  int imageWidth, imageHeight;
202  getImageSize( imageFilename, imageWidth, imageHeight );
203 
204  int smallRepWidth = 0;
205  int smallRepHeight = 0;
206  int largeRepWidth = 0;
207  int largeRepHeight = 0;
208  calcScaledImageDimensions( imageWidth, imageHeight,
209  107, REP_IMAGE_HEIGHT,
210  smallRepWidth, smallRepHeight);
211  calcScaledImageDimensions( imageWidth, imageHeight,
212  500, 320,
213  largeRepWidth, largeRepHeight);
214 
215  //create various representative images
216 
217  //copy and scale small version
218  QImage thumbnailSmall;
219  scaleImage( imageFilename, thumbnailSmall, smallRepWidth, smallRepHeight );
220  smallRepresentativeImage = new QPixmap( thumbnailSmall.width(), thumbnailSmall.height() );
221  smallRepresentativeImage->convertFromImage( thumbnailSmall );
222 
223  //copy and scale large version
224  QImage thumbnailLarge;
225  scaleImage( imageFilename, thumbnailLarge, largeRepWidth, largeRepHeight );
226  largeRepresentativeImage = new QPixmap( thumbnailLarge.width(), thumbnailLarge.height() );
227  largeRepresentativeImage->convertFromImage( thumbnailLarge );
228  }
229 
230  //set modified
231  modified = true;
232 }
233 //==============================================
235 {
236  //if passed a null pointer bail!
237  if( val == NULL) return;
238 
239  //empty list - stick on front
240  if(firstSubalbum == NULL)
241  {
242  firstSubalbum = val;
243  lastSubalbum = val;
244  }
245  //else - append to end
246  else
247  {
248  lastSubalbum->setNext( val );
249  val->setPrev( lastSubalbum );
250  lastSubalbum = val;
251  }
252 
253  numSubalbums++;
254  modified = true;
255 }
256 //==============================================
258 {
259  //if passed a null pointer bail!
260  if( val == NULL) return;
261 
262  //reset head and tail pointers if necessary
263  if( val == firstSubalbum ) firstSubalbum = val->getNext();
264  if( val == lastSubalbum ) lastSubalbum = val->getPrev();
265 
266  //split out
267  if( val->getPrev() != NULL ) val->getPrev()->setNext( val->getNext() );
268  if( val->getNext() != NULL ) val->getNext()->setPrev( val->getPrev() );
269 
270  //delete object
271  delete val;
272  val = NULL;
273  numSubalbums--;
274  modified = true;
275 }
276 //==============================================
278 {
279  //set creation date to today
280  QDate date = QDate::currentDate();
281  creationYear = date.year();
282  creationMonth = date.month();
283  creationDay = date.day();
284 }
285 //==============================================
287 {
288  //set last modification date to today
289  QDate date = QDate::currentDate();
290  modificationYear = date.year();
291  modificationMonth = date.month();
292  modificationDay = date.day();
293 }
294 //==============================================
295 int Album::importFromDisk(StatusWidget* status, QString fileName, bool disableCheckPhotoMods)
296 {
297  //update file
298  updateXML( QFileInfo(fileName).dirPath(TRUE) );
299 
300  //open file
301  QFile albumFile( fileName );
302 
303  //unable to open xml file? alert user
304  if( !albumFile.open( QIODevice::ReadOnly ) )
305  return ALBUM_READ_ERROR;
306 
307  //parse dom
308  QDomDocument albumDom;
309  if( !albumDom.setContent( &albumFile ) )
310  return ALBUM_XML_ERROR;
311 
312  //close file
313  albumFile.close();
314 
315  //get main directory all other files and subdirectories are in
316  QString rootDir = QFileInfo(albumFile).dirPath(TRUE);
317  saveLocation = rootDir + "/img";
318 
319  //if representative image exists load
320  QImage repImage(rootDir + "/img/album.jpg");
321  if(!repImage.isNull())
322  {
323  setRepresentativeImages( rootDir + "/img/album.jpg");
324  }
325 
326  //count number of photos in album, needed for showing loading progress
327  int numPhotos = 0;
328  QDomElement root = albumDom.documentElement();
329  QDomNode node = root.firstChild();
330  while( !node.isNull() )
331  {
332  if( node.isElement() && node.nodeName() == "subalbum" )
333  {
334  QDomNode childNode = node.firstChild();
335  while( !childNode.isNull() )
336  {
337  if( childNode.isElement() && childNode.nodeName() == "photo" )
338  numPhotos++;
339  childNode = childNode.nextSibling();
340  }
341  }
342  node = node.nextSibling();
343  }
344 
345  //setup progress bar
346  status->showProgressBar( StatusWidget::tr("Loading:"), numPhotos );
347  qApp->processEvents();
348 
349  int subalbumNum = 0;
350 
351  //get root node and start parsing DOM
352  root = albumDom.documentElement();
353  node = root.firstChild();
354  QDomText val;
355  while( !node.isNull() )
356  {
357  //------------------------------------------------------------
358  //album name
359  if( node.isElement() && node.nodeName() == "name" )
360  {
361  val = node.firstChild().toText();
362  if(!val.isNull())
363  name = val.nodeValue();
364  name.replace("\\&quot;","\"");
365  }
366  //------------------------------------------------------------
367  //album description
368  else if( node.isElement() && node.nodeName() == "description" )
369  {
370  val = node.firstChild().toText();
371  if(!val.isNull())
372  description = val.nodeValue();
373  description.replace("\\&quot;","\"");
374  }
375  //------------------------------------------------------------
376  //album author
377  else if( node.isElement() && node.nodeName() == "author" )
378  {
379  val = node.firstChild().toText();
380  if(!val.isNull())
381  author = val.nodeValue();
382  author.replace("\\&quot;","\"");
383  }
384  //------------------------------------------------------------
385  //album theme
386  else if( node.isElement() && node.nodeName() == "theme" )
387  {
388  val = node.firstChild().toText();
389  if(!val.isNull())
390  theme = val.nodeValue();
391  theme.replace("\\&quot;","\"");
392  }
393  //------------------------------------------------------------
394  //album creation date
395  else if( node.isElement() && node.nodeName() == "created" )
396  {
397  val = node.firstChild().toText();
398 
399  //split value based on spaces, should be 7 fields
400  QStringList vals = QStringList::split( QRegExp(" "), val.nodeValue() );
401  int i=0;
402  int intVals[3];
403  QStringList::Iterator it;
404  for ( it = vals.begin(); it != vals.end(); ++it )
405  {
406  intVals[i] = QString(*it).toInt();
407  i++;
408  //only read first 3 entires, year/month/day, don't overwrite
409  //buffer on addition entries if xml messed up
410  if(i > 2)
411  break;
412  }
413  creationYear = intVals[0];
414  creationMonth = intVals[1];
415  creationDay = intVals[2];
416  }
417  //------------------------------------------------------------
418  //subalbum
419  else if( node.isElement() && node.nodeName() == "subalbum" )
420  {
421  //increase counter
422  subalbumNum++;
423 
424  //create new subalbum
425  Subalbum* salbum = new Subalbum(this, numSubalbums+1);
426 
427  //populate it
428  salbum->importFromDisk( &node, subalbumNum, status, (rootDir + "/"), disableCheckPhotoMods );
429 
430  //append it to list of subalbums
431  appendSubalbum(salbum);
432  }
433  //------------------------------------------------------------
434  //advance to next node
435  node = node.nextSibling();
436  //------------------------------------------------------------
437  }
438 
439  //reset number of loaded subalbums
441 
442  //hide progress bar
443  status->setStatus( qApp->translate("Album", "Album loaded.") );
444 
445  //save load directory name and loaded/saved bit
446  saveLocation = rootDir;
447  savedToDisk = true;
448 
449  return ALBUM_LOADED;
450 }
451 //==============================================
452 int Album::exportToDisk(StatusWidget* status, QString dirName, QString themeName)
453 {
454  //check to see if save location has actually changed, if not don't force save images
455  //this occurs when user blindly selects the same old spot, or is just changing the theme used by default
456  bool forceSave = true;
457 
458  if(saveLocation == dirName)
459  forceSave = false;
460 
461  //backup theme and save location, if save fails revert to previous values
463  QString oldTheme = theme;
464 
465  //attempt to save album
466  saveLocation = dirName;
467  theme = themeName;
468  int result = exportToDisk(status, forceSave);
469 
470  //if album saving failed revert save location and theme
471  if(result != ALBUM_EXPORTED)
472  {
474  theme = oldTheme;
475  }
476  //else update tmp save dir
477  else
478  {
479  //remove all old tmp dir contents and directory itself
480  QDir oldTmpDir(tmpDir);
481  QString tmpDirName = oldTmpDir.dirName();
482  QStringList strLst = oldTmpDir.entryList();
483  QStringList::iterator it;
484  for(it = strLst.begin(); it != strLst.end(); it++)
485  {
486  oldTmpDir.remove( tmpDir + "/" + *it);
487  }
488 
489  oldTmpDir.cdUp();
490  oldTmpDir.rmdir( tmpDirName );
491 
492  //create and set new temp dir location
493  QDir saveDir( saveLocation );
494  if(!saveDir.exists( "tmp" ))
495  saveDir.mkdir( "tmp" );
496  tmpDir = saveLocation + "/tmp";
497 
498  //reset unique id counter
499  nextUniqueID = 0;
500  }
501 
502  //return result
503  return result;
504 }
505 //==============================================
507 {
508  //------------------------------------------
509  //create subdirs
510  QDir localDir(saveLocation);
511  //img dirs
512  localDir.mkdir("img");
513  //subalbum dirs
514  localDir.setPath(saveLocation + "/img");
515 
516  //make a temporary 0 directory for copying new images, they'll be moved to their final
517  //location during the reordering step
518  localDir.mkdir( "0" );
519 
520  //iterate over each subalbum and create its image directory
521  Subalbum* current = firstSubalbum;
522  int collectionNum = 0;
523  while(current != NULL)
524  {
525  collectionNum++;
526  QString dirName = QString("%1") .arg( collectionNum );
527  localDir.mkdir(dirName);
528  current = current->getNext();
529  }
530  //------------------------------------------
531  //checks worked, go ahead with export
532 
533  //count number of photos
534  int totalPhotos=0;
535  current = firstSubalbum;
536  while(current != NULL)
537  {
538  totalPhotos+=current->getNumPhotos();
539  current = current->getNext();
540  }
541 
542  //setup progress bar
543  status->showProgressBar( StatusWidget::tr("Saving:"), 4*totalPhotos );
544  qApp->processEvents();
545 
546  //copy over theme resources
548 
549  //export album cover image, subalbum thumbnails
551 
552  //export subalbum images (thumbnail, slideshow, and full versions of all images)
553  exportSubalbumImages(status, forceSave);
554 
555  //remove any _orig images for photos which have been reverted to their original form
556  removeStagnantOrigFiles(status);
557 
558  //apply reordering to all images
559  reorderSubalbumImages(status);
560 
561  //reset subalbum numbers to current ordering
562  current = firstSubalbum;
563  int n=0;
564  while(current !=NULL)
565  {
566  n++;
567  current->setSubalbumNumber(n);
568  current = current->getNext();
569  }
570 
571  //remove collection 0 directory
572  QDir rootDir(saveLocation + "/img/");
573  rootDir.rmdir( "0" );
574 
575  //remove old images that nolonger belong
577 
578  //remove previous html/htm files
579  localDir.setPath(saveLocation);
580  QStringList list = localDir.entryList( QDir::Files );
581  QStringList::Iterator file;
582  for ( file = list.begin(); file != list.end(); ++file )
583  {
584  if( (*file).endsWith(".html") || (*file).endsWith(".htm") )
585  localDir.remove( saveLocation + "/" + *file );
586  }
587 
588  //export xml structure of album
589  int result = exportToXML(status, saveLocation);
590  if(result != ALBUM_EXPORTED) { return result; }
591 
592  //export various html pages using selected theme
594 
595  //------------------------------------------
596  //remove files from temp folder
597  QDir tmpDirHandle( getTmpDir() );
598  QStringList strLst = tmpDirHandle.entryList();
599  QStringList::iterator it;
600  for(it = strLst.begin(); it != strLst.end(); it++)
601  {
602  tmpDirHandle.remove( getTmpDir() + "/" + *it);
603  }
604  //------------------------------------------
605  savedToDisk = true;
606 
607  //just saved so no modifications since last save
608  modified = false;
609 
610  //hide progress bar
611  status->setStatus( qApp->translate("Album", "Album saved.") );
612  //------------------------------------------
613  return ALBUM_EXPORTED;
614 }
615 //==============================================
617  QString exportLocation,
618  QString exportMessage)
619 {
620  //------------------------------------------
621  //copy all images
622  QDir localDir(exportLocation);
623  localDir.mkdir("img");
624  localDir.setPath(exportLocation + "/img");
625 
626  //copy album image
627  if(getRepresentativeImage(LARGE) != NULL)
628  { getRepresentativeImage(LARGE)->save(exportLocation + "/img/album.jpg", "JPEG", 95); }
629  else
630  { localDir.remove(exportLocation + "/img/album.jpg"); }
631 
632  int numPhotos = getNumPhotos();
633  int photosLeft = numPhotos;
634  int updateInverval = numPhotos / 50;
635  int updateCount = 0;
636 
637  //iterate over each collection
638  Subalbum* curCollection = firstSubalbum;
639  int collectionNum=1;
640  while(curCollection != NULL)
641  {
642  QString collectionDir = QString("%1").arg( collectionNum );
643  localDir.mkdir( collectionDir );
644 
645  //copy collection image
646  QString collectionThumbFilename = QString(exportLocation + "/img/%1_thumb.jpg" ).arg(collectionNum);
647  if(curCollection->getRepresentativeImage(LARGE) != NULL )
648  { curCollection->getRepresentativeImage(LARGE)->save( collectionThumbFilename, "JPEG", 95); }
649  else
650  { localDir.remove( collectionThumbFilename ); }
651 
652  //copy each photo
653  Photo* curPhoto = curCollection->getFirst();
654  int photoNum = 1;
655  while(curPhoto != NULL)
656  {
657  //update status message
658  status->updateProgress( numPhotos - photosLeft, exportMessage.arg( photosLeft ) );
659 
660  //make sure events are processed every 2% of the photos that are processes
661  updateCount++;
662  if(updateCount > updateInverval)
663  {
664  updateCount = 0;
665  qApp->processEvents();
666  }
667 
668  //copy files
669  QString newFilePath = QDir::convertSeparators( exportLocation + "/img/" +
670  collectionDir + "/" +
671  QString("%1").arg(photoNum) );
672 
673  copyFile( curPhoto->getSlideshowFilename(), newFilePath + "_slideshow.jpg" );
674  copyFile( curPhoto->getThumbnailFilename(), newFilePath + "_thumb.jpg" );
675 
676  curPhoto = curPhoto->getNext();
677  photoNum++;
678  photosLeft--;
679  }
680 
681  curCollection = curCollection->getNext();
682  collectionNum++;
683  }
684  //------------------------------------------
685  //copy theme resources
686  QStringList fileList;
687  QStringList::Iterator file;
688 
689  //create HTML and misc resources directories
690  localDir.setPath(exportLocation);
691  localDir.mkdir("resources");
692 
693  //remove all files in these directories from previous saves with other themes
694  localDir.setPath(exportLocation + "/resources");
695  fileList = localDir.entryList( QDir::Files );
696  for ( file = fileList.begin(); file != fileList.end(); ++file )
697  { localDir.remove( exportLocation + "/resources/" + *file ); }
698 
699  //copy files over from theme's directory
700  localDir.setPath(THEMES_PATH + theme + "/resources");
701  fileList = localDir.entryList( QDir::Files );
702  for ( file = fileList.begin(); file != fileList.end(); ++file )
703  { copyFile( THEMES_PATH + theme + "/resources/" + *file, exportLocation + "/resources/" + *file); }
704  //------------------------------------------
705  //export xml file
706  exportToXML(status, exportLocation);
707  //------------------------------------------
708  //remove previous html/htm files
709  localDir.setPath(exportLocation);
710  fileList = localDir.entryList( QDir::Files );
711  for ( file = fileList.begin(); file != fileList.end(); ++file )
712  {
713  if( (*file).endsWith(".html") || (*file).endsWith(".htm") )
714  localDir.remove( exportLocation + "/" + *file );
715  }
716  //------------------------------------------
717  //construct html files
718  transformXMLtoHTML( exportLocation, theme, true );
719  //------------------------------------------
720  //remove xml file
721  localDir.remove( exportLocation + "/Album.xml" );
722  //------------------------------------------
723  return ALBUM_EXPORTED;
724 }
725 //==============================================
726 int Album::exportLargeImages(StatusWidget* status, QString exportPath, QString exportMessage)
727 {
728  //determine number of digits collecion # requires
729  uint collectionDigits = (uint) (1 + log( (double) getNumSubalbums() ) / log( 10.0 ) );
730 
731  //determine number of digits photo # requires, this
732  //involves walking through the album and finding the collection with the most phots first
733  int mostPhotos = 0;
734  Subalbum* curCollection = getFirstSubalbum();
735  while(curCollection != NULL )
736  {
737  mostPhotos = QMAX( mostPhotos, curCollection->getNumPhotos() );
738  curCollection = curCollection->getNext();
739  }
740  uint photoDigits = (uint) ( 1 + log( (double) mostPhotos ) / log( 10.0 ) );
741  //------------
742  //copy files
743  int numPhotos = getNumPhotos();
744  int photosLeft = numPhotos;
745 
746  int collectionNum = 1;
747  curCollection = getFirstSubalbum();
748 
749  int updateInverval = numPhotos / 50;
750  int updateCount = 0;
751 
752  while(curCollection != NULL )
753  {
754  //construct collection string
755  QString collectionString = QString("%1").arg(collectionNum);
756  while(collectionString.length() < collectionDigits)
757  { collectionString = "0" + collectionString; }
758 
759  //copy all photos in collection
760  int photoNum = 1;
761  Photo* curPhoto = curCollection->getFirst();
762  while(curPhoto != NULL)
763  {
764  //update status message
765  status->updateProgress( numPhotos - photosLeft, exportMessage.arg( photosLeft ) );
766 
767  //make sure events are processed every 2% of the photos that are processes
768  updateCount++;
769  if(updateCount > updateInverval)
770  {
771  updateCount = 0;
772  qApp->processEvents();
773  }
774 
775  //construct photo string
776  QString photoString = QString("%1").arg(photoNum);
777  while(photoString.length() < photoDigits)
778  { photoString = "0" + photoString; }
779 
780  //construct new photo path
781  QString newFilePath = QDir::convertSeparators( exportPath + "/" + collectionString +
782  "_" + photoString + ".jpg" );
783  //copy file
784  copyFile( curPhoto->getImageFilename(), newFilePath );
785 
786  //move on to next file
787  photosLeft--;
788  curPhoto = curPhoto->getNext();
789  photoNum++;
790 
791  } //while photo
792 
793  //move on to next collection
794  curCollection = curCollection->getNext();
795  collectionNum++;
796  }// while collection
797  //------------
798  return ALBUM_EXPORTED;
799 }
800 //==============================================
801 int Album::exportToXML(StatusWidget* status, QString exportPath)
802 {
803  //update modification date
805 
806  //create/open xml file
807  QFile file( exportPath + "/Album.xml" );
808  if(file.open(QIODevice::WriteOnly))
809  {
810  //-----
811  Q3TextStream stream;
812  stream.setDevice( &file );
813  stream.setEncoding( Q3TextStream::UnicodeUTF8 );
814 
815  //write album information
816  stream << "<?xml version=\"1.0\"?>\n";
817  stream << "<album version=\"1.1\">\n";
818  stream << " <name>" << fixXMLString(name) << "</name>\n";
819  stream << " <description>" << fixXMLString(description) << "</description>\n";
820  stream << " <author>" << fixXMLString(author) << "</author>\n";
821  stream << " <created>" << creationYear << " " << creationMonth << " " << creationDay << "</created>\n";
822  stream << " <modified>" << modificationYear << " " << modificationMonth << " " << modificationDay << "</modified>\n";
823  stream << " <theme>" << theme << "</theme>\n";
824  stream << " <thumbnailDimensions>" << THUMBNAIL_WIDTH << " " << THUMBNAIL_HEIGHT << "</thumbnailDimensions>\n";
825  stream << " <slideshowDimensions>" << SLIDESHOW_WIDTH << " " << SLIDESHOW_HEIGHT << "</slideshowDimensions>\n";
826 
827  //if album has a represenatative image save it's path
828  if(getRepresentativeImage(LARGE) != NULL )
829  {
830  stream << " <thumb path=\"img/album.jpg\"/>\n";
831  }
832 
833  //write subalbums
834  Subalbum* current = firstSubalbum;
835  while(current != NULL)
836  {
837  current->exportToXML(status, stream);
838  current = current->getNext();
839  }
840 
841  //end album
842  stream << "</album>\n";
843  file.close();
844 
845  return ALBUM_EXPORTED;
846  }
847  else
848  {
849  return ALBUM_ERROR_OPEN_FILE;
850  }
851 }
852 //==============================================
854 {
855  //if image set export it
856  if(getRepresentativeImage(LARGE) != NULL)
857  {
858  getRepresentativeImage(LARGE)->save(saveLocation + "/img/album.jpg", "JPEG", 95);
859  }
860  //else make sure any previously set images are removed
861  else
862  {
863  QDir rootDir(saveLocation + "/img/");
864  rootDir.remove(saveLocation + "/img/album.jpg");
865  }
866 
867  //export subalbum thumbs
868  int n=0;
869  Subalbum* current = firstSubalbum;
870  while(current != NULL)
871  {
872  n++;
873  //if subalbum has representative image export it
874  if(current->getRepresentativeImage(LARGE) != NULL )
875  {
876  QString fileName = QString(saveLocation + "/img/%1_thumb.jpg" ).arg(n);
877  current->getRepresentativeImage(LARGE)->save(fileName, "JPEG", 95);
878  }
879  //otherwise make sure anyprevious set images are removed
880  else
881  {
882  QDir rootDir(saveLocation + "/img/");
883  rootDir.remove( saveLocation + QString("/img/%1_thumb.jpg").arg(n) );
884  }
885  current = current->getNext();
886  }
887 }
888 //==============================================
890 {
891  //iterate over all subalbums
892  int subalbumNumber=0;
893  Subalbum* currentSubalbum = firstSubalbum;
894  while(currentSubalbum != NULL)
895  {
896  subalbumNumber++;
897 
898  //iterate over all photos in this subalbum
899  int photoNumber=0;
900  Photo* currentPhoto = currentSubalbum->getFirst();
901  while(currentPhoto != NULL)
902  {
903  photoNumber++;
904  //---------------------------------------
905  //if the current photo does not need to be saved then move on
906  if( !forceSave && !currentPhoto->getNeedsSavingVal() )
907  {
908  currentPhoto = currentPhoto->getNext();
909  status->incrementProgress();
910  qApp->processEvents();
911  continue;
912  }
913  //---------------------------------------
914  //get initial photo # and subalbum #, used for saving
915  int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
916  int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
917  //---------------------------------------
918  //export thumbnail image
919  QString oldName = currentPhoto->getThumbnailFilename();
920  QString newName = QString(saveLocation + "/img/%1/%2_thumb.jpg" )
921  .arg(initSubalbumNumber).arg(initPhotoNumber);
922 
923  //if file has been modified move from current location to final location
924  if( currentPhoto->getNeedsSavingVal() ) { moveFile( oldName, newName ); }
925  //If file has not been modified we must be doing a save-as and saving has been forced. In this case
926  //COPY file from current location to final location, DON'T delete previous copy!!!
927  else { copyFile(oldName, newName); }
928 
929  //compute and store md5 for slideshow image
930  std::ifstream thumbnailFile( QFile::encodeName(newName) );
931  if(thumbnailFile.is_open())
932  {
933  currentPhoto->setThumbnailChecksum( getMD5(thumbnailFile) );
934  thumbnailFile.close();
935  }
936  //---------------------------------------
937  //export slideshow image
938  oldName = currentPhoto->getSlideshowFilename();
939  newName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" )
940  .arg(initSubalbumNumber).arg(initPhotoNumber);
941 
942  //if file has been modified move from current location to final location
943  if( currentPhoto->getNeedsSavingVal() ) { moveFile( oldName, newName ); }
944  //If file has not been modified we must be doing a save-as and saving has been forced. In this case
945  //COPY file from current location to final location, DON'T delete previous copy!!!
946  else { copyFile(oldName, newName); }
947 
948  //compute and store md5 for slideshow image
949  std::ifstream slideshowFile( QFile::encodeName(newName) );
950  if(slideshowFile.is_open())
951  {
952  currentPhoto->setSlideshowChecksum( getMD5(slideshowFile) );
953  slideshowFile.close();
954  }
955  //---------------------------------------
956  //export full size image
957  oldName = currentPhoto->getImageFilename();
958  newName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
959 
960  //if file has been modified move from current location to final location
961  if( currentPhoto->getNeedsSavingVal() )
962  {
963  QString tempOrigName = getTmpDir() + QString("/%1_%2_orig.jpg")
964  .arg(initSubalbumNumber).arg(initPhotoNumber);
965 
966  QString finalOrigName = QString(saveLocation + "/img/%1/%2_orig.jpg" )
967  .arg(initSubalbumNumber).arg(initPhotoNumber);
968 
973  QDir tmpDir;
974  if( !currentPhoto->getRecentlyReverted() &&
975  tmpDir.exists(newName) &&
976  !tmpDir.exists(finalOrigName) )
977  {
978  moveFile( newName, finalOrigName );
979  }
980  //if photo previously saved, there is no orig file, but the photo
981  //is modified and we're doing a force save than make sure to copy
982  //over the original as well even though it's not an orig file
983  else if ( currentPhoto->getEverSaved() &&
984  currentPhoto->getNeedsSavingVal() &&
985  forceSave &&
986  saveLocation.compare( oldSaveLocation ) != 0 )
987  {
988  QString storedOrigLocation = oldSaveLocation +
989  QString("/img/%1/%2_orig.jpg").arg(currentPhoto->getInitialSubalbumNumber())
990  .arg(currentPhoto->getInitialPhotoNumber());
991  QString storedLocation = oldSaveLocation +
992  QString("/img/%1/%2.jpg").arg(currentPhoto->getInitialSubalbumNumber())
993  .arg(currentPhoto->getInitialPhotoNumber());
994 
995  if( tmpDir.exists(storedOrigLocation) )
996  copyFile( storedOrigLocation, finalOrigName );
997  else if( tmpDir.exists(storedLocation) )
998  copyFile( storedLocation, finalOrigName );
999  }
1004  else if( !currentPhoto->getRecentlyReverted() &&
1005  !tmpDir.exists(newName) &&
1006  tmpDir.exists(tempOrigName) )
1007  {
1008  moveFile( tempOrigName, finalOrigName );
1009  }
1010 
1012  moveFile( oldName, newName );
1013  }
1014  //If file does not need to be saved a force save is taking place. This occurs when a user chooses
1015  //save as and copies an entire album to a different location so all files must be copied. Make
1016  //sure to copy over the original form of the photo as well if this file exists
1017  else
1018  {
1019  //copy current image
1020  copyFile( oldName, newName );
1021 
1023  //if orig file exists copy it too
1024  QDir tmpDir;
1025 
1026  QString tempOrigName = getTmpDir() + QString("/%1_%2_orig.jpg")
1027  .arg(initSubalbumNumber).arg(initPhotoNumber);
1028 
1029  QString curOrigName = currentPhoto->getImageFilename();
1030  curOrigName.truncate( curOrigName.length() - 4 );
1031  curOrigName = curOrigName + "_orig.jpg";
1032 
1033  QString finalOrigName = QString(saveLocation + "/img/%1/%2_orig.jpg" )
1034  .arg(initSubalbumNumber).arg(initPhotoNumber);
1035 
1036  //if the photo was recently reverted ignore the presence of orig files
1037  if( !currentPhoto->getRecentlyReverted() )
1038  {
1039  //if the photo was never previously saved and an orig file
1040  //exists in the tmp directory make sure to copy it over
1041  if( !currentPhoto->getEverSaved() &&
1042  tmpDir.exists( tempOrigName ) )
1043  {
1044  copyFile( tempOrigName, finalOrigName );
1045  }
1046  //if the photo was previously saved and an orig file exists
1047  //in the previous save location make sure to copy it over
1048  else if( currentPhoto->getEverSaved() &&
1049  tmpDir.exists( curOrigName ) )
1050  {
1051  copyFile( curOrigName, finalOrigName );
1052  }
1053  }
1055  }
1056  //---------------------------------------
1057  //compute and store md5 for image
1058  std::ifstream imageFile( QFile::encodeName(newName) );
1059  if(imageFile.is_open())
1060  {
1061  currentPhoto->setImageChecksum( getMD5(imageFile) );
1062  imageFile.close();
1063  }
1064  //---------------------------------------
1065  //set new storage locations of files
1066  currentPhoto->setImageFilename
1067  ( QString(saveLocation + "/img/%1/%2.jpg").arg(initSubalbumNumber).arg(initPhotoNumber) );
1068 
1069  currentPhoto->setSlideshowFilename
1070  ( QString(saveLocation + "/img/%1/%2_slideshow.jpg").arg(initSubalbumNumber).arg(initPhotoNumber) );
1071 
1072  currentPhoto->setThumbnailFilename
1073  ( QString(saveLocation + "/img/%1/%2_thumb.jpg").arg(initSubalbumNumber).arg(initPhotoNumber) );
1074  //---------------------------------------
1075  //set image as not needing saving and as being saved
1076  currentPhoto->setNeedsSavingVal(false);
1077  currentPhoto->setEverSaved(true);
1078  //---------------------------------------
1079  //update progress bar
1080  status->incrementProgress();
1081  qApp->processEvents();
1082  //---------------------------------------
1083  //move on to next photo in subalbum
1084  currentPhoto = currentPhoto->getNext();
1085  //---------------------------------------
1086  }
1087  //---------------------------------------
1088  //move on to next subalbum
1089  currentSubalbum = currentSubalbum->getNext();
1090  }
1091 }
1092 //==============================================
1094 {
1095  QDir tmpDir;
1096 
1097  //iterate over all collections
1098  Subalbum* currentSubalbum = firstSubalbum;
1099  while(currentSubalbum != NULL)
1100  {
1101  //iterate over all photos in this subalbum
1102  Photo* currentPhoto = currentSubalbum->getFirst();
1103  while(currentPhoto != NULL)
1104  {
1105  //if photo recently reverted and orig file is not the current filename remove orig file
1106  //the orig and current name will match up if a previously saved (but not modified) photo
1107  //is modified, reverted, then saved out again
1108  if(currentPhoto->getRecentlyReverted() &&
1109  currentPhoto->getImageFilename().compare( currentPhoto->originalImageFilename() ) != 0 )
1110  {
1111  tmpDir.remove( currentPhoto->originalImageFilename() );
1112  currentPhoto->setRecentlyReverted( false );
1113  }
1114 
1115  //move on to next photo
1116  currentPhoto = currentPhoto->getNext();
1117  status->incrementProgress();
1118  qApp->processEvents();
1119  }
1120 
1121  //move on to next subalbum
1122  currentSubalbum = currentSubalbum->getNext();
1123  }
1124 }
1125 //==============================================
1127 {
1128  //--------------------------------------------------------
1129  //--------------------------------------------------------
1130  //first pass over all photos, those whose initial and current numbers don't match up
1131  //rename slightly so we don't overwrte them the second time around
1132  //--------------------------------------------------------
1133  //--------------------------------------------------------
1134  //iterate over all subalbums
1135  QDir tmpDir;
1136  int subalbumNumber=0;
1137  Subalbum* currentSubalbum = firstSubalbum;
1138  while(currentSubalbum != NULL)
1139  {
1140  subalbumNumber++;
1141 
1142  //iterate over all photos in this subalbum
1143  int photoNumber=0;
1144  Photo* currentPhoto = currentSubalbum->getFirst();
1145  while(currentPhoto != NULL)
1146  {
1147  photoNumber++;
1148  int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
1149  int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
1150 
1151  //if photo has moved rename full image, orig image (if it exists), slideshow image, and thumbnail images
1152  if( initPhotoNumber != photoNumber || initSubalbumNumber != subalbumNumber)
1153  {
1154  QString oldName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1155  QString newName = QString(saveLocation + "/img/%1/%2_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1156  moveFile( oldName, newName );
1157  //-----
1158  oldName = QString(saveLocation + "/img/%1/%2_orig.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1159  newName = QString(saveLocation + "/img/%1/%2_orig_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1160  if(tmpDir.exists(oldName) ) { moveFile( oldName, newName ); }
1161  //-----
1162  oldName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1163  newName = QString(saveLocation + "/img/%1/%2_slideshow_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1164  moveFile( oldName, newName );
1165  //-----
1166  oldName = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1167  newName = QString(saveLocation + "/img/%1/%2_thumb_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1168  moveFile( oldName, newName );
1169  }
1170 
1171  //move on to next photo
1172  currentPhoto = currentPhoto->getNext();
1173  status->incrementProgress();
1174  qApp->processEvents();
1175  }
1176 
1177  //move on to next subalbum
1178  currentSubalbum = currentSubalbum->getNext();
1179  }
1180 
1181  //--------------------------------------------------------
1182  //--------------------------------------------------------
1183  //second pass over all photos, those whose initial and current numbers don't match up
1184  //rename to their final names and reset initial photo and subalbum numbers
1185  //--------------------------------------------------------
1186  //--------------------------------------------------------
1187  //iterate over all subalbums
1188  subalbumNumber=0;
1189  currentSubalbum = firstSubalbum;
1190  while(currentSubalbum != NULL)
1191  {
1192  subalbumNumber++;
1193 
1194  //iterate over all photos in this subalbum
1195  int photoNumber=0;
1196  Photo* currentPhoto = currentSubalbum->getFirst();
1197  while(currentPhoto != NULL)
1198  {
1199  photoNumber++;
1200  int initPhotoNumber = currentPhoto->getInitialPhotoNumber();
1201  int initSubalbumNumber = currentPhoto->getInitialSubalbumNumber();
1202 
1203  //if the current photo has moved rename full image, slideshow image, and thumbnail image to their final names
1204  if( initPhotoNumber != photoNumber || initSubalbumNumber != subalbumNumber)
1205  {
1206  QString oldName = QString(saveLocation + "/img/%1/%2_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1207  QString newName = QString(saveLocation + "/img/%1/%2.jpg" ).arg(subalbumNumber).arg(photoNumber);
1208  moveFile( oldName, newName );
1209  //-----
1210  oldName = QString(saveLocation + "/img/%1/%2_orig_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1211  newName = QString(saveLocation + "/img/%1/%2_orig.jpg" ).arg(subalbumNumber).arg(photoNumber);
1212  if(tmpDir.exists(oldName) ) { moveFile( oldName, newName ); }
1213  //-----
1214  oldName = QString(saveLocation + "/img/%1/%2_slideshow_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1215  newName = QString(saveLocation + "/img/%1/%2_slideshow.jpg" ).arg(subalbumNumber).arg(photoNumber);
1216  moveFile( oldName, newName );
1217  //-----
1218  oldName = QString(saveLocation + "/img/%1/%2_thumb_moved.jpg" ).arg(initSubalbumNumber).arg(initPhotoNumber);
1219  newName = QString(saveLocation + "/img/%1/%2_thumb.jpg" ).arg(subalbumNumber).arg(photoNumber);
1220  moveFile( oldName, newName );
1221  //---------------------------------------
1222  //reset initial photo and subalbum numbers, and filenames
1223  currentPhoto->setInitialPhotoNumber(photoNumber);
1224  currentPhoto->setInitialSubalbumNumber(subalbumNumber);
1225  currentPhoto->setImageFilename( QString(saveLocation + "/img/%1/%2.jpg").
1226  arg(subalbumNumber).arg(photoNumber) );
1227  currentPhoto->setSlideshowFilename( QString(saveLocation + "/img/%1/%2_slideshow.jpg").
1228  arg(subalbumNumber).arg(photoNumber) );
1229  currentPhoto->setThumbnailFilename( QString(saveLocation + "/img/%1/%2_thumb.jpg").
1230  arg(subalbumNumber).arg(photoNumber) );
1231  }
1232 
1233  //move on to next photo
1234  currentPhoto = currentPhoto->getNext();
1235  status->incrementProgress();
1236  qApp->processEvents();
1237  }
1238 
1239  //move on to next subalbum
1240  currentSubalbum = currentSubalbum->getNext();
1241  }
1242 }
1243 //==============================================
1245 {
1246  QDir rootDir(saveLocation + "/img/");
1247 
1248  //iterate over each collection
1249  int subalbumNumber=0;
1250  Subalbum* currentSubalbum = firstSubalbum;
1251  while(currentSubalbum != NULL)
1252  {
1253  subalbumNumber++;
1254 
1255  //remove all photos who are numbered greater
1256  //than the number of photos in the subalbum
1257  int photoNum = currentSubalbum->getNumPhotos()+1;
1258  while(true)
1259  {
1260  QString imageString = QString(saveLocation + "/img/%1/%2.jpg").arg(subalbumNumber).arg(photoNum);
1261  QString origString = QString(saveLocation + "/img/%1/%2_orig.jpg").arg(subalbumNumber).arg(photoNum);
1262  QString slideshowString = QString(saveLocation + "/img/%1/%2_slideshow.jpg").arg(subalbumNumber).arg(photoNum);
1263  QString thumbString = QString(saveLocation + "/img/%1/%2_thumb.jpg").arg(subalbumNumber).arg(photoNum);
1264 
1265  //if none of the possible images exist then assume
1266  //no more stagnant images exist in this collection
1267  //
1268  if( !rootDir.exists(imageString) && !rootDir.exists(origString) &&
1269  !rootDir.exists(slideshowString) && !rootDir.exists(thumbString) )
1270  break;
1271  //else delete photos and move on
1272  else
1273  {
1274  rootDir.remove( imageString );
1275  rootDir.remove( origString );
1276  rootDir.remove( slideshowString );
1277  rootDir.remove( thumbString );
1278  photoNum++;
1279  }
1280  }
1281 
1282  //reset number of loaded photos since old photos removed now
1283  currentSubalbum->resetNumLoadedPhotos();
1284 
1285  //move on to next collection
1286  currentSubalbum = currentSubalbum->getNext();
1287  }
1288  //---------------------------------
1289  //remove stagnant collections and all their contents
1290  subalbumNumber = numSubalbums+1;
1291  while(true)
1292  {
1293  //check to see if the directory exists, if not we are done
1294  QString imageDirString = QString(saveLocation + "/img/%1/").arg(subalbumNumber);
1295  if( !rootDir.exists(imageDirString) )
1296  break;
1297 
1298  //get filelist for directory
1299  QDir imageDir( imageDirString );
1300  QStringList list = imageDir.entryList( QDir::Files );
1301 
1302  //remove each file in directory
1303  QStringList::Iterator file;
1304  for ( file = list.begin(); file != list.end(); ++file )
1305  { rootDir.remove( QString(saveLocation + "/img/%1/" + *file).arg(subalbumNumber) ); }
1306 
1307  //remove directory
1308  rootDir.rmdir( QString("%1").arg(subalbumNumber) );
1309 
1310  //remove thumbnail image
1311  rootDir.remove( QString(saveLocation + "/img/%1_thumb.jpg").arg(subalbumNumber) );
1312 
1313  //move on to next subalbum
1314  subalbumNumber++;
1315  }
1316 
1317  //reset number of loaded subalbums since stagnant directories removed now
1319  //---------------------------------
1320 }
1321 //==============================================
1323 {
1324  QStringList fileList;
1325  QStringList::Iterator file;
1326  QDir localDir;
1327 
1328  //remove any "resources" directories created by 1.0* versions of Album Shaper
1329  localDir.setPath( saveLocation + "/resources" );
1330  fileList = localDir.entryList();
1331  for(file = fileList.begin(); file != fileList.end(); file++)
1332  {
1333  localDir.remove(saveLocation + "/resources/" + *file);
1334  }
1335  localDir.cdUp();
1336  localDir.rmdir( "resources" );
1337 
1338  //create HTML and misc resources directories
1339  localDir.setPath(saveLocation);
1340  localDir.mkdir("resources");
1341 // localDir.mkdir("misc_resources");
1342 
1343  //remove all files in these directories from previous saves with other themes
1344  localDir.setPath(saveLocation + "/resources");
1345  fileList = localDir.entryList( QDir::Files );
1346  for ( file = fileList.begin(); file != fileList.end(); ++file )
1347  { localDir.remove( saveLocation + "/resources/" + *file ); }
1348  //--
1349 /*
1350  localDir.setPath(saveLocation + "/misc_resources");
1351  fileList = localDir.entryList( QDir::Files );
1352  for ( file = fileList.begin(); file != fileList.end(); ++file )
1353  { localDir.remove( saveLocation + "/misc_resources/" + *file ); }
1354 */
1355  //copy files over from theme's directory
1356  localDir.setPath(THEMES_PATH + theme + "/resources");
1357  fileList = localDir.entryList( QDir::Files );
1358  for ( file = fileList.begin(); file != fileList.end(); ++file )
1359  { copyFile( THEMES_PATH + theme + "/resources/" + *file, saveLocation + "/resources/" + *file); }
1360  //--
1361 /*
1362  localDir.setPath(THEMES_PATH + theme + "/misc_resources");
1363  fileList = localDir.entryList( QDir::Files );
1364  for ( file = fileList.begin(); file != fileList.end(); ++file )
1365  { copyFile( THEMES_PATH + theme + "/misc_resources/" + *file, saveLocation + "/misc_resources/" + *file); }
1366 */
1367 }
1368 //==============================================
1370 {
1371  //check to see if any changes actually took place
1372  bool change = false;
1373  Subalbum* tmp = firstSubalbum;
1374  SubalbumPreviewWidget* tmp2 = item;
1375  while( tmp2 != NULL)
1376  {
1377  //pointers do not match up
1378  if(tmp != tmp2->getSubalbum() )
1379  {
1380  change = true;
1381  break;
1382  }
1383 
1384  tmp = tmp->getNext();
1385  tmp2 = (SubalbumPreviewWidget*)tmp2->nextItem();
1386  }
1387 
1388  //if no change then quit
1389  if(!change)
1390  return;
1391 
1392  //base case, no items
1393  if(item == NULL)
1394  {
1395  firstSubalbum = NULL;
1396  lastSubalbum = NULL;
1397  return;
1398  }
1399 
1400  //set first and last pointers
1401  firstSubalbum = item->getSubalbum();
1402  firstSubalbum->setNext(NULL);
1403  firstSubalbum->setPrev(NULL);
1405 
1406  //set all next pointers
1407  while(item->nextItem() != NULL)
1408  {
1409  item->getSubalbum()->setNext( ((SubalbumPreviewWidget*)item->nextItem())->getSubalbum() );
1410  item->getSubalbum()->getNext()->setPrev( item->getSubalbum() );
1411  item = (SubalbumPreviewWidget*)item->nextItem();
1412  lastSubalbum = item->getSubalbum();
1413  lastSubalbum->setNext(NULL);
1414  }
1415 
1416 }
1417 //==============================================
1418 void Album::setModified(bool val) { modified = val; }
1419 //==============================================
1421 {
1422  nextUniqueID++;
1423  return nextUniqueID;
1424 }
1425 //==============================================
1427 {
1428  //iterate over all collections
1429  QStringList thumbnailList;
1430  Subalbum* currCollection = firstSubalbum;
1431  while(currCollection != NULL)
1432  {
1433  //iterate over all photos
1434  Photo* currPhoto = currCollection->getFirst();
1435  while( currPhoto != NULL )
1436  {
1437  thumbnailList.append( currPhoto->getThumbnailFilename() );
1438  currPhoto = currPhoto->getNext();
1439  }
1440 
1441  currCollection = currCollection->getNext();
1442  }
1443 
1444  return thumbnailList;
1445 }
1446 //==============================================
void removeStagnantImages()
Removes old stagnant images caused when photos are removed from album or moved from one subalbum to a...
Definition: album.cpp:1244
bool albumModified()
Returns true if album has been modified since the last save operation.
Definition: album.cpp:139
#define ALBUM_EXPORTED
Definition: album.h:25
void resetNumLoadedPhotos()
Definition: subalbum.cpp:171
void setDescription(QString val)
Sets the album description.
Definition: album.cpp:168
QString getDescription()
Gets the album description.
Definition: album.cpp:125
QString getName()
Gets the album name.
Definition: album.cpp:124
void importFromDisk(QDomNode *root, int subalbumNum, StatusWidget *status, QString dirName, bool disableCheckPhotoMods)
Builds subalbum from XML DOM node.
Definition: subalbum.cpp:350
int modificationDay
Last modification day.
Definition: album.h:224
Subalbum * lastSubalbum
Pointer to last Subalbum.
Definition: album.h:215
QString getImageFilename()
Gets the image filename.
Definition: photo.cpp:192
#define LARGE
Definition: album.h:19
int getModificationMonth()
Returns the last modified month.
Definition: album.cpp:117
QString originalImageFilename()
orig filename
Definition: photo.cpp:572
int getCreationYear()
Returns the creation year.
Definition: album.cpp:120
A photo consists of a full size image, a smaller slide show image, a very small thumbnail image...
Definition: photo.h:44
int numSubalbums
Number of subalbums.
Definition: album.h:236
Subalbum * getSubalbum()
Returns subalbum pointer.
int getNumSubalbums()
Returns number of subalbums.
Definition: album.cpp:144
bool modified
Modification status of the album.
Definition: album.h:254
int creationDay
Creation day.
Definition: album.h:233
QPixmap * smallRepresentativeImage
Representative images.
Definition: album.h:208
QString oldSaveLocation
Definition: album.h:248
void appendSubalbum(Subalbum *val)
Appends subalbum to end of linked list.
Definition: album.cpp:234
void incrementProgress()
Updates the progress bar by one step.
void setInitialSubalbumNumber(int val)
Sets initial subalbum number.
Definition: photo.cpp:612
int creationYear
Creation year.
Definition: album.h:227
int modificationYear
Last modification year.
Definition: album.h:218
QString getSaveLocation()
Returns the current save location of all images.
Definition: album.cpp:141
void showProgressBar(QString message, int numSteps)
Initializes the progress bar.
bool moveFile(QString oldName, QString newName)
Definition: fileTools.cpp:40
void removeStagnantOrigFiles(StatusWidget *status)
Removes any _orig images for photos which have been recently reverted to their original form (and hen...
Definition: album.cpp:1093
QString theme
Theme to save album with.
Definition: album.h:251
#define ALBUM_XML_ERROR
Definition: album.h:24
void setImageFilename(QString val)
Sets the image filename.
Definition: photo.cpp:196
QString getThumbnailFilename()
Gets the thumbnail filename.
Definition: photo.cpp:194
void exportToXML(StatusWidget *status, Q3TextStream &stream)
Exports subalbum to xml.
Definition: subalbum.cpp:313
int nextUniqueID
Next Unique ID for new photos.
Definition: album.h:262
void setPrev(Subalbum *val)
Sets pointer of prev subalbum.
Definition: subalbum.cpp:301
void setAuthor(QString val)
Sets the album author.
Definition: album.cpp:177
QPixmap * getRepresentativeImage(int size)
Returns the representative image.
Definition: album.cpp:128
bool getRecentlyReverted()
was the photo recently reverted? if so ignore the presence of orig files on disk
Definition: photo.cpp:547
QString getMD5(std::ifstream &stream)
Definition: md5.cpp:542
#define SMALL
Definition: album.h:17
QString description
Longer description of album.
Definition: album.h:202
void transformXMLtoHTML(QString outputPath, QString theme, bool smallWebExport)
Definition: xmlTools.cpp:50
void exportTopLevelImages()
Exports top level images.
Definition: album.cpp:853
Photo * getNext()
Returns next photo pointer.
Definition: photo.cpp:225
#define REP_IMAGE_HEIGHT
Definition: config.h:29
#define ALBUM_LOADED
Definition: album.h:22
int importFromDisk(StatusWidget *status, QString fileName, bool disableCheckPhotoMods)
Imports album from XML format, returning int indicates success or not.
Definition: album.cpp:295
void setRecentlyReverted(bool val)
reset the recently reverted value to val
Definition: photo.cpp:552
QStringList getThumbnailFilenames()
Returns a list of the most up to date thumbnail filesnames.
Definition: album.cpp:1426
void syncSubalbumList(SubalbumPreviewWidget *item)
Syncs subalbum ordering with front end gui ordering.
Definition: album.cpp:1369
void setStatus(QString message)
Update message.
void setNext(Subalbum *val)
Sets pointer of next subalbum.
Definition: subalbum.cpp:307
#define ALBUM_ERROR_OPEN_FILE
Definition: album.h:26
#define THUMBNAIL_HEIGHT
Definition: config.h:25
bool copyFile(QString oldFilePath, QString newFilePath)
Copies a file from one location to another.
Definition: fileTools.cpp:61
Album(QString tmpDir, bool createSubalbum=true)
Sets default information and create temporary directory as necessary.
Definition: album.cpp:41
int getInitialSubalbumNumber()
Returns initial subalbum number.
Definition: photo.cpp:611
StatusWidget * status
int getNumPhotos()
Returns the number of photos.
Definition: album.cpp:146
QString name
Short name for album.
Definition: album.h:199
A subalbum contains photos.
Definition: subalbum.h:48
void setModified(bool val=true)
Sets the album as modified.
Definition: album.cpp:1418
void setImageChecksum(QString val)
Update image checksum.
Definition: photo.cpp:204
int getInitialPhotoNumber()
Returns initial photo number.
Definition: photo.cpp:608
void setRepresentativeImages(QString imageFilename)
Sets the representative image.
Definition: album.cpp:186
void removeSubalbum(Subalbum *val)
Removes a subalbum.
Definition: album.cpp:257
int modificationMonth
Last modification month.
Definition: album.h:221
void setSlideshowChecksum(QString val)
Update slideshow checksum.
Definition: photo.cpp:206
QString saveLocation
Directory album saved to.
Definition: album.h:245
int getNumPhotos()
Returns the number of photos in the subalbum.
Definition: subalbum.cpp:104
void setEverSaved(bool val)
sets everSaved
Definition: photo.cpp:535
Displays subalbum icon and name.
int getModificationYear()
Returns the last modified year.
Definition: album.cpp:116
#define ALBUM_READ_ERROR
Definition: album.h:23
int numLoadedSubalbums
Number of loaded subalbums.
Definition: album.h:239
int getCreationMonth()
Returns the creation month.
Definition: album.cpp:121
void setThumbnailFilename(QString val)
Sets the thumbnail filename.
Definition: photo.cpp:198
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
Definition: imageTools.cpp:157
void setNeedsSavingVal(bool val)
Sets if the image needs to be saved to its permanent location.
Definition: photo.cpp:532
QPixmap * getRepresentativeImage(int size)
gets a sized representative image
Definition: subalbum.cpp:87
void reorderSubalbumImages(StatusWidget *status)
Checks if images need to be moved and does so if necessary.
Definition: album.cpp:1126
bool getEverSaved()
Returns if the image has ever been saved to a permanant location.
Definition: photo.cpp:534
Photo * getFirst()
Returns first photo in subalbum.
Definition: subalbum.cpp:100
bool getImageSize(const char *filename, QSize &size)
Get image dimensions.
Definition: imageTools.cpp:192
void setThumbnailChecksum(QString val)
Update thumbnail checksum.
Definition: photo.cpp:205
void setSlideshowFilename(QString val)
Sets the slideshow filename.
Definition: photo.cpp:197
Subalbum * getFirstSubalbum()
Returns a pointer to the first Subalbum.
Definition: album.cpp:135
void updateCreationDate()
Updates the creation date to today&#39;s date.
Definition: album.cpp:277
int exportLargeImages(StatusWidget *status, QString exportPath, QString exportMessage)
Export fullsize images (excludes slideshow and thumbnail images, album and collection iamges...
Definition: album.cpp:726
bool getNeedsSavingVal()
Returns if the image needs to be saved to its permament location.
Definition: photo.cpp:531
Subalbum * firstSubalbum
Pointer to first Subalbum.
Definition: album.h:212
void updateXML(QString inputPath)
Definition: xmlTools.cpp:90
void exportThemeResources(QString theme)
Removes previously saved resources, copies over new resources.
Definition: album.cpp:1322
bool prevSave()
Returns true if album previously saved to disk.
Definition: album.cpp:138
int creationMonth
Creation month.
Definition: album.h:230
QString getSlideshowFilename()
Gets the slideshow filename.
Definition: photo.cpp:193
void updateModificationDate()
Updates the modification date to today&#39;s date.
Definition: album.cpp:286
QString fixXMLString(QString text)
Fix strings before exporting to XML such that & becomes &, etc...
Definition: xmlTools.cpp:36
QString getTmpDir()
Returns the temporary directory for use when modifying and adding new images.
Definition: album.cpp:142
int exportToXML(StatusWidget *status, QString exportPath)
Exports album to XML.
Definition: album.cpp:801
QPixmap * largeRepresentativeImage
Definition: album.h:209
int getModificationDay()
Returns the last modified day.
Definition: album.cpp:118
Subalbum * getLastSubalbum()
Returns a pointer to the last Subalbum.
Definition: album.cpp:136
int getCreationDay()
Returnst he creation day.
Definition: album.cpp:122
Subalbum * getNext()
Returns pointer to next subalbum.
Definition: subalbum.cpp:98
int exportCompressedWebAlbum(StatusWidget *status, QString exportLocation, QString exportMessage)
Export a compressed web album (excludes full size images and xml data)
Definition: album.cpp:616
QString getAuthor()
Gets the album author.
Definition: album.cpp:126
bool savedToDisk
Set if album was loaded/has been saved to disk.
Definition: album.h:242
void setSubalbumNumber(int newVal)
Sets the subalbum number to newVal.
Definition: subalbum.cpp:170
void exportSubalbumImages(StatusWidget *status, bool forceSave)
Exports subalbum images.
Definition: album.cpp:889
QString getTheme()
Returns currently selected theme.
Definition: album.cpp:143
int getNextUniquePhotoID()
Returns the next unique photo id.
Definition: album.cpp:1420
#define THUMBNAIL_WIDTH
Definition: config.h:24
QString tmpDir
Temporary directory for placing modified or new images before saving takes place. ...
Definition: album.h:257
void setInitialPhotoNumber(int val)
Sets initial photo number.
Definition: photo.cpp:609
void calcScaledImageDimensions(int origWidth, int origHeight, int idealWidth, int idealHeight, int &width, int &height)
Computes scale of image dimensions while respecting aspect ratio, equivalent to a QImage::scaleMin wi...
Definition: imageTools.cpp:39
#define SLIDESHOW_WIDTH
Definition: config.h:26
void setName(QString val)
Sets the album name.
Definition: album.cpp:159
#define SLIDESHOW_HEIGHT
Definition: config.h:27
int exportToDisk(StatusWidget *status, QString dirName, QString themeName)
Exports album in XML and HTML format, along with resized images.
Definition: album.cpp:452
Subalbum * getPrev()
Returns pointer to prev subalbum.
Definition: subalbum.cpp:97
~Album()
Frees Subalbums.
Definition: album.cpp:84
QString THEMES_PATH
Definition: config.cpp:21
QString author
Album Creator.
Definition: album.h:205
void updateProgress(int progress, QString newMessage=QString::null)
Updates the progress bar.