00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qimage.h>
00013 #include <qpixmap.h>
00014 #include <qstring.h>
00015 #include <qtextstream.h>
00016 #include <qdom.h>
00017 #include <fstream>
00018 #include <qdir.h>
00019 #include <qregexp.h>
00020 #include <qapplication.h>
00021
00022
00023 #include "album.h"
00024 #include "subalbum.h"
00025 #include "photo.h"
00026 #include "tools/imageTools.h"
00027 #include "tools/xmlTools.h"
00028 #include "tools/md5.h"
00029 #include "../config.h"
00030 #include "../gui/photoPreviewWidget.h"
00031 #include "../gui/statusWidget.h"
00032 #include "../gui/subalbumPreviewWidget.h"
00033
00034
00035 Subalbum::Subalbum(Album* albm, int number)
00036 {
00037
00038 this->number = number;
00039
00040
00041 numPhotos = 0;
00042 loadedPhotos = 0;
00043
00044
00045 name = qApp->translate("Subalbum", "Collection %1").arg(number);
00046 description ="";
00047
00048
00049 smallRepresentativeImage = NULL;
00050 mediumRepresentativeImage = SubalbumPreviewWidget::createSubalbumPixmap
00051 ( QString(IMAGE_PATH)+"miscImages/subalbum.png" );
00052 largeRepresentativeImage = NULL;
00053
00054
00055 firstPhoto = NULL;
00056 lastPhoto = NULL;
00057
00058
00059 prevSubalbum = NULL;
00060 nextSubalbum = NULL;
00061
00062
00063 this->albm = albm;
00064 }
00065
00066 Subalbum::~Subalbum()
00067 {
00068
00069 delete smallRepresentativeImage;
00070 delete mediumRepresentativeImage;
00071 delete largeRepresentativeImage;
00072
00073
00074 Photo* current = firstPhoto;
00075 while(current != NULL)
00076 {
00077 Photo* temp = current->getNext();
00078 delete current;
00079 current = temp;
00080 }
00081 }
00082
00083 QString Subalbum::getName() { return QString(name); }
00084 QString Subalbum::getDescription() { return QString(description); }
00085
00086 QPixmap* Subalbum::getRepresentativeImage(int size)
00087 {
00088 if(size == SMALL) return smallRepresentativeImage;
00089 if(size == MEDIUM) return mediumRepresentativeImage;
00090 if(size == LARGE) return largeRepresentativeImage;
00091 else return NULL;
00092 }
00093
00094 Album* Subalbum::getAlbum() { return albm; }
00095
00096 Subalbum* Subalbum::getPrev() { return prevSubalbum; }
00097 Subalbum* Subalbum::getNext() { return nextSubalbum; }
00098
00099 Photo* Subalbum::getFirst() { return firstPhoto; }
00100 Photo* Subalbum::getLast() { return lastPhoto; }
00101
00102 int Subalbum::getSubalbumNumber() { return number; }
00103 int Subalbum::getNumPhotos() { return numPhotos; }
00104 int Subalbum::getNumLoadedPhotos() { return loadedPhotos; }
00105
00106 void Subalbum::setName(QString val)
00107 {
00108 if(name != val)
00109 {
00110 name = val;
00111 albm->setModified();
00112 }
00113 }
00114
00115 void Subalbum::setDescription(QString val)
00116 {
00117 if(description != val)
00118 {
00119 description = val;
00120 albm->setModified();
00121 }
00122 }
00123
00124 void Subalbum::setRepresentativeImage(QString imageFilename)
00125 {
00126
00127 delete smallRepresentativeImage;
00128 delete mediumRepresentativeImage;
00129 delete largeRepresentativeImage;
00130
00131
00132 if(imageFilename.isNull())
00133 {
00134 smallRepresentativeImage = NULL;
00135 largeRepresentativeImage = NULL;
00136
00137 mediumRepresentativeImage = SubalbumPreviewWidget::createSubalbumPixmap
00138 ( QString(IMAGE_PATH)+"miscImages/subalbum.png" );
00139 }
00140
00141 else
00142 {
00143 int imageWidth, imageHeight;
00144 getImageSize( imageFilename, imageWidth, imageHeight );
00145
00146
00147 int smallRepWidth = 0;
00148 int smallRepHeight = 0;
00149 calcScaledImageDimensions( imageWidth, imageHeight,
00150 107, REP_IMAGE_HEIGHT,
00151 smallRepWidth, smallRepHeight);
00152 QImage thumbnailSmall;
00153 scaleImage( imageFilename, thumbnailSmall, smallRepWidth, smallRepHeight );
00154 smallRepresentativeImage = new QPixmap( thumbnailSmall.width(), thumbnailSmall.height() );
00155 smallRepresentativeImage->convertFromImage( thumbnailSmall );
00156
00157
00158 mediumRepresentativeImage = SubalbumPreviewWidget::createSubalbumPixmap( imageFilename );
00159
00160
00161 largeRepresentativeImage = new QPixmap( imageFilename );
00162
00163 }
00164
00165
00166 albm->setModified();
00167 }
00168
00169 void Subalbum::setSubalbumNumber(int newVal) { number = newVal; }
00170 void Subalbum::resetNumLoadedPhotos() { loadedPhotos = numPhotos; }
00171 void Subalbum::setModified() { albm->setModified(); }
00172
00173 void Subalbum::addPhoto(Photo* newPhoto)
00174 {
00175
00176 newPhoto->setNext(NULL);
00177 newPhoto->setPrev(NULL);
00178
00179
00180 if(firstPhoto == NULL)
00181 {
00182 firstPhoto = newPhoto;
00183 lastPhoto = newPhoto;
00184 }
00185
00186 else
00187 {
00188 lastPhoto->setNext(newPhoto);
00189 newPhoto->setPrev( lastPhoto );
00190 lastPhoto = newPhoto;
00191 }
00192
00193 numPhotos++;
00194 albm->setModified();
00195 }
00196
00197 bool Subalbum::addPhoto(QString fileName, bool replaceDescription, Photo* newPhoto)
00198 {
00199
00200 if(newPhoto == NULL)
00201 newPhoto = new Photo(this, getLast(), numPhotos);
00202
00203
00204
00205 if(replaceDescription)
00206 {
00207
00208 QString desc(fileName);
00209
00210
00211 desc = desc.section( QRegExp("/"), -1);
00212
00213
00214 int extensionIndex = desc.findRev( '.' );
00215 if(extensionIndex > 0 )
00216 desc.truncate(extensionIndex);
00217
00218
00219 desc = desc.replace('_', ' ');
00220
00221
00222 newPhoto->setDescription( desc );
00223 }
00224
00225
00226 if(!newPhoto->setImage(fileName, albm->getNextUniquePhotoID() ))
00227 {
00228 delete newPhoto;
00229 return false;
00230 }
00231
00232
00233 if(firstPhoto == NULL)
00234 {
00235 firstPhoto = newPhoto;
00236 lastPhoto = newPhoto;
00237 }
00238
00239 else
00240 {
00241 lastPhoto->setNext(newPhoto);
00242 newPhoto->setPrev( lastPhoto );
00243 lastPhoto = newPhoto;
00244 }
00245
00246 numPhotos++;
00247 albm->setModified();
00248 return true;
00249 }
00250
00251 bool Subalbum::lazyAddPhoto(QString imageName, QString slideshowName, QString thumbnailName,
00252 Photo* newPhoto)
00253 {
00254
00255 if(!newPhoto->setImage(imageName, slideshowName, thumbnailName))
00256 {
00257 delete newPhoto;
00258 return false;
00259 }
00260
00261
00262 if(firstPhoto == NULL)
00263 {
00264 firstPhoto = newPhoto;
00265 lastPhoto = newPhoto;
00266 }
00267
00268 else
00269 {
00270 lastPhoto->setNext(newPhoto);
00271 newPhoto->setPrev( lastPhoto );
00272 lastPhoto = newPhoto;
00273 }
00274
00275 numPhotos++;
00276 albm->setModified();
00277 return true;
00278 }
00279
00280 void Subalbum::removePhoto(Photo* val)
00281 {
00282
00283 if(val == NULL) return;
00284
00285
00286 if( val == firstPhoto ) firstPhoto = val->getNext();
00287 if( val == lastPhoto ) lastPhoto = val->getPrev();
00288
00289
00290 if( val->getPrev() != NULL ) val->getPrev()->setNext( val->getNext() );
00291 if( val->getNext() != NULL ) val->getNext()->setPrev( val->getPrev() );
00292
00293
00294 delete val;
00295 val = NULL;
00296 numPhotos--;
00297 albm->setModified();
00298 }
00299
00300 void Subalbum::setPrev(Subalbum* val)
00301 {
00302 prevSubalbum = val;
00303 albm->setModified();
00304 }
00305
00306 void Subalbum::setNext(Subalbum* val)
00307 {
00308 nextSubalbum = val;
00309 albm->setModified();
00310 }
00311
00312 void Subalbum::exportToXML(StatusWidget*, QTextStream& stream)
00313 {
00314
00315 stream << " <subalbum>\n";
00316
00317
00318 if(getRepresentativeImage(LARGE) != NULL )
00319 {
00320 stream << " <thumb path=\"img/" << number << "_thumb.jpg\"/>\n";
00321 stream << " <name>" << fixXMLString(name) << "</name>\n";
00322 }
00323
00324
00325 else
00326 {
00327 QString strippedName = fixXMLString(name);
00328 if(strippedName.stripWhiteSpace() == "")
00329 stream << QString(" <name>%1 %2</name>\n").arg(qApp->translate("Subalbum", "Collection")).arg(number);
00330 else
00331 stream << " <name>" << fixXMLString(name) << "</name>\n";
00332 }
00333
00334 stream << " <description>" << fixXMLString(description) << "</description>\n";
00335
00336
00337 Photo* current = firstPhoto;
00338 while(current != NULL)
00339 {
00340 current->exportToXML(stream);
00341 current = current->getNext();
00342 }
00343
00344
00345 stream << " </subalbum>\n";
00346
00347 }
00348
00349 void Subalbum::importFromDisk(QDomNode* root,
00350 int subalbumNum,
00351 StatusWidget* status,
00352 QString dirName,
00353 bool disableCheckPhotoMods)
00354 {
00355
00356 QString repName = QString(dirName + "/img/%1_thumb.jpg").arg(subalbumNum);
00357 QImage repImage(repName);
00358 if(!repImage.isNull())
00359 {
00360 setRepresentativeImage(repName);
00361 }
00362
00363 QDomNode node = root->firstChild();
00364 QDomText val;
00365 int photoNum = 0;
00366 while( !node.isNull() )
00367 {
00368
00369
00370 if( node.isElement() && node.nodeName() == "name" )
00371 {
00372 val = node.firstChild().toText();
00373 if(!val.isNull())
00374 name = val.nodeValue();
00375 name.replace("\\"","\"");
00376 }
00377
00378
00379 else if( node.isElement() && node.nodeName() == "description" )
00380 {
00381 val = node.firstChild().toText();
00382 if(!val.isNull())
00383 description = val.nodeValue();
00384 description.replace("\\"","\"");
00385 }
00386
00387
00388 else if( node.isElement() && node.nodeName() == "photo" )
00389 {
00390
00391 photoNum++;
00392
00393
00394 QString imageName = QString(dirName + "img/%1/%2.jpg").arg(subalbumNum).arg(photoNum);
00395 QString slideshowName = QString(dirName + "img/%1/%2_slideshow.jpg").arg(subalbumNum).arg(photoNum);
00396 QString thumbName = QString(dirName + "img/%1/%2_thumb.jpg").arg(subalbumNum).arg(photoNum);
00397 Photo* newPhoto = new Photo(this, getLast(), photoNum);
00398
00399
00400 QDateTime* modificationTimes = newPhoto->importFromDisk( &node );
00401
00402
00403 bool lazyLoad = true;
00404
00405
00406 if(!disableCheckPhotoMods)
00407 {
00408 QFileInfo info[3];
00409 info[0].setFile( imageName );
00410 info[1].setFile( slideshowName );
00411 info[2].setFile( thumbName );
00412 if(
00413 modificationTimes[0] != info[0].lastModified() ||
00414 modificationTimes[1] != info[1].lastModified() ||
00415 modificationTimes[2] != info[2].lastModified()
00416 )
00417 lazyLoad = false;
00418 }
00419
00420
00421
00422
00423 std::ifstream imageFile ( QFile::encodeName(imageName) );
00424 std::ifstream slideshowFile( QFile::encodeName(slideshowName) );
00425 std::ifstream thumbnailFile( QFile::encodeName(thumbName) );
00426
00427 if( imageFile.is_open() &&
00428 thumbnailFile.is_open() &&
00429 slideshowFile.is_open() &&
00430 (
00431 lazyLoad ||
00432 (
00433 getMD5(imageFile) == newPhoto->getImageChecksum() &&
00434 getMD5(slideshowFile) == newPhoto->getSlideshowChecksum() &&
00435 getMD5(thumbnailFile) == newPhoto->getThumbnailChecksum()
00436 )
00437 )
00438 )
00439 {
00440
00441 imageFile.close();
00442 slideshowFile.close();
00443 thumbnailFile.close();
00444
00445
00446 lazyAddPhoto(imageName, slideshowName, thumbName, newPhoto);
00447 }
00448
00449 else
00450 {
00451
00452 if(imageFile.is_open())
00453 imageFile.close();
00454 if(thumbnailFile.is_open())
00455 thumbnailFile.close();
00456
00457
00458 addPhoto(imageName, false, newPhoto);
00459 }
00460
00461 if(imageFile.is_open())
00462 imageFile.close();
00463 if(slideshowFile.is_open())
00464 slideshowFile.close();
00465 if(thumbnailFile.is_open())
00466 thumbnailFile.close();
00467
00468
00469 status->incrementProgress();
00470 qApp->processEvents();
00471 }
00472
00473
00474 node = node.nextSibling();
00475
00476 }
00477
00478
00479 resetNumLoadedPhotos();
00480
00481 }
00482
00483 void Subalbum::photoMoved(Photo* val)
00484 {
00485
00486 if(val == NULL) return;
00487
00488
00489 if(val == firstPhoto) firstPhoto = val->getNext();
00490 if(val == lastPhoto) lastPhoto = val->getPrev();
00491
00492
00493 if(val->getPrev() != NULL) val->getPrev()->setNext( val->getNext() );
00494 if(val->getNext() != NULL) val->getNext()->setPrev( val->getPrev() );
00495
00496 numPhotos--;
00497 albm->setModified();
00498 }
00499
00500 void Subalbum::syncPhotoList(PhotoPreviewWidget* item)
00501 {
00502
00503 if(item == NULL)
00504 {
00505 firstPhoto = NULL;
00506 lastPhoto = NULL;
00507 return;
00508 }
00509
00510
00511 firstPhoto = item->getPhoto();
00512 firstPhoto->setNext(NULL);
00513 firstPhoto->setPrev(NULL);
00514 lastPhoto = firstPhoto;
00515
00516
00517 while(item->nextItem() != NULL)
00518 {
00519 item->getPhoto()->setNext( ((PhotoPreviewWidget*)item->nextItem())->getPhoto() );
00520 item->getPhoto()->getNext()->setPrev( item->getPhoto() );
00521 item = (PhotoPreviewWidget*)item->nextItem();
00522 lastPhoto = item->getPhoto();
00523 lastPhoto->setNext(NULL);
00524 }
00525
00526 }
00527