00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <QDir>
00021 #include <QApplication>
00022
00023
00024 #include <mythcontext.h>
00025 #include <mythdbcon.h>
00026 #include <mythmiscutil.h>
00027 #include <mythdirs.h>
00028 #include <mythdb.h>
00029 #include <mythuihelper.h>
00030 #include <mythmainwindow.h>
00031
00032
00033 #include "config.h"
00034 #include "galleryutil.h"
00035 #include "thumbgenerator.h"
00036
00037 #ifdef DCRAW_SUPPORT
00038 #include "../dcrawplugin/dcrawformats.h"
00039 #endif // DCRAW_SUPPORT
00040
00041 #ifdef EXIF_SUPPORT
00042 #include <libexif/exif-data.h>
00043 #include <libexif/exif-entry.h>
00044 #endif // EXIF_SUPPORT
00045
00046 #define LOC QString("GalleryUtil:")
00047
00048 static QFileInfo MakeUnique(const QFileInfo &dest);
00049 static QFileInfo MakeUniqueDirectory(const QFileInfo &dest);
00050 static bool FileCopy(const QFileInfo &src, const QFileInfo &dst);
00051 static bool FileMove(const QFileInfo &src, const QFileInfo &dst);
00052 static bool FileDelete(const QFileInfo &file);
00053
00054 QStringList GalleryUtil::GetImageFilter(void)
00055 {
00056 QStringList filt;
00057 filt.push_back("*.jpg");
00058 filt.push_back("*.jpeg");
00059 filt.push_back("*.png");
00060 filt.push_back("*.tif");
00061 filt.push_back("*.tiff");
00062 filt.push_back("*.bmp");
00063 filt.push_back("*.gif");
00064
00065 #ifdef DCRAW_SUPPORT
00066 filt << DcrawFormats::getFilters();
00067 #endif // DCRAW_SUPPORT
00068
00069 return filt;
00070 }
00071
00072 QStringList GalleryUtil::GetMovieFilter(void)
00073 {
00074 QStringList filt;
00075 filt.push_back("*.avi");
00076 filt.push_back("*.mpg");
00077 filt.push_back("*.mp4");
00078 filt.push_back("*.mpeg");
00079 filt.push_back("*.mov");
00080 filt.push_back("*.wmv");
00081 filt.push_back("*.3gp");
00082 return filt;
00083 }
00084
00085 QStringList GalleryUtil::GetMediaFilter(void)
00086 {
00087 QStringList filt = GetImageFilter();
00088 filt << GetMovieFilter();
00089 return filt;
00090 }
00091
00092 bool GalleryUtil::IsImage(const QString &filePath)
00093 {
00094 QFileInfo fi(filePath);
00095 if (fi.isDir())
00096 return false;
00097
00098 QStringList filt = GetImageFilter();
00099 QStringList::const_iterator it = filt.begin();
00100 for (; it != filt.end(); ++it)
00101 {
00102 if ((*it).contains(fi.suffix().toLower()))
00103 return true;
00104 }
00105
00106 return false;
00107 }
00108
00109 bool GalleryUtil::IsMovie(const QString &filePath)
00110 {
00111 QFileInfo fi(filePath);
00112 if (fi.isDir())
00113 return false;
00114
00115 QStringList filt = GetMovieFilter();
00116 QStringList::const_iterator it = filt.begin();
00117 for (; it != filt.end(); ++it)
00118 {
00119 if ((*it).contains(fi.suffix().toLower()))
00120 return true;
00121 }
00122
00123 return false;
00124 }
00125
00126 long GalleryUtil::GetNaturalRotation(const unsigned char *buffer, int size)
00127 {
00128 long rotateAngle = 0;
00129
00130 #ifdef EXIF_SUPPORT
00131 try
00132 {
00133 ExifData *data = exif_data_new_from_data(buffer, size);
00134 if (data)
00135 {
00136 rotateAngle = GetNaturalRotation(data);
00137 exif_data_free(data);
00138 }
00139 else
00140 {
00141 LOG(VB_FILE, LOG_ERR, LOC + "Could not load exif data from buffer");
00142 }
00143 }
00144 catch (...)
00145 {
00146 LOG(VB_GENERAL, LOG_ERR, LOC +
00147 "Failed to extract EXIF headers from buffer");
00148 }
00149 #else
00150
00151 (void)buffer;
00152 (void)size;
00153 #endif
00154
00155 return rotateAngle;
00156 }
00157
00158 long GalleryUtil::GetNaturalRotation(const QString &filePathString)
00159 {
00160 long rotateAngle = 0;
00161
00162 #ifdef EXIF_SUPPORT
00163 QByteArray filePathBA = filePathString.toLocal8Bit();
00164 const char *filePath = filePathBA.constData();
00165
00166 try
00167 {
00168 ExifData *data = exif_data_new_from_file(filePath);
00169 if (data)
00170 {
00171 rotateAngle = GetNaturalRotation(data);
00172 exif_data_free(data);
00173 }
00174 else
00175 {
00176 LOG(VB_FILE, LOG_ERR, LOC +
00177 QString("Could not load exif data from '%1'") .arg(filePath));
00178 }
00179 }
00180 catch (...)
00181 {
00182 LOG(VB_GENERAL, LOG_ERR, LOC +
00183 QString("Failed to extract EXIF headers from '%1'") .arg(filePath));
00184 }
00185 #else
00186
00187 (void)filePathString;
00188 #endif
00189
00190 return rotateAngle;
00191 }
00192
00193 long GalleryUtil::GetNaturalRotation(void *exifData)
00194 {
00195 long rotateAngle = 0;
00196
00197 #ifdef EXIF_SUPPORT
00198 ExifData *data = (ExifData *)exifData;
00199
00200 if (!data)
00201 return 0;
00202
00203 for (int i = 0; i < EXIF_IFD_COUNT; i++)
00204 {
00205 ExifEntry *entry = exif_content_get_entry(data->ifd[i],
00206 EXIF_TAG_ORIENTATION);
00207 ExifByteOrder byteorder = exif_data_get_byte_order(data);
00208
00209 if (entry)
00210 {
00211 ExifShort v_short = exif_get_short(entry->data, byteorder);
00212 LOG(VB_GENERAL, LOG_DEBUG,
00213 QString("Exif entry=%1").arg(v_short));
00214
00215
00216 switch (v_short)
00217 {
00218 case 3:
00219 rotateAngle = 180;
00220 break;
00221 case 6:
00222 rotateAngle = 90;
00223 break;
00224 case 8:
00225 rotateAngle = -90;
00226 break;
00227 default:
00228 rotateAngle = 0;
00229 break;
00230 }
00231 break;
00232 }
00233 }
00234 #else
00235
00236 (void)exifData;
00237 #endif // EXIF_SUPPORT
00238
00239 return rotateAngle;
00240 }
00241
00242 bool GalleryUtil::LoadDirectory(ThumbList& itemList, const QString& dir,
00243 const GalleryFilter& flt, bool recurse,
00244 ThumbHash *itemHash, ThumbGenerator* thumbGen)
00245 {
00246 QString blah = dir;
00247 QDir d(blah);
00248 QString currDir = d.absolutePath();
00249 QStringList splitFD;
00250
00251 bool isGallery;
00252 QFileInfoList gList = d.entryInfoList(QStringList("serial*.dat"),
00253 QDir::Files);
00254 isGallery = (gList.count() != 0);
00255
00256
00257 if (thumbGen)
00258 thumbGen->getThumbcacheDir(currDir);
00259
00260 QFileInfoList list = d.entryInfoList(GetMediaFilter(),
00261 QDir::Files | QDir::AllDirs,
00262 (QDir::SortFlag)flt.getSort());
00263
00264 if (list.isEmpty())
00265 return false;
00266
00267 QFileInfoList::const_iterator it = list.begin();
00268 const QFileInfo *fi;
00269
00270 if (thumbGen)
00271 {
00272 thumbGen->cancel();
00273 thumbGen->setDirectory(currDir, isGallery);
00274 }
00275
00276 if (!flt.getDirFilter().isEmpty())
00277 {
00278 splitFD = flt.getDirFilter().split(":");
00279 }
00280
00281 while (it != list.end())
00282 {
00283 fi = &(*it);
00284 ++it;
00285 if (fi->fileName() == "." || fi->fileName() == "..")
00286 continue;
00287
00288
00289 if (isGallery && (
00290 (fi->fileName().indexOf(".thumb.") > 0) ||
00291 (fi->fileName().indexOf(".sized.") > 0) ||
00292 (fi->fileName().indexOf(".highlight.") > 0)))
00293 continue;
00294
00295
00296 if (fi->isDir() &&
00297 !splitFD.filter(fi->fileName(), Qt::CaseInsensitive).isEmpty())
00298 continue;
00299
00300 if (fi->isDir() && recurse)
00301 {
00302 LoadDirectory(itemList, QDir::cleanPath(fi->absoluteFilePath()),
00303 flt, true, itemHash, thumbGen);
00304 }
00305 else
00306 {
00307 if ((GalleryUtil::IsImage(fi->absoluteFilePath()) &&
00308 flt.getTypeFilter() == kTypeFilterMoviesOnly) ||
00309 (GalleryUtil::IsMovie(fi->absoluteFilePath()) &&
00310 flt.getTypeFilter() == kTypeFilterImagesOnly))
00311 continue;
00312
00313 ThumbItem *item = new ThumbItem(fi->fileName(),
00314 QDir::cleanPath(fi->absoluteFilePath()), fi->isDir());
00315
00316 itemList.append(item);
00317
00318 if (itemHash)
00319 itemHash->insert(item->GetName(), item);
00320
00321 if (thumbGen)
00322 thumbGen->addFile(item->GetName());
00323 }
00324 }
00325
00326 return isGallery;
00327 }
00328
00329 QString GalleryUtil::GetCaption(const QString &filePath)
00330 {
00331 QString caption("");
00332
00333 try
00334 {
00335 #ifdef EXIF_SUPPORT
00336 #if NEW_LIB_EXIF
00337 char *exifvalue = new char[1024];
00338 #endif
00339 ExifData *data = exif_data_new_from_file(
00340 filePath.toLocal8Bit().constData());
00341 if (data)
00342 {
00343 for (int i = 0; i < EXIF_IFD_COUNT; i++)
00344 {
00345 ExifEntry *entry = exif_content_get_entry (data->ifd[i],
00346 EXIF_TAG_USER_COMMENT);
00347 if (entry)
00348 {
00349 #if NEW_LIB_EXIF
00350 exif_entry_get_value(entry, exifvalue, 1023);
00351 caption = exifvalue;
00352 #else
00353 caption = exif_entry_get_value(entry);
00354 #endif
00355
00356 if(!caption.trimmed().isEmpty())
00357 break;
00358 }
00359
00360 entry = exif_content_get_entry (data->ifd[i],
00361 EXIF_TAG_IMAGE_DESCRIPTION);
00362 if (entry)
00363 {
00364 #if NEW_LIB_EXIF
00365 exif_entry_get_value(entry, exifvalue, 1023);
00366 caption = exifvalue;
00367 #else
00368 caption = exif_entry_get_value(entry);
00369 #endif
00370
00371 if(!caption.trimmed().isEmpty())
00372 break;
00373 }
00374 }
00375 exif_data_free(data);
00376 }
00377 else
00378 {
00379 LOG(VB_FILE, LOG_ERR, LOC +
00380 QString("Could not load exif data from '%1'") .arg(filePath));
00381 }
00382 #if NEW_LIB_EXIF
00383 delete [] exifvalue;
00384 #endif
00385 #endif // EXIF_SUPPORT
00386 }
00387 catch (...)
00388 {
00389 LOG(VB_GENERAL, LOG_ERR, LOC +
00390 QString("Failed to extract EXIF headers from '%1'") .arg(filePath));
00391 }
00392
00393 return caption;
00394 }
00395
00396 bool GalleryUtil::Copy(const QFileInfo &src, QFileInfo &dst)
00397 {
00398 if (src.isDir())
00399 return CopyDirectory(src, dst);
00400
00401 dst = MakeUnique(dst);
00402
00403 if (!FileCopy(src, dst))
00404 return false;
00405
00406 MSqlQuery query(MSqlQuery::InitCon());
00407 query.prepare("INSERT INTO gallerymetadata (image, angle) "
00408 "SELECT :IMAGENEW , angle "
00409 "FROM gallerymetadata "
00410 "WHERE image = :IMAGEOLD");
00411 query.bindValue(":IMAGENEW", dst.absoluteFilePath());
00412 query.bindValue(":IMAGEOLD", src.absoluteFilePath());
00413 if (query.exec())
00414 return true;
00415
00416
00417 FileDelete(dst);
00418 return false;
00419 }
00420
00421 bool GalleryUtil::Move(const QFileInfo &src, QFileInfo &dst)
00422 {
00423 if (src.isDir())
00424 return MoveDirectory(src, dst);
00425
00426 dst = MakeUnique(dst);
00427
00428 if (!FileMove(src, dst))
00429 return false;
00430
00431 MSqlQuery query(MSqlQuery::InitCon());
00432 query.prepare("UPDATE gallerymetadata "
00433 "SET image = :IMAGENEW "
00434 "WHERE image = :IMAGEOLD");
00435 query.bindValue(":IMAGENEW", dst.absoluteFilePath());
00436 query.bindValue(":IMAGEOLD", src.absoluteFilePath());
00437 if (query.exec())
00438 return true;
00439
00440
00441 FileMove(dst, src);
00442 return false;
00443 }
00444
00445 bool GalleryUtil::Delete(const QFileInfo &file)
00446 {
00447 if (!file.exists())
00448 return false;
00449
00450 if (file.isDir())
00451 return DeleteDirectory(file);
00452
00453 MSqlQuery query(MSqlQuery::InitCon());
00454 query.prepare("DELETE FROM gallerymetadata "
00455 "WHERE image = :IMAGE ;");
00456 query.bindValue(":IMAGE", file.absoluteFilePath());
00457 if (query.exec())
00458 return FileDelete(file);
00459
00460 return false;
00461 }
00462
00463 bool GalleryUtil::Rename(const QString &currDir, const QString &oldName,
00464 const QString &newName)
00465 {
00466
00467 QFileInfo fi(currDir + '/' + newName);
00468 if (fi.exists())
00469 return false;
00470
00471 fi.setFile(currDir + '/' + oldName);
00472 if (fi.isDir())
00473 return RenameDirectory(currDir, oldName, newName);
00474
00475
00476 QDir cdir(currDir);
00477 if (!cdir.rename(oldName, newName))
00478 return false;
00479
00480
00481 if (QFile::exists(currDir + "/.thumbcache/" + oldName))
00482 {
00483 QDir d(currDir + "/.thumbcache/");
00484 d.rename(oldName, newName);
00485 }
00486
00487 int prefixLen = gCoreContext->GetSetting("GalleryDir").length();
00488 QString path = GetConfDir() + "/MythGallery";
00489 path += currDir.right(currDir.length() - prefixLen);
00490 path += QString("/.thumbcache/");
00491 if (QFile::exists(path + oldName))
00492 {
00493 QDir d(path);
00494 d.rename(oldName, newName);
00495 }
00496
00497
00498 MSqlQuery query(MSqlQuery::InitCon());
00499 query.prepare("UPDATE gallerymetadata "
00500 "SET image = :IMAGENEW "
00501 "WHERE image = :IMAGEOLD");
00502 query.bindValue(":IMAGENEW", QString(currDir + '/' + newName));
00503 query.bindValue(":IMAGEOLD", QString(currDir + '/' + oldName));
00504 if (query.exec())
00505 return true;
00506
00507
00508 cdir.rename(newName, oldName);
00509 return false;
00510 }
00511
00512 QSize GalleryUtil::ScaleToDest(const QSize &src, const QSize &dest, ScaleMax scaleMax)
00513 {
00514 QSize sz = src;
00515
00516
00517 double pixelAspect = GetMythUI()->GetPixelAspectRatio();
00518
00519
00520 double imageAspect = 1.0;
00521 if ((sz.width() > 0) && (sz.height() > 0))
00522 imageAspect = (double)sz.width() / (double)sz.height();
00523
00524 int scaleWidth = sz.width();
00525 int scaleHeight = sz.height();
00526
00527 switch (scaleMax)
00528 {
00529 case kScaleToFill:
00530
00531 scaleWidth = dest.width();
00532 scaleHeight = (int)((float)dest.width() * pixelAspect / imageAspect);
00533 if (scaleHeight < dest.height())
00534 {
00535
00536 scaleWidth = (int)((float)dest.height() * imageAspect / pixelAspect);
00537 scaleHeight = dest.height();
00538 }
00539 break;
00540
00541 case kReduceToFit:
00542
00543 if (scaleWidth <= dest.width() && scaleHeight <= dest.height())
00544 break;
00545
00546
00547 case kScaleToFit:
00548
00549 scaleWidth = (int)((float)dest.height() * imageAspect / pixelAspect);
00550 scaleHeight = dest.height();
00551 if (scaleWidth > dest.width())
00552 {
00553
00554 scaleWidth = dest.width();
00555 scaleHeight = (int)((float)dest.width() * pixelAspect / imageAspect);
00556 }
00557 break;
00558
00559 default:
00560 break;
00561 }
00562
00563 if (scaleWidth != sz.width() || scaleHeight != sz.height())
00564 sz.scale(scaleWidth, scaleHeight, Qt::KeepAspectRatio);
00565 return sz;
00566 }
00567
00568 bool GalleryUtil::CopyDirectory(const QFileInfo src, QFileInfo &dst)
00569 {
00570 QDir srcDir(src.absoluteFilePath());
00571
00572 dst = MakeUniqueDirectory(dst);
00573 if (!dst.exists())
00574 {
00575 srcDir.mkdir(dst.absoluteFilePath());
00576 dst.refresh();
00577 }
00578
00579 if (!dst.exists() || !dst.isDir())
00580 return false;
00581
00582 bool ok = true;
00583 QDir dstDir(dst.absoluteFilePath());
00584 QFileInfoList list = srcDir.entryInfoList();
00585 QFileInfoList::const_iterator it = list.begin();
00586 for (; it != list.end(); ++it)
00587 {
00588 const QString fn = it->fileName();
00589 if (fn != "." && fn != "..")
00590 {
00591 QFileInfo dfi(dstDir, fn);
00592 ok &= Copy(*it, dfi);
00593 }
00594 }
00595
00596 return ok;
00597 }
00598
00599 bool GalleryUtil::MoveDirectory(const QFileInfo src, QFileInfo &dst)
00600 {
00601 QDir srcDir(src.absoluteFilePath());
00602
00603 dst = MakeUniqueDirectory(dst);
00604 if (!dst.exists())
00605 {
00606 srcDir.mkdir(dst.absoluteFilePath());
00607 dst.refresh();
00608 }
00609
00610 if (!dst.exists() || !dst.isDir())
00611 return false;
00612
00613 bool ok = true;
00614 QDir dstDir(dst.absoluteFilePath());
00615 QFileInfoList list = srcDir.entryInfoList();
00616 QFileInfoList::const_iterator it = list.begin();
00617 for (; it != list.end(); ++it)
00618 {
00619 const QString fn = it->fileName();
00620 if (fn != "." && fn != "..")
00621 {
00622 QFileInfo dfi(dstDir, fn);
00623 ok &= Move(*it, dfi);
00624 }
00625 }
00626
00627 return ok && FileDelete(src);
00628 }
00629
00630 bool GalleryUtil::DeleteDirectory(const QFileInfo &dir)
00631 {
00632 if (!dir.exists())
00633 return false;
00634
00635 QDir srcDir(dir.absoluteFilePath());
00636 QFileInfoList list = srcDir.entryInfoList();
00637 QFileInfoList::const_iterator it = list.begin();
00638 for (; it != list.end(); ++it)
00639 {
00640 const QString fn = it->fileName();
00641 if (fn != "." && fn != "..")
00642 Delete(*it);
00643 }
00644
00645 return FileDelete(dir);
00646 }
00647
00648 bool GalleryUtil::RenameDirectory(const QString &currDir, const QString &oldName,
00649 const QString &newName)
00650 {
00651
00652 QDir cdir(currDir);
00653 if (!cdir.rename(oldName, newName))
00654 return false;
00655
00656
00657 if (QFile::exists(currDir + "/.thumbcache/" + oldName))
00658 {
00659 QDir d(currDir + "/.thumbcache/");
00660 d.rename(oldName, newName);
00661 }
00662
00663
00664 int prefixLen = gCoreContext->GetSetting("GalleryDir").length();
00665 QString path = GetConfDir() + "/MythGallery";
00666 path += currDir.right(currDir.length() - prefixLen) + '/';
00667 if (QFile::exists(path + oldName))
00668 {
00669 QDir d(path);
00670 d.rename(oldName, newName);
00671
00672
00673 path += QString(".thumbcache/");
00674 if (QFile::exists(path + oldName))
00675 {
00676 QDir d(path);
00677 d.rename(oldName, newName);
00678 }
00679 }
00680
00681
00682 MSqlQuery query(MSqlQuery::InitCon());
00683 query.prepare("SELECT image, angle FROM gallerymetadata "
00684 "WHERE image LIKE :IMAGEOLD");
00685 query.bindValue(":IMAGEOLD", QString(currDir + '/' + oldName + '%'));
00686 if (query.exec())
00687 {
00688 while (query.next())
00689 {
00690 QString oldImage = query.value(0).toString();
00691 QString newImage = oldImage;
00692 newImage = newImage.replace(currDir + '/' + oldName,
00693 currDir + '/' + newName);
00694
00695 MSqlQuery subquery(MSqlQuery::InitCon());
00696 subquery.prepare("UPDATE gallerymetadata "
00697 "SET image = :IMAGENEW "
00698 "WHERE image = :IMAGEOLD");
00699 subquery.bindValue(":IMAGENEW", newImage);
00700 subquery.bindValue(":IMAGEOLD", oldImage);
00701 if (!subquery.exec())
00702 MythDB::DBError("GalleryUtil::RenameDirectory - update image",
00703 subquery);
00704 }
00705 }
00706
00707 return true;
00708 }
00709
00710
00711 void GalleryUtil::PlayVideo(const QString &filename)
00712 {
00713
00714 vector<QWidget *> widgetList;
00715 if (GetMythMainWindow()->currentWidget())
00716 {
00717 QWidget *widget = GetMythMainWindow()->currentWidget();
00718
00719 while (widget)
00720 {
00721 widgetList.push_back(widget);
00722 GetMythMainWindow()->detach(widget);
00723 widget->hide();
00724 widget = GetMythMainWindow()->currentWidget();
00725 }
00726
00727 GetMythMainWindow()->GetPaintWindow()->raise();
00728 GetMythMainWindow()->GetPaintWindow()->setFocus();
00729
00730 }
00731
00732
00733 GetMythMainWindow()->HandleMedia("Internal", filename);
00734
00735
00736
00737 vector<QWidget*>::reverse_iterator it;
00738 for (it = widgetList.rbegin(); it != widgetList.rend(); ++it)
00739 {
00740 GetMythMainWindow()->attach(*it);
00741 (*it)->show();
00742 }
00743
00744
00745 }
00746
00747 static QFileInfo MakeUnique(const QFileInfo &dest)
00748 {
00749 QFileInfo newDest = dest;
00750
00751 for (uint i = 0; newDest.exists(); i++)
00752 {
00753 QString basename = QString("%1_%2.%3")
00754 .arg(dest.baseName()).arg(i).arg(dest.completeSuffix());
00755
00756 newDest.setFile(dest.dir(), basename);
00757
00758 LOG(VB_GENERAL, LOG_ERR, LOC +
00759 QString("Need to find a new name for '%1' trying '%2'")
00760 .arg(dest.absoluteFilePath()).arg(newDest.absoluteFilePath()));
00761 }
00762
00763 return newDest;
00764 }
00765
00766 static QFileInfo MakeUniqueDirectory(const QFileInfo &dest)
00767 {
00768 QFileInfo newDest = dest;
00769
00770 for (uint i = 0; newDest.exists() && !newDest.isDir(); i++)
00771 {
00772 QString fullname = QString("%1_%2").arg(dest.absoluteFilePath()).arg(i);
00773 newDest.setFile(fullname);
00774
00775 LOG(VB_GENERAL, LOG_ERR, LOC +
00776 QString("Need to find a new name for '%1' trying '%2'")
00777 .arg(dest.absoluteFilePath()).arg(newDest.absoluteFilePath()));
00778 }
00779
00780 return newDest;
00781 }
00782
00783 static bool FileCopy(const QFileInfo &src, const QFileInfo &dst)
00784 {
00785 const int bufferSize = 16*1024;
00786
00787 QFile s(src.absoluteFilePath());
00788 QFile d(dst.absoluteFilePath());
00789 char buffer[bufferSize];
00790 int len;
00791
00792 if (!s.open(QIODevice::ReadOnly))
00793 return false;
00794
00795 if (!d.open(QIODevice::WriteOnly))
00796 {
00797 s.close();
00798 return false;
00799 }
00800
00801 len = s.read(buffer, bufferSize);
00802 do
00803 {
00804 d.write(buffer, len);
00805 len = s.read(buffer, bufferSize);
00806 } while (len > 0);
00807
00808 s.close();
00809 d.close();
00810
00811 return true;
00812 }
00813
00814 static bool FileMove(const QFileInfo &src, const QFileInfo &dst)
00815 {
00816
00817
00818 QByteArray source = src.absoluteFilePath().toLocal8Bit();
00819 QByteArray dest = dst.absoluteFilePath().toLocal8Bit();
00820 if (rename(source.constData(), dest.constData()) == 0)
00821 {
00822 return true;
00823 }
00824
00825
00826 if (errno == EXDEV)
00827 {
00828 if (FileCopy(src, dst))
00829 return FileDelete(src);
00830 }
00831
00832 return false;
00833 }
00834
00835 static bool FileDelete(const QFileInfo &file)
00836 {
00837 if (!file.isDir())
00838 return QFile::remove(file.absoluteFilePath());
00839
00840
00841 QDir srcDir(file.absoluteFilePath());
00842 QFileInfo tc(srcDir, ".thumbcache");
00843 GalleryUtil::Delete(tc);
00844
00845 srcDir.rmdir(srcDir.absolutePath());
00846
00847 return true;
00848 }
00849
00850
00851
00852