00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <qimage.h>
00019 #include <qpixmap.h>
00020 #include <qstring.h>
00021 #include <qtextstream.h>
00022 #include <qdom.h>
00023 #include <fstream>
00024 #include <qdir.h>
00025 #include <qregexp.h>
00026 #include <qapplication.h>
00027
00028
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/photoWidget.h"
00036 #include "../gui/statusWidget.h"
00037 #include "../config.h"
00038
00039
00041 Subalbum::Subalbum(Album* albm, int number)
00042 {
00043
00044 this->number = number;
00045
00046
00047 numPhotos = 0;
00048 loadedPhotos = 0;
00049
00050
00051 name = "";
00052 description ="";
00053
00054
00055 smallRepresentativeImage = new QPixmap( QString(IMAGE_PATH)+"notSpecified.png" );
00056 mediumRepresentativeImage = new QPixmap( QString(IMAGE_PATH)+"subalbum.png" );
00057 largeRepresentativeImage = NULL;
00058
00059
00060 firstPhoto = NULL;
00061 lastPhoto = NULL;
00062
00063
00064 nextSubalbum = NULL;
00065
00066
00067 this->albm = albm;
00068 }
00069
00071 Subalbum::~Subalbum()
00072 {
00073
00074 delete smallRepresentativeImage;
00075 delete mediumRepresentativeImage;
00076 delete largeRepresentativeImage;
00077
00078
00079 Photo* current = firstPhoto;
00080 Photo* temp;
00081 while(current != NULL)
00082 {
00083 temp = current->getNext();
00084 delete current;
00085 current = temp;
00086 }
00087 }
00088
00090 void Subalbum::setName(QString val)
00091 {
00092 if(name != val)
00093 {
00094 name = val;
00095 albm->setModified();
00096 }
00097 }
00098
00100 QString Subalbum::getName()
00101 {
00102 return QString(name);
00103 }
00104
00106 void Subalbum::setDescription(QString val)
00107 {
00108 if(description != val)
00109 {
00110 description = val;
00111 albm->setModified();
00112 }
00113 }
00114
00116 QString Subalbum::getDescription()
00117 {
00118 return QString(description);
00119 }
00120
00121
00122 QPixmap* Subalbum::getRepresentativeImage(int size)
00123 {
00124 if(size == SMALL)
00125 return smallRepresentativeImage;
00126 if(size == MEDIUM)
00127 return mediumRepresentativeImage;
00128 if(size == LARGE)
00129 return largeRepresentativeImage;
00130 else
00131 return NULL;
00132 }
00133
00134
00135 void Subalbum::setRepresentativeImages(QImage* rawThumbnail)
00136 {
00137
00138
00139 delete smallRepresentativeImage;
00140 delete mediumRepresentativeImage;
00141 delete largeRepresentativeImage;
00142
00143
00144 int smallRepWidth = 0;
00145 int smallRepHeight = 0;
00146 int mediumRepWidth = 0;
00147 int mediumRepHeight = 0;
00148 resizeImage( rawThumbnail->width(), rawThumbnail->height(),
00149 131, 98,
00150 mediumRepWidth, mediumRepHeight);
00151 resizeImage( rawThumbnail->width(), rawThumbnail->height(),
00152 107, 80,
00153 smallRepWidth, smallRepHeight);
00154
00155
00156
00157
00158 QImage thumbnailSmall = rawThumbnail->smoothScale( smallRepWidth, smallRepHeight );
00159 smallRepresentativeImage = new QPixmap( smallRepWidth, smallRepHeight );
00160 smallRepresentativeImage->convertFromImage( thumbnailSmall );
00161
00162
00163 QImage thumbnailMedium = rawThumbnail->smoothScale( mediumRepWidth, mediumRepHeight );
00164 QImage* centeredThumbnailMedium = new QImage(131, 98, thumbnailMedium.depth());
00165 centeredThumbnailMedium->setAlphaBuffer(true);
00166
00167 int xDiff = 131 - mediumRepWidth;
00168 int yDiff = 98 - mediumRepHeight;
00169
00170
00171 int x, y;
00172 for(x=0; x< 131; x++)
00173 {
00174 for(y=0; y<98; y++)
00175 {
00176 centeredThumbnailMedium->setPixel(x, y, QColor(255, 255, 255).rgb());
00177 }
00178 }
00179
00180 int x2 = 0;
00181 for(x= xDiff/2; x < (xDiff/2) + mediumRepWidth; x++)
00182 {
00183 int y2 = 0;
00184 for(y= yDiff/2; y < (yDiff/2) + mediumRepHeight; y++)
00185 {
00186 centeredThumbnailMedium->setPixel(x, y, thumbnailMedium.pixel(x2, y2));
00187 y2++;
00188 }
00189 x2++;
00190 }
00191
00192 mediumRepresentativeImage = new QPixmap( centeredThumbnailMedium->width(), centeredThumbnailMedium->height() );
00193 mediumRepresentativeImage->convertFromImage( *centeredThumbnailMedium );
00194 delete centeredThumbnailMedium;
00195
00196 largeRepresentativeImage = new QPixmap(*rawThumbnail);
00197
00198
00199
00200 albm->setModified();
00201 }
00202
00203 void Subalbum::addPhoto(Photo* newPhoto)
00204 {
00205
00206 numPhotos++;
00207
00208
00209 newPhoto->setNext(NULL);
00210
00211
00212
00213 if(firstPhoto == NULL)
00214 {
00215 firstPhoto = newPhoto;
00216 lastPhoto = newPhoto;
00217 }
00218
00219 else
00220 {
00221 lastPhoto->setNext(newPhoto);
00222 lastPhoto = newPhoto;
00223 }
00224
00225
00226 albm->setModified();
00227 }
00228
00230 bool Subalbum::addPhoto(QString fileName, bool replaceDescription, Photo* newPhoto)
00231 {
00232 numPhotos++;
00233
00234
00235 if(newPhoto == NULL)
00236 newPhoto = new Photo(this, numPhotos);
00237
00238
00239
00240 if(replaceDescription)
00241 {
00242 QString desc(fileName);
00243 desc = desc.section( QRegExp("/"), -1);
00244 desc.truncate(desc.length() - 4);
00245 newPhoto->setDescription( desc );
00246 }
00247
00248
00249 if(!newPhoto->setImage(fileName))
00250 {
00251 delete newPhoto;
00252 return false;
00253 }
00254
00255
00256
00257 if(firstPhoto == NULL)
00258 {
00259 firstPhoto = newPhoto;
00260 lastPhoto = newPhoto;
00261 }
00262
00263 else
00264 {
00265 lastPhoto->setNext(newPhoto);
00266 lastPhoto = newPhoto;
00267 }
00268
00269
00270 QString saveName = QDir::homeDirPath() + QString("/.albumShaper/tmp/%1_%2")
00271 .arg(number)
00272 .arg(numPhotos);
00273
00274 newPhoto->getImage(IMAGE)->save( saveName + ".jpg", "JPEG", 100);
00275 newPhoto->getImage(SLIDESHOW)->save( saveName + "_slideshow.jpg", "JPEG", 100);
00276
00277 newPhoto->setImageFilename(saveName + ".jpg");
00278 newPhoto->setSlideshowFilename(saveName + "_slideshow.jpg");
00279
00280
00281 newPhoto->deallocateLargeImages();
00282
00283
00284 albm->setModified();
00285
00286 return true;
00287 }
00288
00289 bool Subalbum::lazyAddPhoto(QString imageName,
00290 QString slideshowName,
00291 QString thumbnailName,
00292 Photo* newPhoto)
00293 {
00294 numPhotos++;
00295
00296
00297 if(!newPhoto->setImage(imageName, slideshowName, thumbnailName))
00298 {
00299 delete newPhoto;
00300 return false;
00301 }
00302
00303
00304
00305 if(firstPhoto == NULL)
00306 {
00307 firstPhoto = newPhoto;
00308 lastPhoto = newPhoto;
00309 }
00310
00311 else
00312 {
00313 lastPhoto->setNext(newPhoto);
00314 lastPhoto = newPhoto;
00315 }
00316
00317
00318 albm->setModified();
00319
00320 return true;
00321 }
00322
00324 void Subalbum::removePhoto(Photo* val)
00325 {
00326
00327 Photo* current = firstPhoto;
00328 Photo* prev = NULL;
00329 while(current != val && current->getNext() != NULL)
00330 {
00331 prev = current;
00332 current = current->getNext();
00333 }
00334
00335 if(current == val)
00336 {
00337
00338 if(prev != NULL)
00339 prev->setNext(current->getNext());
00340
00341
00342 if(current == firstPhoto)
00343 firstPhoto = current->getNext();
00344 if(current == lastPhoto)
00345 lastPhoto = prev;
00346
00347
00348 delete current;
00349 current = NULL;
00350 numPhotos--;
00351 }
00352
00353
00354 albm->setModified();
00355 }
00356
00357 Subalbum* Subalbum::getNext()
00358 {
00359 return nextSubalbum;
00360 }
00361
00362 void Subalbum::setNext(Subalbum* val)
00363 {
00364 nextSubalbum = val;
00365
00366
00367 albm->setModified();
00368 }
00369
00370 void Subalbum::exportToXML(QTextStream& stream)
00371 {
00372
00373 stream << " <subalbum>\n";
00374 stream << " <name>" << fixXMLString(name) << "</name>\n";
00375 stream << " <description>" << fixXMLString(description) << "</description>\n";
00376
00377
00378 if(getRepresentativeImage(LARGE) != NULL )
00379 {
00380 stream << " <thumb path=\"img/" << number << "_thumb.jpg\"/>\n";
00381 }
00382
00383
00384 Photo* current = firstPhoto;
00385 while(current != NULL)
00386 {
00387 current->exportToXML(stream);
00388 current = current->getNext();
00389 }
00390
00391
00392 stream << " </subalbum>\n";
00393
00394 }
00395
00396 Photo* Subalbum::getFirst()
00397 {
00398 return firstPhoto;
00399 }
00400
00401 Photo* Subalbum::getLast()
00402 {
00403 return lastPhoto;
00404 }
00405
00406 void Subalbum::importFromDisk(QDomNode* root,
00407 int subalbumNum,
00408 StatusWidget* status,
00409 QString dirName)
00410 {
00411
00412 QString repName = QString(dirName + "/img/%1_thumb.jpg").arg(subalbumNum);
00413 QImage repImage(repName);
00414 if(!repImage.isNull())
00415 {
00416 setRepresentativeImages(&repImage);
00417 }
00418
00419 QDomNode node = root->firstChild();
00420 QDomText val;
00421 int photoNum = 0;
00422 while( !node.isNull() )
00423 {
00424
00425
00426 if( node.isElement() && node.nodeName() == "name" )
00427 {
00428 val = node.firstChild().toText();
00429 if(!val.isNull())
00430 name = val.nodeValue();
00431 }
00432
00433
00434 else if( node.isElement() && node.nodeName() == "description" )
00435 {
00436 val = node.firstChild().toText();
00437 if(!val.isNull())
00438 description = val.nodeValue();
00439 }
00440
00441
00442 else if( node.isElement() && node.nodeName() == "photo" )
00443 {
00444
00445 photoNum++;
00446
00447
00448 QString imageName = QString(dirName + "img/%1/%2.jpg").arg(subalbumNum).arg(photoNum);
00449 QString slideshowName = QString(dirName + "img/%1/%2_slideshow.jpg").arg(subalbumNum).arg(photoNum);
00450 QString thumbName = QString(dirName + "img/%1/%2_thumb.jpg").arg(subalbumNum).arg(photoNum);
00451 Photo* newPhoto = new Photo(this, photoNum);
00452
00453
00454 QDateTime* modificationTimes = newPhoto->importFromDisk( &node );
00455
00456
00457 bool lazyLoad = true;
00458 QFileInfo info[3];
00459 info[0].setFile( imageName );
00460 info[1].setFile( slideshowName );
00461 info[2].setFile( thumbName );
00462 if(modificationTimes[0] != info[0].lastModified() ||
00463 modificationTimes[1] != info[1].lastModified() ||
00464 modificationTimes[2] != info[2].lastModified())
00465 lazyLoad = false;
00466
00467
00468
00469
00470 std::ifstream imageFile( imageName );
00471 std::ifstream slideshowFile( slideshowName );
00472 std::ifstream thumbnailFile( thumbName );
00473
00474 if( lazyLoad ||
00475 (
00476 imageFile.is_open() &&
00477 thumbnailFile.is_open() &&
00478 slideshowFile.is_open() &&
00479 getMD5(imageFile) == newPhoto->getImageChecksum() &&
00480 getMD5(slideshowFile) == newPhoto->getSlideshowChecksum() &&
00481 getMD5(thumbnailFile) == newPhoto->getThumbnailChecksum()
00482 )
00483 )
00484 {
00485
00486 imageFile.close();
00487 slideshowFile.close();
00488 thumbnailFile.close();
00489
00490
00491 lazyAddPhoto(imageName, slideshowName, thumbName, newPhoto);
00492 }
00493
00494 else
00495 {
00496
00497 if(imageFile.is_open())
00498 imageFile.close();
00499 if(thumbnailFile.is_open())
00500 thumbnailFile.close();
00501
00502
00503 addPhoto(imageName, false, newPhoto);
00504 }
00505
00506 if(imageFile.is_open())
00507 imageFile.close();
00508 if(slideshowFile.is_open())
00509 slideshowFile.close();
00510 if(thumbnailFile.is_open())
00511 thumbnailFile.close();
00512
00513
00514 status->incrementProgress();
00515 qApp->processEvents();
00516 }
00517
00518
00519 node = node.nextSibling();
00520
00521 }
00522
00523
00524 resetNumLoadedPhotos();
00525
00526 }
00527
00528 void Subalbum::photoMoved(Photo* val)
00529 {
00530
00531 numPhotos--;
00532
00533
00534 Photo* current = firstPhoto;
00535 Photo* prev = NULL;
00536 while(current != NULL &&
00537 current != val)
00538 {
00539 prev = current;
00540 current = current->getNext();
00541 }
00542
00543 if(current == val)
00544 {
00545
00546 if(prev != NULL)
00547 prev->setNext(current->getNext());
00548
00549
00550 if(current == firstPhoto)
00551 firstPhoto = current->getNext();
00552 if(current == lastPhoto)
00553 lastPhoto = prev;
00554 }
00555
00556
00557 albm->setModified();
00558 }
00559
00560 void Subalbum::syncPhotoList(PhotoWidget* item)
00561 {
00562
00563 if(item == NULL)
00564 {
00565 firstPhoto = NULL;
00566 lastPhoto = NULL;
00567 return;
00568 }
00569
00570
00571 firstPhoto = item->getPhoto();
00572 firstPhoto->setNext(NULL);
00573 lastPhoto = firstPhoto;
00574
00575
00576 while(item->nextItem() != NULL)
00577 {
00578 item->getPhoto()->setNext( ((PhotoWidget*)item->nextItem())->getPhoto() );
00579 item = (PhotoWidget*)item->nextItem();
00580 lastPhoto = item->getPhoto();
00581 lastPhoto->setNext(NULL);
00582 }
00583 }
00584
00585 int Subalbum::getSubalbumNumber()
00586 {
00587 return number;
00588 }
00589
00590 int Subalbum::getNumPhotos()
00591 {
00592 return numPhotos;;
00593 }
00594
00595 int Subalbum::getNumLoadedPhotos()
00596 {
00597 return loadedPhotos;;
00598 }
00599
00600 void Subalbum::resetNumLoadedPhotos()
00601 {
00602 loadedPhotos = numPhotos;
00603 }
00604
00605 void Subalbum::setModified()
00606 {
00607 albm->setModified();
00608 }
00609