00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "albumdb.h"
00027
00028
00029
00030 extern "C"
00031 {
00032 #include <sys/time.h>
00033 }
00034
00035
00036
00037 #include <cstdio>
00038 #include <cstdlib>
00039 #include <ctime>
00040
00041
00042
00043 #include <QFile>
00044 #include <QFileInfo>
00045 #include <QDir>
00046
00047
00048
00049 #include <klocale.h>
00050 #include <kdebug.h>
00051
00052
00053
00054 #include "databasebackend.h"
00055 #include "collectionmanager.h"
00056 #include "collectionlocation.h"
00057
00058 namespace Digikam
00059 {
00060
00061 class AlbumDBPriv
00062 {
00063
00064 public:
00065
00066 AlbumDBPriv()
00067 {
00068 db = 0;
00069 }
00070
00071 DatabaseBackend *db;
00072 QList<int> recentlyAssignedTags;
00073 };
00074
00075 AlbumDB::AlbumDB(DatabaseBackend *backend)
00076 : d(new AlbumDBPriv)
00077 {
00078 d->db = backend;
00079 }
00080
00081 AlbumDB::~AlbumDB()
00082 {
00083 delete d;
00084 }
00085
00086 QList<AlbumRootInfo> AlbumDB::getAlbumRoots()
00087 {
00088 QList<AlbumRootInfo> list;
00089
00090 QList<QVariant> values;
00091 d->db->execSql( "SELECT id, label, status, type, identifier, specificPath FROM AlbumRoots;", &values );
00092
00093 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
00094 {
00095 AlbumRootInfo info;
00096 info.id = (*it).toInt();
00097 ++it;
00098 info.label = (*it).toString();
00099 ++it;
00100 info.status = (*it).toInt();
00101 ++it;
00102 info.type = (AlbumRoot::Type)(*it).toInt();
00103 ++it;
00104 info.identifier = (*it).toString();
00105 ++it;
00106 info.specificPath = (*it).toString();
00107 ++it;
00108
00109 list << info;
00110 }
00111
00112 return list;
00113 }
00114
00115 int AlbumDB::addAlbumRoot(AlbumRoot::Type type, const QString& identifier, const QString& specificPath, const QString& label)
00116 {
00117 QVariant id;
00118 d->db->execSql( QString("REPLACE INTO AlbumRoots (type, label, status, identifier, specificPath) "
00119 "VALUES(?, ?, 0, ?, ?);"),
00120 (int)type, label, identifier, specificPath, 0, &id);
00121
00122 d->db->recordChangeset(AlbumRootChangeset(id.toInt(), AlbumRootChangeset::Added));
00123 return id.toInt();
00124 }
00125
00126 void AlbumDB::deleteAlbumRoot(int rootId)
00127 {
00128 d->db->execSql( QString("DELETE FROM AlbumRoots WHERE id=?;"),
00129 rootId );
00130 d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::Deleted));
00131 }
00132
00133 void AlbumDB::migrateAlbumRoot(int rootId, const QString& identifier)
00134 {
00135 d->db->execSql( QString("UPDATE AlbumRoots SET identifier=? WHERE id=?;"),
00136 identifier, rootId);
00137 d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::PropertiesChanged));
00138 }
00139
00140 void AlbumDB::setAlbumRootLabel(int rootId, const QString& newLabel)
00141 {
00142 d->db->execSql( QString("UPDATE AlbumRoots SET label=? WHERE id=?;"),
00143 newLabel, rootId);
00144 d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::PropertiesChanged));
00145 }
00146
00147 void AlbumDB::changeAlbumRootType(int rootId, AlbumRoot::Type newType)
00148 {
00149 d->db->execSql( QString("UPDATE AlbumRoots SET type=? WHERE id=?;"),
00150 (int)newType, rootId);
00151 d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::PropertiesChanged));
00152 }
00153
00154
00155
00156 AlbumInfo::List AlbumDB::scanAlbums()
00157 {
00158 AlbumInfo::List aList;
00159
00160 QList<QVariant> values;
00161 d->db->execSql( "SELECT A.albumRoot, A.id, A.relativePath, A.date, A.caption, A.collection, B.albumRoot, B.relativePath, I.name \n "
00162 "FROM Albums AS A \n "
00163 " LEFT JOIN Images AS I ON A.icon=I.id \n"
00164 " LEFT JOIN Albums AS B ON B.id=I.album \n"
00165 " WHERE A.albumRoot != 0;",
00166 &values);
00167
00168 QString iconAlbumUrl, iconName;
00169
00170 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
00171 {
00172 AlbumInfo info;
00173
00174 info.albumRootId = (*it).toInt();
00175 ++it;
00176 info.id = (*it).toInt();
00177 ++it;
00178 info.relativePath = (*it).toString();
00179 ++it;
00180 info.date = QDate::fromString((*it).toString(), Qt::ISODate);
00181 ++it;
00182 info.caption = (*it).toString();
00183 ++it;
00184 info.category = (*it).toString();
00185 ++it;
00186 info.iconAlbumRootId = (*it).toInt();
00187 ++it;
00188 iconAlbumUrl = (*it).toString();
00189 ++it;
00190 iconName = (*it).toString();
00191 ++it;
00192
00193 if (!iconName.isEmpty())
00194 info.iconRelativePath = iconAlbumUrl + '/' + iconName;
00195
00196 aList.append(info);
00197 }
00198
00199 return aList;
00200 }
00201
00202 TagInfo::List AlbumDB::scanTags()
00203 {
00204 TagInfo::List tList;
00205
00206 QList<QVariant> values;
00207 d->db->execSql( "SELECT T.id, T.pid, T.name, A.relativePath, I.name, T.iconkde, A.albumRoot \n "
00208 "FROM Tags AS T \n"
00209 " LEFT JOIN Images AS I ON I.id=T.icon \n "
00210 " LEFT JOIN Albums AS A ON A.id=I.album; ", &values );
00211
00212 QString iconName, iconKDE, albumURL;
00213 int iconAlbumRootId;
00214
00215 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
00216 {
00217 TagInfo info;
00218
00219 info.id = (*it).toInt();
00220 ++it;
00221 info.pid = (*it).toInt();
00222 ++it;
00223 info.name = (*it).toString();
00224 ++it;
00225 albumURL = (*it).toString();
00226 ++it;
00227 iconName = (*it).toString();
00228 ++it;
00229 iconKDE = (*it).toString();
00230 ++it;
00231 iconAlbumRootId = (*it).toInt();
00232 ++it;
00233
00234 if (albumURL.isEmpty())
00235 {
00236 info.icon = iconKDE;
00237 }
00238 else
00239 {
00240 info.iconAlbumRootId = iconAlbumRootId;
00241 info.iconRelativePath = albumURL + '/' + iconName;
00242 }
00243
00244 tList.append(info);
00245 }
00246
00247 return tList;
00248 }
00249
00250 SearchInfo::List AlbumDB::scanSearches()
00251 {
00252 SearchInfo::List searchList;
00253
00254 QList<QVariant> values;
00255 d->db->execSql( "SELECT id, type, name, query FROM Searches;", &values);
00256
00257 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
00258 {
00259 SearchInfo info;
00260
00261 info.id = (*it).toInt();
00262 ++it;
00263 info.type = (DatabaseSearch::Type)(*it).toInt();
00264 ++it;
00265 info.name = (*it).toString();
00266 ++it;
00267 info.query = (*it).toString();
00268 ++it;
00269
00270 searchList.append(info);
00271 }
00272
00273 return searchList;
00274 }
00275
00276 QList<AlbumShortInfo> AlbumDB::getAlbumShortInfos()
00277 {
00278 QList<QVariant> values;
00279 d->db->execSql( QString("SELECT Albums.id, Albums.relativePath, Albums.albumRoot from Albums; "),
00280 &values);
00281
00282 QList<AlbumShortInfo> albumList;
00283
00284 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
00285 {
00286 AlbumShortInfo info;
00287
00288 info.id = (*it).toLongLong();
00289 ++it;
00290 info.relativePath = (*it).toString();
00291 ++it;
00292 info.albumRootId = (*it).toInt();
00293 ++it;
00294
00295 albumList << info;
00296 }
00297
00298 return albumList;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 int AlbumDB::addAlbum(int albumRootId, const QString& relativePath,
00355 const QString& caption,
00356 const QDate& date, const QString& collection)
00357 {
00358 QVariant id;
00359 QList<QVariant> boundValues;
00360 boundValues << albumRootId << relativePath << date.toString(Qt::ISODate) << caption << collection;
00361
00362 d->db->execSql( QString("REPLACE INTO Albums (albumRoot, relativePath, date, caption, collection) "
00363 "VALUES(?, ?, ?, ?, ?);"),
00364 boundValues, 0, &id);
00365
00366 d->db->recordChangeset(AlbumChangeset(id.toInt(), AlbumChangeset::Added));
00367 return id.toInt();
00368 }
00369
00370 void AlbumDB::setAlbumCaption(int albumID, const QString& caption)
00371 {
00372 d->db->execSql( QString("UPDATE Albums SET caption=? WHERE id=?;"),
00373 caption, albumID );
00374 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00375 }
00376
00377 void AlbumDB::setAlbumCategory(int albumID, const QString& category)
00378 {
00379
00380 d->db->execSql( QString("UPDATE Albums SET collection=? WHERE id=?;"),
00381 category, albumID );
00382 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00383 }
00384
00385 void AlbumDB::setAlbumDate(int albumID, const QDate& date)
00386 {
00387 d->db->execSql( QString("UPDATE Albums SET date=? WHERE id=?;"),
00388 date.toString(Qt::ISODate),
00389 albumID );
00390 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00391 }
00392
00393 void AlbumDB::setAlbumIcon(int albumID, qlonglong iconID)
00394 {
00395 d->db->execSql( QString("UPDATE Albums SET icon=? WHERE id=?;"),
00396 iconID,
00397 albumID );
00398 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00399 }
00400
00401 bool AlbumDB::getAlbumIcon(int albumID, int *albumRootId, QString *iconRelativePath)
00402 {
00403 QList<QVariant> values;
00404 d->db->execSql( QString("SELECT B.relativePath, I.name, B.albumRoot \n "
00405 "FROM Albums AS A \n "
00406 " LEFT JOIN Images AS I ON I.id=A.icon \n "
00407 " LEFT JOIN Albums AS B ON B.id=I.album \n "
00408 "WHERE A.id=?;"),
00409 albumID, &values );
00410 if (values.isEmpty())
00411 return false;
00412
00413 QList<QVariant>::const_iterator it = values.constBegin();
00414 QString album = (*it).toString();
00415 ++it;
00416 QString iconName = (*it).toString();
00417 ++it;
00418 *albumRootId = (*it).toInt();
00419
00420 *iconRelativePath = album + '/' + iconName;
00421
00422 return !iconName.isEmpty();
00423 }
00424
00425 void AlbumDB::deleteAlbum(int albumID)
00426 {
00427 d->db->execSql( QString("DELETE FROM Albums WHERE id=?;"),
00428 albumID );
00429 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::Deleted));
00430 }
00431
00432 void AlbumDB::makeStaleAlbum(int albumID)
00433 {
00434
00435
00436 QList<QVariant> values;
00437
00438
00439 d->db->execSql( QString("SELECT Albums.albumRoot, Albums.relativePath from Albums WHERE id=?;"),
00440 albumID, &values);
00441
00442 if (values.isEmpty())
00443 return;
00444
00445
00446 QString newRelativePath = values[0].toString() + '-' + values[1].toString();
00447
00448
00449 d->db->execSql( QString("DELETE FROM Albums WHERE albumRoot=0 AND relativePath=?;"),
00450 newRelativePath );
00451
00452
00453 d->db->execSql( QString("UPDATE Albums SET albumRoot=0, relativePath=? WHERE id=?;"),
00454 newRelativePath, albumID );
00455
00456
00457 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::Deleted));
00458 }
00459
00460 void AlbumDB::deleteStaleAlbums()
00461 {
00462 d->db->execSql( QString("DELETE FROM Albums WHERE albumRoot=0;") );
00463
00464 }
00465
00466 int AlbumDB::addTag(int parentTagID, const QString& name, const QString& iconKDE,
00467 qlonglong iconID)
00468 {
00469 QVariant id;
00470 if (!d->db->execSql( QString("INSERT INTO Tags (pid, name) "
00471 "VALUES( ?, ?);"),
00472 parentTagID,
00473 name,
00474 0, &id) )
00475 {
00476 return -1;
00477 }
00478
00479 if (!iconKDE.isEmpty())
00480 {
00481 d->db->execSql( QString("UPDATE Tags SET iconkde=? WHERE id=?;"),
00482 iconKDE,
00483 id.toInt() );
00484 }
00485 else
00486 {
00487 d->db->execSql( QString("UPDATE Tags SET icon=? WHERE id=?;"),
00488 iconID,
00489 id.toInt());
00490 }
00491
00492 d->db->recordChangeset(TagChangeset(id.toInt(), TagChangeset::Added));
00493 return id.toInt();
00494 }
00495
00496 void AlbumDB::deleteTag(int tagID)
00497 {
00498 d->db->execSql( QString("DELETE FROM Tags WHERE id=?;"),
00499 tagID );
00500 d->db->recordChangeset(TagChangeset(tagID, TagChangeset::Deleted));
00501 }
00502
00503 void AlbumDB::setTagIcon(int tagID, const QString& iconKDE, qlonglong iconID)
00504 {
00505 int _iconID = iconKDE.isEmpty() ? iconID : 0;
00506 QString _iconKDE = iconKDE;
00507
00508 if (iconKDE.isEmpty() || iconKDE.toLower() == QString("tag"))
00509 _iconKDE.clear();
00510
00511 d->db->execSql( QString("UPDATE Tags SET iconkde=?, icon=? WHERE id=?;"),
00512 _iconKDE, _iconID, tagID );
00513
00514 d->db->recordChangeset(TagChangeset(tagID, TagChangeset::IconChanged));
00515 }
00516
00517 bool AlbumDB::getTagIcon(int tagID, int *iconAlbumRootId, QString *iconAlbumRelativePath, QString *icon)
00518 {
00519 QList<QVariant> values;
00520 d->db->execSql( QString("SELECT A.relativePath, I.name, T.iconkde, A.albumRoot \n "
00521 "FROM Tags AS T \n "
00522 " LEFT JOIN Images AS I ON I.id=T.icon \n "
00523 " LEFT JOIN Albums AS A ON A.id=I.album \n "
00524 "WHERE T.id=?;"),
00525 tagID, &values );
00526
00527 if (values.isEmpty())
00528 return false;
00529
00530 QString iconName, iconKDE, albumURL;
00531
00532 QList<QVariant>::const_iterator it = values.constBegin();
00533
00534 albumURL = (*it).toString();
00535 ++it;
00536 iconName = (*it).toString();
00537 ++it;
00538 iconKDE = (*it).toString();
00539 ++it;
00540
00541 *iconAlbumRootId = (*it).toInt();
00542 ++it;
00543
00544 if (albumURL.isEmpty())
00545 {
00546 *iconAlbumRelativePath = QString();
00547 *icon = iconKDE;
00548 return !iconKDE.isEmpty();
00549 }
00550 else
00551 {
00552 *iconAlbumRelativePath = albumURL + '/' + iconName;
00553 *icon = QString();
00554 return true;
00555 }
00556 }
00557
00558 void AlbumDB::setTagParentID(int tagID, int newParentTagID)
00559 {
00560 d->db->execSql( QString("UPDATE Tags SET pid=? WHERE id=?;"),
00561 newParentTagID, tagID );
00562 d->db->recordChangeset(TagChangeset(tagID, TagChangeset::Reparented));
00563 }
00564
00565 int AlbumDB::addSearch(DatabaseSearch::Type type, const QString& name, const QString& query)
00566 {
00567 QVariant id;
00568 if (!d->db->execSql(QString("INSERT INTO Searches (type, name, query) VALUES(?, ?, ?);"),
00569 type, name, query, 0, &id) )
00570 {
00571 return -1;
00572 }
00573
00574 d->db->recordChangeset(SearchChangeset(id.toInt(), SearchChangeset::Added));
00575 return id.toInt();
00576 }
00577
00578 void AlbumDB::updateSearch(int searchID, DatabaseSearch::Type type,
00579 const QString& name, const QString &query)
00580 {
00581 d->db->execSql(QString("UPDATE Searches SET type=?, name=?, query=? WHERE id=?"),
00582 type, name, query, searchID);
00583 d->db->recordChangeset(SearchChangeset(searchID, SearchChangeset::Changed));
00584 }
00585
00586 void AlbumDB::deleteSearch(int searchID)
00587 {
00588 d->db->execSql( QString("DELETE FROM Searches WHERE id=?"),
00589 searchID );
00590 d->db->recordChangeset(SearchChangeset(searchID, SearchChangeset::Deleted));
00591 }
00592
00593 void AlbumDB::deleteSearches(DatabaseSearch::Type type)
00594 {
00595 d->db->execSql( QString("DELETE FROM Searches WHERE type=?"),
00596 type );
00597 d->db->recordChangeset(SearchChangeset(0, SearchChangeset::Deleted));
00598 }
00599
00600 QString AlbumDB::getSearchQuery(int searchId)
00601 {
00602 QList<QVariant> values;
00603 d->db->execSql( QString("SELECT query FROM Searches WHERE id=?;"),
00604 searchId, &values );
00605
00606 if (values.isEmpty())
00607 return QString();
00608 else
00609 return values.first().toString();
00610 }
00611
00612 SearchInfo AlbumDB::getSearchInfo(int searchId)
00613 {
00614 SearchInfo info;
00615
00616 QList<QVariant> values;
00617 d->db->execSql( "SELECT id, type, name, query FROM Searches WHERE id=?;",
00618 searchId, &values);
00619
00620 if (values.size() == 4)
00621 {
00622 QList<QVariant>::const_iterator it = values.constBegin();
00623 info.id = (*it).toInt();
00624 ++it;
00625 info.type = (DatabaseSearch::Type)(*it).toInt();
00626 ++it;
00627 info.name = (*it).toString();
00628 ++it;
00629 info.query = (*it).toString();
00630 ++it;
00631 }
00632
00633 return info;
00634 }
00635
00636 void AlbumDB::setSetting(const QString& keyword,
00637 const QString& value )
00638 {
00639 d->db->execSql( QString("REPLACE into Settings VALUES (?,?);"),
00640 keyword, value );
00641 }
00642
00643 QString AlbumDB::getSetting(const QString& keyword)
00644 {
00645 QList<QVariant> values;
00646 d->db->execSql( QString("SELECT value FROM Settings "
00647 "WHERE keyword=?;"),
00648 keyword, &values );
00649
00650 if (values.isEmpty())
00651 return QString();
00652 else
00653 return values.first().toString();
00654 }
00655
00656
00657 static QStringList joinMainAndUserFilterString(const QString &filter, const QString &userFilter)
00658 {
00659 QSet<QString> filterSet;
00660 QStringList userFilterList;
00661
00662 filterSet = filter.split(';', QString::SkipEmptyParts).toSet();
00663 userFilterList = userFilter.split(';', QString::SkipEmptyParts);
00664 foreach (const QString& userFormat, userFilterList)
00665 {
00666 if (userFormat.startsWith('-'))
00667 filterSet.remove(userFormat.mid(1));
00668 else
00669 filterSet << userFormat;
00670 }
00671 return filterSet.toList();
00672 }
00673
00674 void AlbumDB::getFilterSettings(QStringList *imageFilter, QStringList *videoFilter, QStringList *audioFilter)
00675 {
00676 QString imageFormats, videoFormats, audioFormats, userImageFormats, userVideoFormats, userAudioFormats;
00677
00678 if (imageFilter)
00679 {
00680 imageFormats = getSetting("databaseImageFormats");
00681 userImageFormats = getSetting("databaseUserImageFormats");
00682 *imageFilter = joinMainAndUserFilterString(imageFormats, userImageFormats);
00683 }
00684
00685 if (videoFilter)
00686 {
00687 videoFormats = getSetting("databaseVideoFormats");
00688 userVideoFormats = getSetting("databaseUserVideoFormats");
00689 *videoFilter = joinMainAndUserFilterString(videoFormats, userVideoFormats);
00690 }
00691
00692 if (audioFilter)
00693 {
00694 audioFormats = getSetting("databaseAudioFormats");
00695 userAudioFormats = getSetting("databaseUserAudioFormats");
00696 *audioFilter = joinMainAndUserFilterString(audioFormats, userAudioFormats);
00697 }
00698 }
00699
00700 void AlbumDB::getUserFilterSettings(QString *imageFilterString, QString *videoFilterString, QString *audioFilterString)
00701 {
00702 if (imageFilterString)
00703 *imageFilterString = getSetting("databaseUserImageFormats");
00704 if (videoFilterString)
00705 *videoFilterString = getSetting("databaseUserVideoFormats");
00706 if (audioFilterString)
00707 *audioFilterString = getSetting("databaseUserAudioFormats");
00708 }
00709
00710 void AlbumDB::setFilterSettings(const QStringList& imageFilter, const QStringList& videoFilter, const QStringList& audioFilter)
00711 {
00712 setSetting("databaseImageFormats", imageFilter.join(";"));
00713 setSetting("databaseVideoFormats", videoFilter.join(";"));
00714 setSetting("databaseAudioFormats", audioFilter.join(";"));
00715 }
00716
00717
00718 static QStringList cleanUserFilterString(const QString &filterString)
00719 {
00720
00721 QStringList filterList;
00722
00723 QString wildcard("*.");
00724 QString minusWildcard("-*.");
00725 QChar dot('.');
00726 QString minusDot("-.");
00727 QChar sep( ';' );
00728 int i = filterString.indexOf( sep );
00729 if ( i == -1 && filterString.indexOf( ' ') != -1 )
00730 sep = QChar( ' ' );
00731
00732 QStringList sepList = filterString.split(sep, QString::SkipEmptyParts);
00733 foreach (const QString& f, sepList)
00734 {
00735 if (f.startsWith(wildcard))
00736 filterList << f.mid(2).trimmed().toLower();
00737 else if (f.startsWith(minusWildcard))
00738 filterList << '-' + f.mid(3).trimmed().toLower();
00739 else if (f.startsWith(dot))
00740 filterList << f.mid(1).trimmed().toLower();
00741 else if (f.startsWith(minusDot))
00742 filterList << '-' + f.mid(2).trimmed().toLower();
00743 else
00744 filterList << f.trimmed().toLower();
00745 }
00746 return filterList;
00747 }
00748
00749 void AlbumDB::setUserFilterSettings(const QString& imageFilterString, const QString& videoFilterString, const QString& audioFilterString)
00750 {
00751 setUserFilterSettings(cleanUserFilterString(imageFilterString),
00752 cleanUserFilterString(videoFilterString),
00753 cleanUserFilterString(audioFilterString));
00754 }
00755
00756 void AlbumDB::setUserFilterSettings(const QStringList& imageFilter, const QStringList& videoFilter, const QStringList& audioFilter)
00757 {
00758 setSetting("databaseUserImageFormats", imageFilter.join(";"));
00759 setSetting("databaseUserVideoFormats", videoFilter.join(";"));
00760 setSetting("databaseUserAudioFormats", audioFilter.join(";"));
00761 }
00762
00763 void AlbumDB::addToUserImageFilterSettings(const QString& filterString)
00764 {
00765 QStringList addList = cleanUserFilterString(filterString);
00766
00767 QStringList currentList = getSetting("databaseUserImageFormats").split(';', QString::SkipEmptyParts);
00768
00769
00770 foreach(const QString& addedFilter, addList)
00771 {
00772 if (!currentList.contains(addedFilter))
00773 currentList << addedFilter;
00774 }
00775
00776 setSetting("databaseUserImageFormats", currentList.join(";"));
00777 }
00778
00779 QUuid AlbumDB::databaseUuid()
00780 {
00781 QString uuidString = getSetting("databaseUUID");
00782 QUuid uuid = QUuid(uuidString);
00783 if (uuidString.isNull() || uuid.isNull())
00784 {
00785 uuid = QUuid::createUuid();
00786 setSetting("databaseUUID", uuid.toString());
00787 }
00788 return uuid;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 qlonglong AlbumDB::getImageId(int albumID, const QString& name)
00856 {
00857 QList<QVariant> values;
00858
00859 d->db->execSql( QString("SELECT id FROM Images "
00860 "WHERE album=? AND name=?;"),
00861 albumID,
00862 name,
00863 &values );
00864
00865 if (values.isEmpty())
00866 return -1;
00867 else
00868 return values.first().toLongLong();
00869 }
00870
00871 QStringList AlbumDB::getItemTagNames(qlonglong imageID)
00872 {
00873 QList<QVariant> values;
00874
00875 d->db->execSql( QString("SELECT name FROM Tags \n "
00876 "WHERE id IN (SELECT tagid FROM ImageTags \n "
00877 " WHERE imageid=?) \n "
00878 "ORDER BY name;"),
00879 imageID,
00880 &values );
00881
00882 QStringList names;
00883 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
00884 names << it->toString();
00885 return names;
00886 }
00887
00888 QList<int> AlbumDB::getItemTagIDs(qlonglong imageID)
00889 {
00890 QList<QVariant> values;
00891
00892 d->db->execSql( QString("SELECT tagid FROM ImageTags \n "
00893 "WHERE imageID=?;"),
00894 imageID,
00895 &values );
00896
00897 QList<int> ids;
00898
00899 if (values.isEmpty())
00900 return ids;
00901
00902 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
00903 ids << it->toInt();
00904 return ids;
00905 }
00906
00907 ItemShortInfo AlbumDB::getItemShortInfo(qlonglong imageID)
00908 {
00909 QList<QVariant> values;
00910
00911 d->db->execSql( QString("SELECT Images.name, Albums.albumRoot, Albums.relativePath, Albums.id "
00912 "FROM Images "
00913 " LEFT JOIN Albums ON Albums.id=Images.album "
00914 "WHERE Images.id=?;"),
00915 imageID,
00916 &values );
00917
00918 ItemShortInfo info;
00919
00920 if (!values.isEmpty())
00921 {
00922 info.id = imageID;
00923 info.itemName = values[0].toString();
00924 info.albumRootID = values[1].toInt();
00925 info.album = values[2].toString();
00926 info.albumID = values[3].toInt();
00927 }
00928
00929 return info;
00930 }
00931
00932 ItemShortInfo AlbumDB::getItemShortInfo(int albumRootId, const QString& relativePath, const QString& name)
00933 {
00934 QList<QVariant> values;
00935
00936 d->db->execSql( QString("SELECT Images.id, Albums.id "
00937 " FROM Images INNER JOIN Albums "
00938 " ON Images.album=Albums.id "
00939 " WHERE name=? AND albumRoot=? AND relativePath=?;"),
00940 name, albumRootId, relativePath,
00941 &values );
00942
00943 ItemShortInfo info;
00944
00945 if (!values.isEmpty())
00946 {
00947 info.id = values[0].toLongLong();
00948 info.itemName = name;
00949 info.albumRootID = albumRootId;
00950 info.album = relativePath;
00951 info.albumID = values[1].toInt();
00952 }
00953
00954 return info;
00955 }
00956
00957 bool AlbumDB::hasTags(const QList<qlonglong>& imageIDList)
00958 {
00959 QList<int> ids;
00960
00961 if (imageIDList.isEmpty())
00962 return false;
00963
00964 QList<QVariant> values;
00965 QList<QVariant> boundValues;
00966
00967 QString sql = QString("SELECT count(tagid) FROM ImageTags "
00968 "WHERE imageid=? ");
00969 boundValues << imageIDList.first();
00970
00971 QList<qlonglong>::const_iterator it = imageIDList.constBegin();
00972 ++it;
00973 for (; it != imageIDList.constEnd(); ++it)
00974 {
00975 sql += QString(" OR imageid=? ");
00976 boundValues << (*it);
00977 }
00978
00979 sql += QString(";");
00980 d->db->execSql( sql, boundValues, &values );
00981
00982 if (values.isEmpty() || values.first().toInt() == 0)
00983 return false;
00984 else
00985 return true;
00986 }
00987
00988 QList<int> AlbumDB::getItemCommonTagIDs(const QList<qlonglong>& imageIDList)
00989 {
00990 QList<int> ids;
00991
00992 if (imageIDList.isEmpty())
00993 return ids;
00994
00995 QList<QVariant> values;
00996 QList<QVariant> boundValues;
00997
00998 QString sql = QString("SELECT DISTINCT tagid FROM ImageTags "
00999 "WHERE imageid=? ");
01000 boundValues << imageIDList.first();
01001
01002 QList<qlonglong>::const_iterator it = imageIDList.constBegin();
01003 ++it;
01004 for (; it != imageIDList.constEnd(); ++it)
01005 {
01006 sql += QString(" OR imageid=? ");
01007 boundValues << (*it);
01008 }
01009
01010 sql += QString(";");
01011 d->db->execSql( sql, boundValues, &values );
01012
01013 if (values.isEmpty())
01014 return ids;
01015
01016 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
01017 ids << it->toInt();
01018 return ids;
01019 }
01020
01021
01022
01023 QVariantList AlbumDB::getImagesFields(qlonglong imageID, DatabaseFields::Images fields)
01024 {
01025 QVariantList values;
01026 if (fields != DatabaseFields::ImagesNone)
01027 {
01028 QString query("SELECT ");
01029 QStringList fieldNames = imagesFieldList(fields);
01030 query += fieldNames.join(", ");
01031 query += (" FROM Images WHERE id=?;");
01032
01033 d->db->execSql(query, imageID, &values);
01034
01035
01036 if (fields & DatabaseFields::ModificationDate && !values.isEmpty())
01037 {
01038 int index = fieldNames.indexOf("modificationDate");
01039 values[index] = (values[index].isNull() ? QDateTime()
01040 : QDateTime::fromString(values[index].toString(), Qt::ISODate));
01041 }
01042 }
01043 return values;
01044 }
01045
01046 QVariantList AlbumDB::getImageInformation(qlonglong imageID, DatabaseFields::ImageInformation fields)
01047 {
01048 QVariantList values;
01049 if (fields != DatabaseFields::ImageInformationNone)
01050 {
01051 QString query("SELECT ");
01052 QStringList fieldNames = imageInformationFieldList(fields);
01053 query += fieldNames.join(", ");
01054 query += (" FROM ImageInformation WHERE imageid=?;");
01055
01056 d->db->execSql(query, imageID, &values);
01057
01058
01059 if (fields & DatabaseFields::CreationDate && !values.isEmpty())
01060 {
01061 int index = fieldNames.indexOf("creationDate");
01062 values[index] = (values[index].isNull() ? QDateTime()
01063 : QDateTime::fromString(values[index].toString(), Qt::ISODate));
01064 }
01065 if (fields & DatabaseFields::DigitizationDate && !values.isEmpty())
01066 {
01067 int index = fieldNames.indexOf("digitizationDate");
01068 values[index] = (values[index].isNull() ? QDateTime()
01069 : QDateTime::fromString(values[index].toString(), Qt::ISODate));
01070 }
01071 }
01072 return values;
01073 }
01074
01075 QVariantList AlbumDB::getImageMetadata(qlonglong imageID, DatabaseFields::ImageMetadata fields)
01076 {
01077 QVariantList values;
01078 if (fields != DatabaseFields::ImageMetadataNone)
01079 {
01080 QString query("SELECT ");
01081 QStringList fieldNames = imageMetadataFieldList(fields);
01082 query += fieldNames.join(", ");
01083 query += (" FROM ImageMetadata WHERE imageid=?;");
01084
01085 d->db->execSql(query, imageID, &values);
01086
01087
01088 if (values.size() == fieldNames.size() &&
01089 (fields & DatabaseFields::Aperture ||
01090 fields & DatabaseFields::FocalLength ||
01091 fields & DatabaseFields::FocalLength35 ||
01092 fields & DatabaseFields::ExposureTime ||
01093 fields & DatabaseFields::SubjectDistance)
01094 )
01095 {
01096 for (int i=0; i<values.size(); ++i)
01097 {
01098 if (values[i].type() == QVariant::String &&
01099 (fieldNames[i] == "aperture" ||
01100 fieldNames[i] == "focalLength" ||
01101 fieldNames[i] == "focalLength35" ||
01102 fieldNames[i] == "exposureTime" ||
01103 fieldNames[i] == "subjectDistance")
01104 )
01105 values[i] = values[i].toDouble();
01106 }
01107 }
01108 }
01109 return values;
01110 }
01111
01112 QVariantList AlbumDB::getImagePosition(qlonglong imageID, DatabaseFields::ImagePositions fields)
01113 {
01114 QVariantList values;
01115 if (fields != DatabaseFields::ImagePositionsNone)
01116 {
01117 QString query("SELECT ");
01118 QStringList fieldNames = imagePositionsFieldList(fields);
01119 query += fieldNames.join(", ");
01120 query += (" FROM ImagePositions WHERE imageid=?;");
01121
01122 d->db->execSql(query, imageID, &values);
01123
01124
01125 if (values.size() == fieldNames.size() &&
01126 (fields & DatabaseFields::LatitudeNumber ||
01127 fields & DatabaseFields::LongitudeNumber ||
01128 fields & DatabaseFields::Altitude ||
01129 fields & DatabaseFields::PositionOrientation ||
01130 fields & DatabaseFields::PositionTilt ||
01131 fields & DatabaseFields::PositionRoll ||
01132 fields & DatabaseFields::PositionAccuracy)
01133 )
01134 {
01135 for (int i=0; i<values.size(); ++i)
01136 {
01137 if (values[i].type() == QVariant::String &&
01138 (fieldNames[i] == "latitudeNumber" ||
01139 fieldNames[i] == "longitudeNumber" ||
01140 fieldNames[i] == "altitude" ||
01141 fieldNames[i] == "orientation" ||
01142 fieldNames[i] == "tilt" ||
01143 fieldNames[i] == "roll" ||
01144 fieldNames[i] == "accuracy")
01145 )
01146 values[i] = values[i].toDouble();
01147 }
01148 }
01149 }
01150 return values;
01151 }
01152
01153 void AlbumDB::addImageInformation(qlonglong imageID, const QVariantList& infos, DatabaseFields::ImageInformation fields)
01154 {
01155 if (fields == DatabaseFields::ImageInformationNone)
01156 return;
01157
01158 QString query("REPLACE INTO ImageInformation ( imageid, ");
01159
01160 QStringList fieldNames = imageInformationFieldList(fields);
01161 Q_ASSERT(fieldNames.size()==infos.size());
01162 query += fieldNames.join(", ");
01163
01164 query += " ) VALUES (";
01165 addBoundValuePlaceholders(query, infos.size() + 1);
01166 query += ");";
01167
01168 QVariantList boundValues;
01169 boundValues << imageID;
01170
01171 if (fields & DatabaseFields::CreationDate || fields & DatabaseFields::DigitizationDate)
01172 {
01173 foreach (const QVariant& value, infos)
01174 {
01175 if (value.type() == QVariant::DateTime || value.type() == QVariant::Date)
01176 boundValues << value.toDateTime().toString(Qt::ISODate);
01177 else
01178 boundValues << value;
01179 }
01180 }
01181 else
01182 boundValues << infos;
01183
01184 d->db->execSql( query, boundValues );
01185 d->db->recordChangeset(ImageChangeset(imageID, fields));
01186 }
01187
01188 void AlbumDB::changeImageInformation(qlonglong imageId, const QVariantList& infos,
01189 DatabaseFields::ImageInformation fields)
01190 {
01191 if (fields == DatabaseFields::ImageInformationNone)
01192 return;
01193
01194 QString query("UPDATE ImageInformation SET ");
01195
01196 QStringList fieldNames = imageInformationFieldList(fields);
01197 Q_ASSERT(fieldNames.size()==infos.size());
01198 query += fieldNames.join("=?,");
01199
01200 query += "=? WHERE imageid=?;";
01201
01202 QVariantList boundValues;
01203
01204 if (fields & DatabaseFields::CreationDate || fields & DatabaseFields::DigitizationDate)
01205 {
01206 foreach (const QVariant& value, infos)
01207 {
01208 if (value.type() == QVariant::DateTime || value.type() == QVariant::Date)
01209 boundValues << value.toDateTime().toString(Qt::ISODate);
01210 else
01211 boundValues << value;
01212 }
01213 boundValues << imageId;
01214 }
01215 else
01216 boundValues << infos << imageId;
01217
01218 d->db->execSql( query, boundValues );
01219 d->db->recordChangeset(ImageChangeset(imageId, fields));
01220 }
01221
01222 void AlbumDB::addImageMetadata(qlonglong imageID, const QVariantList& infos, DatabaseFields::ImageMetadata fields)
01223 {
01224 if (fields == DatabaseFields::ImageMetadataNone)
01225 return;
01226
01227 QString query("REPLACE INTO ImageMetadata ( imageid, ");
01228
01229 QStringList fieldNames = imageMetadataFieldList(fields);
01230 Q_ASSERT(fieldNames.size()==infos.size());
01231 query += fieldNames.join(", ");
01232
01233 query += " ) VALUES (";
01234 addBoundValuePlaceholders(query, infos.size() + 1);
01235 query += ");";
01236
01237 QVariantList boundValues;
01238 boundValues << imageID << infos;
01239
01240 d->db->execSql( query, boundValues );
01241 d->db->recordChangeset(ImageChangeset(imageID, fields));
01242 }
01243
01244 void AlbumDB::changeImageMetadata(qlonglong imageId, const QVariantList& infos,
01245 DatabaseFields::ImageMetadata fields)
01246 {
01247 if (fields == DatabaseFields::ImageMetadataNone)
01248 return;
01249
01250 QString query("UPDATE ImageMetadata SET ");
01251
01252 QStringList fieldNames = imageMetadataFieldList(fields);
01253 Q_ASSERT(fieldNames.size()==infos.size());
01254 query += fieldNames.join("=?,");
01255
01256 query += "=? WHERE imageid=?;";
01257
01258 QVariantList boundValues;
01259 boundValues << infos << imageId;
01260
01261 d->db->execSql( query, boundValues );
01262 d->db->recordChangeset(ImageChangeset(imageId, fields));
01263 }
01264
01265 void AlbumDB::addImagePosition(qlonglong imageID, const QVariantList& infos, DatabaseFields::ImagePositions fields)
01266 {
01267 if (fields == DatabaseFields::ImagePositionsNone)
01268 return;
01269
01270 QString query("REPLACE INTO ImagePositions ( imageid, ");
01271
01272 QStringList fieldNames = imagePositionsFieldList(fields);
01273 Q_ASSERT(fieldNames.size()==infos.size());
01274 query += fieldNames.join(", ");
01275
01276 query += " ) VALUES (";
01277 addBoundValuePlaceholders(query, infos.size() + 1);
01278 query += ");";
01279
01280 QVariantList boundValues;
01281 boundValues << imageID << infos;
01282
01283 d->db->execSql( query, boundValues );
01284 d->db->recordChangeset(ImageChangeset(imageID, fields));
01285 }
01286
01287 void AlbumDB::changeImagePosition(qlonglong imageId, const QVariantList& infos,
01288 DatabaseFields::ImagePositions fields)
01289 {
01290 if (fields == DatabaseFields::ImagePositionsNone)
01291 return;
01292
01293 QString query("UPDATE ImagePositions SET ");
01294
01295 QStringList fieldNames = imagePositionsFieldList(fields);
01296 Q_ASSERT(fieldNames.size()==infos.size());
01297 query += fieldNames.join("=?,");
01298
01299 query += "=? WHERE imageid=?;";
01300
01301 QVariantList boundValues;
01302 boundValues << infos << imageId;
01303
01304 d->db->execSql( query, boundValues );
01305 d->db->recordChangeset(ImageChangeset(imageId, fields));
01306 }
01307
01308 void AlbumDB::removeImagePosition(qlonglong imageid)
01309 {
01310 d->db->execSql( QString("DELETE FROM ImagePositions WHERE imageid=?;"),
01311 imageid );
01312
01313 d->db->recordChangeset(ImageChangeset(imageid, DatabaseFields::ImagePositionsAll));
01314 }
01315
01316 QList<CommentInfo> AlbumDB::getImageComments(qlonglong imageID)
01317 {
01318 QList<CommentInfo> list;
01319
01320 QList<QVariant> values;
01321 d->db->execSql( QString("SELECT id, type, language, author, date, comment "
01322 "FROM ImageComments WHERE imageid=?;"),
01323 imageID, &values);
01324
01325 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
01326 {
01327 CommentInfo info;
01328 info.imageId = imageID;
01329
01330 info.id = (*it).toInt();
01331 ++it;
01332 info.type = (DatabaseComment::Type)(*it).toInt();
01333 ++it;
01334 info.language = (*it).toString();
01335 ++it;
01336 info.author = (*it).toString();
01337 ++it;
01338 info.date = ((*it).isNull() ? QDateTime() : QDateTime::fromString((*it).toString(), Qt::ISODate));
01339 ++it;
01340 info.comment = (*it).toString();
01341 ++it;
01342
01343 list << info;
01344 }
01345
01346 return list;
01347 }
01348
01349 int AlbumDB::setImageComment(qlonglong imageID, const QString& comment, DatabaseComment::Type type,
01350 const QString& language, const QString& author, const QDateTime& date)
01351 {
01352 QVariantList boundValues;
01353 boundValues << imageID << (int)type << language << author << date << comment;
01354
01355 QVariant id;
01356 d->db->execSql( QString("REPLACE INTO ImageComments "
01357 "( imageid, type, language, author, date, comment ) "
01358 " VALUES (?,?,?,?,?,?);"),
01359 boundValues, 0, &id);
01360
01361 d->db->recordChangeset(ImageChangeset(imageID, DatabaseFields::ImageCommentsAll));
01362 return id.toInt();
01363 }
01364
01365 void AlbumDB::changeImageComment(int commentId, qlonglong imageID, const QVariantList& infos, DatabaseFields::ImageComments fields)
01366 {
01367 if (fields == DatabaseFields::ImageCommentsNone)
01368 return;
01369
01370 QString query("UPDATE ImageComments SET ");
01371
01372 QStringList fieldNames = imageCommentsFieldList(fields);
01373 Q_ASSERT(fieldNames.size()==infos.size());
01374 query += fieldNames.join("=?,");
01375 query += "=? WHERE id=?;";
01376
01377 QVariantList boundValues;
01378 boundValues << infos << commentId;
01379
01380 d->db->execSql( query, boundValues );
01381 d->db->recordChangeset(ImageChangeset(imageID, fields));
01382 }
01383
01384 void AlbumDB::removeImageComment(int commentid, qlonglong imageid)
01385 {
01386 d->db->execSql( QString("DELETE FROM ImageComments WHERE id=?;"),
01387 commentid );
01388
01389 d->db->recordChangeset(ImageChangeset(imageid, DatabaseFields::ImageCommentsAll));
01390 }
01391
01392 QString AlbumDB::getImageProperty(qlonglong imageID, const QString& property)
01393 {
01394 QList<QVariant> values;
01395
01396 d->db->execSql( QString("SELECT value FROM ImageProperties "
01397 "WHERE imageid=? and property=?;"),
01398 imageID, property,
01399 &values);
01400
01401 if (!values.isEmpty())
01402 return values.first().toString();
01403 else
01404 return QString();
01405 }
01406
01407 void AlbumDB::setImageProperty(qlonglong imageID, const QString& property, const QString& value)
01408 {
01409 d->db->execSql( QString ("REPLACE INTO ImageProperties "
01410 "(imageid, property, value) "
01411 "VALUES(?, ?, ?);"),
01412 imageID, property, value);
01413 }
01414
01415 void AlbumDB::removeImageProperty(qlonglong imageID, const QString& property)
01416 {
01417 d->db->execSql( QString ("DELETE FROM ImageProperties WHERE imageid=? AND property=?;"),
01418 imageID, property);
01419 }
01420
01421 QList<CopyrightInfo> AlbumDB::getImageCopyright(qlonglong imageID, const QString& property)
01422 {
01423 QList<CopyrightInfo> list;
01424
01425 QList<QVariant> values;
01426 if (property.isNull())
01427 {
01428 d->db->execSql( QString("SELECT property, value, extraValue FROM ImageCopyright "
01429 "WHERE imageid=?;"),
01430 imageID, &values);
01431 }
01432 else
01433 {
01434 d->db->execSql( QString("SELECT property, value, extraValue FROM ImageCopyright "
01435 "WHERE imageid=? and property=?;"),
01436 imageID, property, &values);
01437 }
01438
01439 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
01440 {
01441 CopyrightInfo info;
01442 info.id = imageID;
01443
01444 info.property = (*it).toString();
01445 ++it;
01446 info.value = (*it).toString();
01447 ++it;
01448 info.extraValue = (*it).toString();
01449 ++it;
01450
01451 list << info;
01452 }
01453
01454 return list;
01455 }
01456
01457 void AlbumDB::setImageCopyrightProperty(qlonglong imageID, const QString& property,
01458 const QString& value, const QString& extraValue,
01459 CopyrightPropertyUnique uniqueness)
01460 {
01461 if (uniqueness == PropertyUnique)
01462 {
01463 d->db->execSql( QString("DELETE FROM ImageCopyright "
01464 "WHERE imageid=? AND property=?;"),
01465 imageID, property );
01466 }
01467 else if (uniqueness == PropertyExtraValueUnique)
01468 {
01469 d->db->execSql( QString("DELETE FROM ImageCopyright "
01470 "WHERE imageid=? AND property=? AND extraValue=?;"),
01471 imageID, property, extraValue );
01472 }
01473
01474 d->db->execSql( QString("REPLACE INTO ImageCopyright "
01475 "(imageid, property, value, extraValue) "
01476 "VALUES(?, ?, ?, ?);"),
01477 imageID, property, value, extraValue);
01478 }
01479
01480 void AlbumDB::removeImageCopyrightProperties(qlonglong imageID, const QString& property,
01481 const QString& extraValue, const QString& value)
01482 {
01483 int removeBy = 0;
01484 if (!property.isNull())
01485 removeBy++;
01486 else if (!extraValue.isNull())
01487 removeBy++;
01488 else if (!value.isNull())
01489 removeBy++;
01490
01491 switch (removeBy)
01492 {
01493 case 0:
01494 d->db->execSql( QString("DELETE FROM ImageCopyright "
01495 "WHERE imageid=?;"),
01496 imageID );
01497 break;
01498 case 1:
01499 d->db->execSql( QString("DELETE FROM ImageCopyright "
01500 "WHERE imageid=? AND property=?;"),
01501 imageID, property );
01502 break;
01503 case 2:
01504 d->db->execSql( QString("DELETE FROM ImageCopyright "
01505 "WHERE imageid=? AND property=? AND extraValue=?;"),
01506 imageID, property, extraValue );
01507 break;
01508 case 3:
01509 d->db->execSql( QString("DELETE FROM ImageCopyright "
01510 "WHERE imageid=? AND property=? AND extraValue=? AND value=?;"),
01511 imageID, property, extraValue, value );
01512 break;
01513 }
01514 }
01515
01516 bool AlbumDB::hasHaarFingerprints()
01517 {
01518 QList<QVariant> values;
01519
01520 d->db->execSql( QString("SELECT imageid FROM ImageHaarMatrix "
01521 "WHERE matrix IS NOT NULL LIMIT 1;"),
01522 &values);
01523
01524
01525 return !values.isEmpty();
01526 }
01527
01528 QList<qlonglong> AlbumDB::getDirtyOrMissingFingerprints()
01529 {
01530 QList<qlonglong> itemIDs;
01531 QList<QVariant> values;
01532
01533 d->db->execSql( QString("SELECT id FROM Images "
01534 "LEFT JOIN ImageHaarMatrix ON Images.id=ImageHaarMatrix.imageid "
01535 " WHERE Images.status=1 AND Images.category=1 AND "
01536 " ( ImageHaarMatrix.imageid IS NULL "
01537 " OR Images.modificationDate != ImageHaarMatrix.modificationDate "
01538 " OR Images.uniqueHash != ImageHaarMatrix.uniqueHash ); "),
01539 &values );
01540
01541 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
01542 {
01543 itemIDs << (*it).toLongLong();
01544 }
01545
01546 return itemIDs;
01547 }
01548
01549 QStringList AlbumDB::getDirtyOrMissingFingerprintURLs()
01550 {
01551 QList<QVariant> values;
01552
01553 d->db->execSql( QString("SELECT Albums.albumRoot, Albums.relativePath, Images.name FROM Images "
01554 "LEFT JOIN ImageHaarMatrix ON Images.id=ImageHaarMatrix.imageid "
01555 "LEFT JOIN Albums ON Albums.id=Images.album "
01556 " WHERE Images.status=1 AND Images.category=1 AND "
01557 " ( ImageHaarMatrix.imageid IS NULL "
01558 " OR Images.modificationDate != ImageHaarMatrix.modificationDate "
01559 " OR Images.uniqueHash != ImageHaarMatrix.uniqueHash ); "),
01560 &values );
01561
01562 QStringList urls;
01563 QString albumRootPath, relativePath, name;
01564 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
01565 {
01566 albumRootPath = CollectionManager::instance()->albumRootPath((*it).toInt());
01567 ++it;
01568 relativePath = (*it).toString();
01569 ++it;
01570 name = (*it).toString();
01571 ++it;
01572 if (relativePath == "/")
01573 urls << albumRootPath + relativePath + name;
01574 else
01575 urls << albumRootPath + relativePath + '/' + name;
01576 }
01577
01578 return urls;
01579 }
01580
01581 QList<ItemScanInfo> AlbumDB::getIdenticalFiles(qlonglong id)
01582 {
01583 if (!id)
01584 return QList<ItemScanInfo>();
01585
01586 QList<QVariant> values;
01587
01588
01589 d->db->execSql( QString("SELECT uniqueHash, fileSize FROM Images WHERE id=?; "),
01590 id,
01591 &values );
01592
01593 if (values.isEmpty())
01594 return QList<ItemScanInfo>();
01595
01596 QString uniqueHash = values[0].toString();
01597 int fileSize = values[1].toInt();
01598
01599 return getIdenticalFiles(fileSize, uniqueHash, id);
01600 }
01601
01602 QList<ItemScanInfo> AlbumDB::getIdenticalFiles(int fileSize, const QString& uniqueHash, qlonglong sourceId)
01603 {
01604
01605 if (uniqueHash.isEmpty() || fileSize <= 0)
01606 return QList<ItemScanInfo>();
01607
01608 QList<QVariant> values;
01609
01610
01611 d->db->execSql( QString("SELECT id, album, name, status, category, modificationDate FROM Images "
01612 " WHERE fileSize=? AND uniqueHash=?; "),
01613 fileSize, uniqueHash,
01614 &values );
01615
01616 QList<ItemScanInfo> list;
01617 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
01618 {
01619 ItemScanInfo info;
01620
01621 info.id = (*it).toLongLong();
01622 ++it;
01623 info.albumID = (*it).toInt();
01624 ++it;
01625 info.itemName = (*it).toString();
01626 ++it;
01627 info.status = (DatabaseItem::Status)(*it).toInt();
01628 ++it;
01629 info.category = (DatabaseItem::Category)(*it).toInt();
01630 ++it;
01631 info.modificationDate = ((*it).isNull() ? QDateTime()
01632 : QDateTime::fromString( (*it).toString(), Qt::ISODate ));
01633 ++it;
01634
01635
01636 if (sourceId == info.id)
01637 continue;
01638
01639
01640 info.uniqueHash = uniqueHash;
01641
01642 list << info;
01643 }
01644
01645 return list;
01646 }
01647
01648 QStringList AlbumDB::imagesFieldList(DatabaseFields::Images fields)
01649 {
01650
01651 QStringList list;
01652 if (fields & DatabaseFields::Album)
01653 list << "album";
01654 if (fields & DatabaseFields::Name)
01655 list << "name";
01656 if (fields & DatabaseFields::Status)
01657 list << "status";
01658 if (fields & DatabaseFields::Category)
01659 list << "category";
01660 if (fields & DatabaseFields::ModificationDate)
01661 list << "modificationDate";
01662 if (fields & DatabaseFields::FileSize)
01663 list << "fileSize";
01664 if (fields & DatabaseFields::UniqueHash)
01665 list << "uniqueHash";
01666
01667 return list;
01668 }
01669
01670 QStringList AlbumDB::imageInformationFieldList(DatabaseFields::ImageInformation fields)
01671 {
01672
01673 QStringList list;
01674 if (fields & DatabaseFields::Rating)
01675 list << "rating";
01676 if (fields & DatabaseFields::CreationDate)
01677 list << "creationDate";
01678 if (fields & DatabaseFields::DigitizationDate)
01679 list << "digitizationDate";
01680 if (fields & DatabaseFields::Orientation)
01681 list << "orientation";
01682 if (fields & DatabaseFields::Width)
01683 list << "width";
01684 if (fields & DatabaseFields::Height)
01685 list << "height";
01686 if (fields & DatabaseFields::Format)
01687 list << "format";
01688 if (fields & DatabaseFields::ColorDepth)
01689 list << "colorDepth";
01690 if (fields & DatabaseFields::ColorModel)
01691 list << "colorModel";
01692
01693 return list;
01694 }
01695
01696 QStringList AlbumDB::imageMetadataFieldList(DatabaseFields::ImageMetadata fields)
01697 {
01698
01699 QStringList list;
01700 if (fields & DatabaseFields::Make)
01701 list << "make";
01702 if (fields & DatabaseFields::Model)
01703 list << "model";
01704 if (fields & DatabaseFields::Lens)
01705 list << "lens";
01706 if (fields & DatabaseFields::Aperture)
01707 list << "aperture";
01708 if (fields & DatabaseFields::FocalLength)
01709 list << "focalLength";
01710 if (fields & DatabaseFields::FocalLength35)
01711 list << "focalLength35";
01712 if (fields & DatabaseFields::ExposureTime)
01713 list << "exposureTime";
01714 if (fields & DatabaseFields::ExposureProgram)
01715 list << "exposureProgram";
01716 if (fields & DatabaseFields::ExposureMode)
01717 list << "exposureMode";
01718 if (fields & DatabaseFields::Sensitivity)
01719 list << "sensitivity";
01720 if (fields & DatabaseFields::FlashMode)
01721 list << "flash";
01722 if (fields & DatabaseFields::WhiteBalance)
01723 list << "whiteBalance";
01724 if (fields & DatabaseFields::WhiteBalanceColorTemperature)
01725 list << "whiteBalanceColorTemperature";
01726 if (fields & DatabaseFields::MeteringMode)
01727 list << "meteringMode";
01728 if (fields & DatabaseFields::SubjectDistance)
01729 list << "subjectDistance";
01730 if (fields & DatabaseFields::SubjectDistanceCategory)
01731 list << "subjectDistanceCategory";
01732
01733 return list;
01734 }
01735
01736 QStringList AlbumDB::imagePositionsFieldList(DatabaseFields::ImagePositions fields)
01737 {
01738
01739 QStringList list;
01740 if (fields & DatabaseFields::Latitude)
01741 list << "latitude";
01742 if (fields & DatabaseFields::LatitudeNumber)
01743 list << "latitudeNumber";
01744 if (fields & DatabaseFields::Longitude)
01745 list << "longitude";
01746 if (fields & DatabaseFields::LongitudeNumber)
01747 list << "longitudeNumber";
01748 if (fields & DatabaseFields::Altitude)
01749 list << "altitude";
01750 if (fields & DatabaseFields::PositionOrientation)
01751 list << "orientation";
01752 if (fields & DatabaseFields::PositionTilt)
01753 list << "tilt";
01754 if (fields & DatabaseFields::PositionRoll)
01755 list << "roll";
01756 if (fields & DatabaseFields::PositionAccuracy)
01757 list << "accuracy";
01758 if (fields & DatabaseFields::PositionDescription)
01759 list << "description";
01760
01761 return list;
01762 }
01763
01764 QStringList AlbumDB::imageCommentsFieldList(DatabaseFields::ImageComments fields)
01765 {
01766
01767 QStringList list;
01768 if (fields & DatabaseFields::CommentType)
01769 list << "type";
01770 if (fields & DatabaseFields::CommentLanguage)
01771 list << "language";
01772 if (fields & DatabaseFields::CommentAuthor)
01773 list << "author";
01774 if (fields & DatabaseFields::CommentDate)
01775 list << "date";
01776 if (fields & DatabaseFields::Comment)
01777 list << "comment";
01778
01779 return list;
01780 }
01781
01782
01783 void AlbumDB::addBoundValuePlaceholders(QString& query, int count)
01784 {
01785
01786 QString questionMarks;
01787 questionMarks.reserve(count * 2);
01788 QString questionMark("?,");
01789
01790 for (int i=0; i<count; ++i)
01791 questionMarks += questionMark;
01792
01793 questionMarks.chop(1);
01794
01795 query += questionMarks;
01796 }
01797
01798 int AlbumDB::findInDownloadHistory(const QString& identifier, const QString& name, int fileSize, const QDateTime& date)
01799 {
01800 QList<QVariant> values;
01801 d->db->execSql( QString("SELECT id FROM DownloadHistory WHERE "
01802 "identifier=? AND filename=? AND filesize=? AND filedate=?;"),
01803 identifier, name, fileSize, date.toString(Qt::ISODate), &values);
01804
01805 if (values.isEmpty())
01806 return -1;
01807 return values.first().toInt();
01808 }
01809
01810 int AlbumDB::addToDownloadHistory(const QString& identifier, const QString& name, int fileSize, const QDateTime& date)
01811 {
01812 QVariant id;
01813 d->db->execSql( QString("REPLACE INTO DownloadHistory "
01814 "(identifier, filename, filesize, filedate) "
01815 "VALUES (?,?,?,?);"),
01816 identifier, name, fileSize, date.toString(Qt::ISODate), 0, &id);
01817
01818 return id.toInt();
01819 }
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855 void AlbumDB::addItemTag(qlonglong imageID, int tagID)
01856 {
01857 d->db->execSql( QString("REPLACE INTO ImageTags (imageid, tagid) "
01858 "VALUES(?, ?);"),
01859 imageID,
01860 tagID );
01861
01862 d->db->recordChangeset(ImageTagChangeset(imageID, tagID, ImageTagChangeset::Added));
01863
01864 if (!d->recentlyAssignedTags.contains(tagID))
01865 {
01866 d->recentlyAssignedTags.push_front(tagID);
01867 if (d->recentlyAssignedTags.size() > 10)
01868 d->recentlyAssignedTags.pop_back();
01869 }
01870 }
01871
01872 void AlbumDB::addItemTag(int albumID, const QString& name, int tagID)
01873 {
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 return addItemTag(getImageId(albumID, name), tagID);
01885 }
01886
01887 void AlbumDB::addTagsToItems(QList<qlonglong> imageIDs, QList<int> tagIDs)
01888 {
01889 QSqlQuery query = d->db->prepareQuery("REPLACE INTO ImageTags (imageid, tagid) VALUES(?, ?);");
01890
01891 QVariantList images;
01892 QVariantList tags;
01893
01894 foreach (const qlonglong& imageid, imageIDs)
01895 {
01896 foreach (int tagid, tagIDs)
01897 {
01898 images << imageid;
01899 tags << tagid;
01900 }
01901 }
01902
01903 query.addBindValue(images);
01904 query.addBindValue(tags);
01905 d->db->execBatch(query);
01906 d->db->recordChangeset(ImageTagChangeset(imageIDs, tagIDs, ImageTagChangeset::Added));
01907 }
01908
01909 QList<int> AlbumDB::getRecentlyAssignedTags() const
01910 {
01911 return d->recentlyAssignedTags;
01912 }
01913
01914 void AlbumDB::removeItemTag(qlonglong imageID, int tagID)
01915 {
01916 d->db->execSql( QString("DELETE FROM ImageTags "
01917 "WHERE imageID=? AND tagid=?;"),
01918 imageID,
01919 tagID );
01920
01921 d->db->recordChangeset(ImageTagChangeset(imageID, tagID, ImageTagChangeset::Removed));
01922 }
01923
01924 void AlbumDB::removeItemAllTags(qlonglong imageID, QList<int> currentTagIds)
01925 {
01926 d->db->execSql( QString("DELETE FROM ImageTags "
01927 "WHERE imageID=?;"),
01928 imageID );
01929
01930 d->db->recordChangeset(ImageTagChangeset(imageID, currentTagIds, ImageTagChangeset::RemovedAll));
01931 }
01932
01933 void AlbumDB::removeTagsFromItems(QList<qlonglong> imageIDs, QList<int> tagIDs)
01934 {
01935 QSqlQuery query = d->db->prepareQuery("DELETE FROM ImageTags WHERE imageID=? AND tagid=?;");
01936
01937 QVariantList images;
01938 QVariantList tags;
01939
01940 foreach (const qlonglong& imageid, imageIDs)
01941 {
01942 foreach (int tagid, tagIDs)
01943 {
01944 images << imageid;
01945 tags << tagid;
01946 }
01947 }
01948
01949 query.addBindValue(images);
01950 query.addBindValue(tags);
01951 d->db->execBatch(query);
01952 d->db->recordChangeset(ImageTagChangeset(imageIDs, tagIDs, ImageTagChangeset::Removed));
01953 }
01954
01955 QStringList AlbumDB::getItemNamesInAlbum(int albumID, bool recurssive)
01956 {
01957 QList<QVariant> values;
01958
01959 if (recurssive)
01960 {
01961 int rootId = getAlbumRootId(albumID);
01962 QString path = getAlbumRelativePath(albumID);
01963 d->db->execSql( QString("SELECT Images.name FROM Images WHERE Images.album IN "
01964 " (SELECT DISTINCT id FROM Albums "
01965 " WHERE albumRoot=? AND (relativePath=? OR relativePath LIKE ?));"),
01966 rootId, path, path == "/" ? "/%" : path + "/%",
01967 &values );
01968 }
01969 else
01970 {
01971 d->db->execSql( QString("SELECT Images.name "
01972 "FROM Images "
01973 "WHERE Images.album=?"),
01974 albumID, &values );
01975 }
01976
01977 QStringList names;
01978 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
01979 names << it->toString();
01980 return names;
01981 }
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003 QList<QDateTime> AlbumDB::getAllCreationDates()
02004 {
02005 QList<QVariant> values;
02006 d->db->execSql( "SELECT creationDate FROM ImageInformation "
02007 " INNER JOIN Images ON Images.id=ImageInformation.imageid "
02008 " WHERE Images.status=1;", &values );
02009
02010 QList<QDateTime> list;
02011 foreach (const QVariant& value, values)
02012 {
02013 if (!value.isNull())
02014 list << QDateTime::fromString(value.toString(), Qt::ISODate);
02015 }
02016 return list;
02017 }
02018
02019 QMap<QDateTime, int> AlbumDB::getAllCreationDatesAndNumberOfImages()
02020 {
02021 QList<QVariant> values;
02022 d->db->execSql( "SELECT creationDate FROM ImageInformation "
02023 " INNER JOIN Images ON Images.id=ImageInformation.imageid "
02024 " WHERE Images.status=1;", &values );
02025
02026 QMap<QDateTime, int> datesStatMap;
02027 foreach (const QVariant& value, values)
02028 {
02029 if (!value.isNull())
02030 {
02031 QDateTime dateTime = QDateTime::fromString(value.toString(), Qt::ISODate);
02032 if ( !dateTime.isValid() )
02033 continue;
02034
02035 QMap<QDateTime, int>::iterator it2 = datesStatMap.find(dateTime);
02036 if ( it2 == datesStatMap.end() )
02037 datesStatMap.insert( dateTime, 1 );
02038 else
02039 it2.value()++;
02040 }
02041 }
02042 return datesStatMap;
02043 }
02044
02045 QMap<int, int> AlbumDB::getNumberOfImagesInAlbums()
02046 {
02047 QList<QVariant> values, allAbumIDs;
02048 QMap<int, int> albumsStatMap;
02049 int albumID;
02050
02051
02052
02053 d->db->execSql("SELECT id from Albums", &allAbumIDs);
02054
02055 for (QList<QVariant>::const_iterator it = allAbumIDs.constBegin(); it != allAbumIDs.constEnd(); ++it)
02056 {
02057 albumID = (*it).toInt();
02058 albumsStatMap.insert(albumID, 0);
02059 }
02060
02061 d->db->execSql( "SELECT album FROM Images WHERE Images.status=1;", &values );
02062
02063 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02064 {
02065 albumID = (*it).toInt();
02066 ++it;
02067
02068 QMap<int, int>::iterator it2 = albumsStatMap.find(albumID);
02069 if ( it2 == albumsStatMap.end() )
02070 albumsStatMap.insert(albumID, 1);
02071 else
02072 it2.value()++;
02073 }
02074
02075 return albumsStatMap;
02076 }
02077
02078 QMap<int, int> AlbumDB::getNumberOfImagesInTags()
02079 {
02080 QList<QVariant> values, allTagIDs;
02081 QMap<int, int> tagsStatMap;
02082 int tagID;
02083
02084
02085
02086 d->db->execSql(QString("SELECT id from Tags"), &allTagIDs);
02087
02088 for (QList<QVariant>::const_iterator it = allTagIDs.constBegin(); it != allTagIDs.constEnd(); ++it)
02089 {
02090 tagID = (*it).toInt();
02091 tagsStatMap.insert(tagID, 0);
02092 }
02093
02094 d->db->execSql( "SELECT tagid FROM ImageTags "
02095 " LEFT JOIN Images ON Images.id=ImageTags.imageid "
02096 " WHERE Images.status=1;", &values );
02097
02098 for (QList<QVariant>::const_iterator it=values.constBegin(); it != values.constEnd();)
02099 {
02100 tagID = (*it).toInt();
02101 ++it;
02102
02103 QMap<int, int>::iterator it2 = tagsStatMap.find(tagID);
02104 if ( it2 == tagsStatMap.end() )
02105 tagsStatMap.insert(tagID, 1);
02106 else
02107 it2.value()++;
02108 }
02109
02110 return tagsStatMap;
02111 }
02112
02113 QMap<QString,int> AlbumDB::getImageFormatStatistics()
02114 {
02115 QMap<QString, int> map;
02116
02117 QSqlQuery query;
02118 query = d->db->prepareQuery("SELECT COUNT(*), II.format "
02119 "FROM ImageInformation AS II "
02120 " INNER JOIN Images ON II.imageid=images.id "
02121 "WHERE Images.status=1 "
02122 "GROUP BY II.format;");
02123 if (d->db->exec(query))
02124 {
02125 while (query.next())
02126 {
02127 QString quantity = query.value(0).toString();
02128 QString format = query.value(1).toString();
02129 if (format.isEmpty())
02130 continue;
02131 map[format] = quantity.isEmpty() ? 0 : quantity.toInt();
02132 }
02133 }
02134
02135 return map;
02136 }
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174 int AlbumDB::getAlbumForPath(int albumRootId, const QString& folder, bool create)
02175 {
02176 QList<QVariant> values;
02177 d->db->execSql( QString("SELECT id FROM Albums WHERE albumRoot=? AND relativePath=?;"),
02178 albumRootId, folder, &values);
02179
02180 int albumID = -1;
02181 if (values.isEmpty())
02182 {
02183 if (create)
02184 albumID = addAlbum(albumRootId, folder, QString(), QDate::currentDate(), QString());
02185 }
02186 else
02187 {
02188 albumID = values.first().toInt();
02189 }
02190
02191 return albumID;
02192 }
02193
02194 QList<int> AlbumDB::getAlbumAndSubalbumsForPath(int albumRootId, const QString& relativePath)
02195 {
02196 QList<QVariant> values;
02197 d->db->execSql( QString("SELECT id FROM Albums WHERE albumRoot=? AND (relativePath=? OR relativePath LIKE ?);"),
02198 albumRootId, relativePath, (relativePath == "/" ? "/%" : relativePath + "/%"), &values);
02199
02200 QList<int> albumIds;
02201 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
02202 {
02203 albumIds << (*it).toInt();
02204 }
02205 return albumIds;
02206 }
02207
02208 QList<int> AlbumDB::getAlbumsOnAlbumRoot(int albumRootId)
02209 {
02210 QList<QVariant> values;
02211 d->db->execSql( QString("SELECT id FROM Albums WHERE albumRoot=?;"),
02212 albumRootId, &values);
02213
02214 QList<int> albumIds;
02215 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
02216 {
02217 albumIds << (*it).toInt();
02218 }
02219 return albumIds;
02220 }
02221
02222 qlonglong AlbumDB::addItem(int albumID, const QString& name,
02223 DatabaseItem::Status status,
02224 DatabaseItem::Category category,
02225 const QDateTime& modificationDate,
02226 int fileSize,
02227 const QString& uniqueHash)
02228 {
02229 QVariantList boundValues;
02230 boundValues << albumID << name << (int)status << (int)category
02231 << modificationDate.toString(Qt::ISODate) << fileSize << uniqueHash;
02232
02233 QVariant id;
02234 d->db->execSql ( QString ("REPLACE INTO Images "
02235 " ( album, name, status, category, modificationDate, fileSize, uniqueHash ) "
02236 " VALUES (?,?,?,?,?,?,?);" ),
02237 boundValues,
02238 0, &id);
02239
02240 if (id.isNull())
02241 return -1;
02242 d->db->recordChangeset(ImageChangeset(id.toLongLong(), DatabaseFields::ImagesAll));
02243 d->db->recordChangeset(CollectionImageChangeset(id.toLongLong(), albumID, CollectionImageChangeset::Added));
02244 return id.toLongLong();
02245 }
02246
02247 void AlbumDB::updateItem(qlonglong imageID, DatabaseItem::Category category,
02248 const QDateTime& modificationDate,
02249 int fileSize, const QString& uniqueHash)
02250 {
02251 QVariantList boundValues;
02252 boundValues << category << modificationDate << fileSize << uniqueHash << imageID;
02253 d->db->execSql( QString("UPDATE Images SET category=?, modificationDate=?, fileSize=?, uniqueHash=? WHERE id=?;"),
02254 boundValues );
02255 d->db->recordChangeset(ImageChangeset(imageID, DatabaseFields::Category
02256 | DatabaseFields::ModificationDate
02257 | DatabaseFields::FileSize
02258 | DatabaseFields::UniqueHash ));
02259 }
02260
02261 QList<int> AlbumDB::getTagsFromTagPaths(const QStringList& keywordsList, bool create)
02262 {
02263 if (keywordsList.isEmpty())
02264 return QList<int>();
02265
02266 QList<int> tagIDs;
02267
02268 QStringList keywordsList2Create;
02269
02270
02271
02272 TagInfo::List currentTagsList;
02273
02274 QList<QVariant> values;
02275 d->db->execSql( "SELECT id, pid, name FROM Tags;", &values );
02276
02277 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02278 {
02279 TagInfo info;
02280
02281 info.id = (*it).toInt();
02282 ++it;
02283 info.pid = (*it).toInt();
02284 ++it;
02285 info.name = (*it).toString();
02286 ++it;
02287 currentTagsList.append(info);
02288 }
02289
02290
02291
02292 for (QStringList::const_iterator kwd = keywordsList.constBegin();
02293 kwd != keywordsList.constEnd(); ++kwd )
02294 {
02295
02296 QStringList tagHierarchy = (*kwd).split('/', QString::SkipEmptyParts);
02297 if (tagHierarchy.isEmpty())
02298 continue;
02299
02300
02301 bool foundTag = false;
02302 QString tagName = tagHierarchy.back();
02303 tagHierarchy.pop_back();
02304
02305 for (TagInfo::List::const_iterator tag = currentTagsList.constBegin();
02306 tag != currentTagsList.constEnd(); ++tag )
02307 {
02308
02309
02310 if ((*tag).name == tagName)
02311 {
02312 int parentID = (*tag).pid;
02313
02314
02315 bool foundParentTag = true;
02316 QStringList::iterator parentTagName = tagHierarchy.end();
02317
02318 while (foundParentTag && parentTagName != tagHierarchy.begin())
02319 {
02320 --parentTagName;
02321
02322 foundParentTag = false;
02323
02324 for (TagInfo::List::const_iterator parentTag = currentTagsList.constBegin();
02325 parentTag != currentTagsList.constEnd(); ++parentTag )
02326 {
02327
02328
02329 if ( (*parentTag).id == parentID &&
02330 (*parentTag).name == (*parentTagName) )
02331 {
02332 parentID = (*parentTag).pid;
02333 foundParentTag = true;
02334 break;
02335 }
02336 }
02337
02338
02339
02340 }
02341
02342
02343
02344 if (foundParentTag)
02345 {
02346
02347 tagIDs.append((*tag).id);
02348 foundTag = true;
02349 break;
02350 }
02351 }
02352 }
02353
02354 if (!foundTag)
02355 keywordsList2Create.append(*kwd);
02356 }
02357
02358
02359
02360 if (create && !keywordsList2Create.isEmpty())
02361 {
02362 for (QStringList::const_iterator kwd = keywordsList2Create.constBegin();
02363 kwd != keywordsList2Create.constEnd(); ++kwd )
02364 {
02365
02366 QStringList tagHierarchy = (*kwd).split('/', QString::SkipEmptyParts);
02367
02368 if (tagHierarchy.isEmpty())
02369 continue;
02370
02371 int parentTagID = 0;
02372 int tagID = 0;
02373 bool parentTagExisted = true;
02374
02375
02376 for (QStringList::const_iterator tagName = tagHierarchy.constBegin();
02377 tagName != tagHierarchy.constEnd(); ++tagName)
02378 {
02379 tagID = 0;
02380
02381
02382 if (parentTagExisted)
02383 {
02384 for (TagInfo::List::const_iterator tag = currentTagsList.constBegin();
02385 tag != currentTagsList.constEnd(); ++tag )
02386 {
02387
02388
02389
02390 if ((*tag).name == (*tagName) && (*tag).pid == parentTagID)
02391 {
02392 tagID = (*tag).id;
02393 break;
02394 }
02395 }
02396 }
02397
02398 if (tagID != 0)
02399 {
02400
02401 parentTagID = tagID;
02402 continue;
02403 }
02404
02405
02406 tagID = addTag(parentTagID, (*tagName), QString(), 0);
02407
02408 if (tagID == -1)
02409 {
02410
02411 break;
02412 }
02413
02414
02415 TagInfo info;
02416 info.id = tagID;
02417 info.pid = parentTagID;
02418 info.name = (*tagName);
02419 currentTagsList.append(info);
02420
02421 parentTagID = tagID;
02422 parentTagExisted = false;
02423 }
02424
02425
02426 tagIDs.append(tagID);
02427 }
02428 }
02429
02430 return tagIDs;
02431 }
02432
02433 int AlbumDB::getItemAlbum(qlonglong imageID)
02434 {
02435 QList<QVariant> values;
02436
02437 d->db->execSql(QString("SELECT album FROM Images WHERE id=?;"),
02438 imageID, &values);
02439
02440 if (!values.isEmpty())
02441 return values.first().toInt();
02442 else
02443 return 1;
02444 }
02445
02446 QString AlbumDB::getItemName(qlonglong imageID)
02447 {
02448 QList<QVariant> values;
02449
02450 d->db->execSql(QString("SELECT name FROM Images WHERE id=?;"),
02451 imageID, &values);
02452
02453 if (!values.isEmpty())
02454 return values.first().toString();
02455 else
02456 return QString();
02457 }
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521 QStringList AlbumDB::getItemURLsInAlbum(int albumID, ItemSortOrder sortOrder)
02522 {
02523 QList<QVariant> values;
02524
02525 int albumRootId = getAlbumRootId(albumID);
02526 if (albumRootId == -1)
02527 return QStringList();
02528 QString albumRootPath = CollectionManager::instance()->albumRootPath(albumRootId);
02529 if (albumRootPath.isNull())
02530 return QStringList();
02531
02532 QString sqlString;
02533 switch(sortOrder)
02534 {
02535 case ByItemName:
02536 sqlString = QString("SELECT Albums.relativePath, Images.name "
02537 "FROM Images INNER JOIN Albums ON Albums.id=Images.album "
02538 "WHERE Albums.id=? "
02539 "ORDER BY Images.name COLLATE NOCASE;");
02540 break;
02541 case ByItemPath:
02542
02543
02544 sqlString = QString("SELECT Albums.relativePath, Images.name "
02545 "FROM Images INNER JOIN Albums ON Albums.id=Images.album "
02546 "WHERE Albums.id=? "
02547 "ORDER BY Albums.relativePath,Images.name;");
02548 break;
02549 case ByItemDate:
02550 sqlString = QString("SELECT Albums.relativePath, Images.name "
02551 "FROM Images INNER JOIN Albums ON Albums.id=Images.album "
02552 " INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id "
02553 "WHERE Albums.id=? "
02554 "ORDER BY ImageInformation.creationDate;");
02555 break;
02556 case ByItemRating:
02557 sqlString = QString("SELECT Albums.relativePath, Images.name "
02558 "FROM Images INNER JOIN Albums ON Albums.id=Images.album "
02559 " INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id "
02560 "WHERE Albums.id=? "
02561 "ORDER BY ImageInformation.rating DESC;");
02562 break;
02563 case NoItemSorting:
02564 default:
02565 sqlString = QString("SELECT Albums.relativePath, Images.name "
02566 "FROM Images INNER JOIN Albums ON Albums.id=Images.album "
02567 "WHERE Albums.id=?;");
02568 break;
02569 }
02570
02571 d->db->execSql(sqlString, albumID, &values);
02572
02573 QStringList urls;
02574 QString relativePath, name;
02575 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02576 {
02577 relativePath = (*it).toString();
02578 ++it;
02579 name = (*it).toString();
02580 ++it;
02581 if (relativePath == "/")
02582 urls << albumRootPath + relativePath + name;
02583 else
02584 urls << albumRootPath + relativePath + '/' + name;
02585 }
02586
02587 return urls;
02588 }
02589
02590 QList<qlonglong> AlbumDB::getItemIDsInAlbum(int albumID)
02591 {
02592 QList<qlonglong> itemIDs;
02593 QList<QVariant> values;
02594
02595 d->db->execSql( QString("SELECT id FROM Images WHERE album=?;"),
02596 albumID, &values );
02597
02598 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
02599 {
02600 itemIDs << (*it).toLongLong();
02601 }
02602
02603 return itemIDs;
02604 }
02605
02606 QMap<qlonglong, QString> AlbumDB::getItemIDsAndURLsInAlbum(int albumID)
02607 {
02608 int albumRootId = getAlbumRootId(albumID);
02609 if (albumRootId == -1)
02610 return QMap<qlonglong, QString>();
02611
02612 QString albumRootPath = CollectionManager::instance()->albumRootPath(albumRootId);
02613 if (albumRootPath.isNull())
02614 return QMap<qlonglong, QString>();
02615
02616 QMap<qlonglong, QString> itemsMap;
02617 QList<QVariant> values;
02618
02619 d->db->execSql( QString("SELECT Images.id, Albums.relativePath, Images.name "
02620 "FROM Images JOIN Albums ON Albums.id=Images.album "
02621 "WHERE Albums.id=?;"),
02622 albumID, &values );
02623
02624 QString path;
02625 qlonglong id;
02626 QString relativePath, name;
02627 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02628 {
02629 id = (*it).toLongLong();
02630 ++it;
02631 relativePath = (*it).toString();
02632 ++it;
02633 name = (*it).toString();
02634 ++it;
02635 if (relativePath == "/")
02636 path = albumRootPath + relativePath + name;
02637 else
02638 path = albumRootPath + relativePath + '/' + name;
02639
02640 itemsMap.insert(id, path);
02641 };
02642
02643 return itemsMap;
02644 }
02645
02646 QList<ItemScanInfo> AlbumDB::getItemScanInfos(int albumID)
02647 {
02648 QList<QVariant> values;
02649
02650 d->db->execSql( QString("SELECT id, album, name, status, category, modificationDate, uniqueHash "
02651 "FROM Images WHERE album=?;"),
02652 albumID,
02653 &values );
02654
02655 QList<ItemScanInfo> list;
02656
02657 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02658 {
02659 ItemScanInfo info;
02660
02661 info.id = (*it).toLongLong();
02662 ++it;
02663 info.albumID = (*it).toInt();
02664 ++it;
02665 info.itemName = (*it).toString();
02666 ++it;
02667 info.status = (DatabaseItem::Status)(*it).toInt();
02668 ++it;
02669 info.category = (DatabaseItem::Category)(*it).toInt();
02670 ++it;
02671 info.modificationDate = ((*it).isNull() ? QDateTime()
02672 : QDateTime::fromString( (*it).toString(), Qt::ISODate ));
02673 ++it;
02674 info.uniqueHash = (*it).toString();
02675 ++it;
02676
02677 list << info;
02678 }
02679
02680 return list;
02681 }
02682
02683 ItemScanInfo AlbumDB::getItemScanInfo(qlonglong imageID)
02684 {
02685 QList<QVariant> values;
02686
02687 d->db->execSql( QString("SELECT id, album, name, status, category, modificationDate, uniqueHash "
02688 "FROM Images WHERE id=?;"),
02689 imageID,
02690 &values );
02691
02692 ItemScanInfo info;
02693
02694 if (!values.isEmpty())
02695 {
02696 QList<QVariant>::const_iterator it = values.constBegin();
02697
02698 info.id = (*it).toLongLong();
02699 ++it;
02700 info.albumID = (*it).toInt();
02701 ++it;
02702 info.itemName = (*it).toString();
02703 ++it;
02704 info.status = (DatabaseItem::Status)(*it).toInt();
02705 ++it;
02706 info.category = (DatabaseItem::Category)(*it).toInt();
02707 ++it;
02708 info.modificationDate = ((*it).isNull() ? QDateTime()
02709 : QDateTime::fromString( (*it).toString(), Qt::ISODate ));
02710 ++it;
02711 info.uniqueHash = (*it).toString();
02712 ++it;
02713 }
02714
02715 return info;
02716 }
02717
02718 QStringList AlbumDB::getItemURLsInTag(int tagID, bool recursive)
02719 {
02720 QList<QVariant> values;
02721
02722 QString imagesIdClause;
02723 QList<QVariant> boundValues;
02724 if (recursive)
02725 {
02726 imagesIdClause = QString("SELECT imageid FROM ImageTags "
02727 " WHERE tagid=? "
02728 " OR tagid IN (SELECT id FROM TagsTree WHERE pid=?)");
02729 boundValues << tagID << tagID;
02730 }
02731 else
02732 {
02733 imagesIdClause = QString("SELECT imageid FROM ImageTags WHERE tagid=?");
02734 boundValues << tagID;
02735 }
02736
02737 d->db->execSql( QString("SELECT Albums.albumRoot, Albums.relativePath, Images.name "
02738 "FROM Images JOIN Albums ON Albums.id=Images.album "
02739 "WHERE Images.status=1 AND Images.id IN (%1);")
02740 .arg(imagesIdClause), boundValues, &values );
02741
02742 QStringList urls;
02743 QString albumRootPath, relativePath, name;
02744 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd();)
02745 {
02746 albumRootPath = CollectionManager::instance()->albumRootPath((*it).toInt());
02747 ++it;
02748 relativePath = (*it).toString();
02749 ++it;
02750 name = (*it).toString();
02751 ++it;
02752 if (relativePath == "/")
02753 urls << albumRootPath + relativePath + name;
02754 else
02755 urls << albumRootPath + relativePath + '/' + name;
02756 }
02757
02758 return urls;
02759 }
02760
02761 QList<qlonglong> AlbumDB::getItemIDsInTag(int tagID, bool recursive)
02762 {
02763 QList<qlonglong> itemIDs;
02764 QList<QVariant> values;
02765
02766 if (recursive)
02767 d->db->execSql( QString("SELECT imageid FROM ImageTags JOIN Images ON ImageTags.imageid=Images.id "
02768 " WHERE Images.status=1 AND "
02769 " ( tagid=? "
02770 " OR tagid IN (SELECT id FROM TagsTree WHERE pid=?) );"),
02771 tagID, tagID, &values );
02772 else
02773 d->db->execSql( QString("SELECT imageid FROM ImageTags JOIN Images ON ImageTags.imageid=Images.id "
02774 " WHERE Images.status=1 AND tagid=?;"),
02775 tagID, &values );
02776
02777 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
02778 {
02779 itemIDs << (*it).toLongLong();
02780 }
02781
02782 return itemIDs;
02783 }
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799 QString AlbumDB::getAlbumRelativePath(int albumID)
02800 {
02801 QList<QVariant> values;
02802 d->db->execSql( QString("SELECT relativePath from Albums WHERE id=?"),
02803 albumID, &values);
02804 if (!values.isEmpty())
02805 return values.first().toString();
02806 else
02807 return QString();
02808 }
02809
02810 int AlbumDB::getAlbumRootId(int albumID)
02811 {
02812 QList<QVariant> values;
02813 d->db->execSql( QString("SELECT albumRoot FROM Albums WHERE id=?; "),
02814 albumID, &values);
02815 if (!values.isEmpty())
02816 return values.first().toInt();
02817 else
02818 return -1;
02819 }
02820
02821 QDate AlbumDB::getAlbumLowestDate(int albumID)
02822 {
02823 QList<QVariant> values;
02824 d->db->execSql( "SELECT MIN(creationDate) FROM ImageInformation "
02825 " INNER JOIN Images ON Images.id=ImageInformation.imageid "
02826 " WHERE Images.album=? GROUP BY Images.album;",
02827 albumID, &values );
02828 if (!values.isEmpty())
02829 return QDate::fromString( values.first().toString(), Qt::ISODate );
02830 else
02831 return QDate();
02832 }
02833
02834 QDate AlbumDB::getAlbumHighestDate(int albumID)
02835 {
02836 QList<QVariant> values;
02837 d->db->execSql( "SELECT MAX(creationDate) FROM ImageInformation "
02838 " INNER JOIN Images ON Images.id=ImageInformation.imageid "
02839 " WHERE Images.album=? GROUP BY Images.album;",
02840 albumID , &values );
02841 if (!values.isEmpty())
02842 return QDate::fromString( values.first().toString(), Qt::ISODate );
02843 else
02844 return QDate();
02845 }
02846
02847 QDate AlbumDB::getAlbumAverageDate(int albumID)
02848 {
02849 QList<QVariant> values;
02850 d->db->execSql( "SELECT creationDate FROM ImageInformation "
02851 " INNER JOIN Images ON Images.id=ImageInformation.imageid "
02852 " WHERE Images.album=?;",
02853 albumID , &values);
02854
02855 int differenceInSecs = 0;
02856 int amountOfImages = 0;
02857 QDateTime baseDateTime;
02858
02859 for (QList<QVariant>::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
02860 {
02861 QDateTime itemDateTime = (*it).isNull() ? QDateTime()
02862 : QDateTime::fromString( (*it).toString(), Qt::ISODate );
02863 if (itemDateTime.isValid())
02864 {
02865 ++amountOfImages;
02866 if ( baseDateTime.isNull() )
02867 baseDateTime=itemDateTime;
02868 else
02869 differenceInSecs += itemDateTime.secsTo( baseDateTime );
02870 }
02871 }
02872
02873 if ( amountOfImages > 0 )
02874 {
02875 QDateTime averageDateTime;
02876 averageDateTime.setTime_t( baseDateTime.toTime_t() -
02877 (int)( differenceInSecs/amountOfImages ) );
02878 return ( averageDateTime.date() );
02879 }
02880 else
02881 return QDate();
02882 }
02883
02884 void AlbumDB::deleteItem(int albumID, const QString& file)
02885 {
02886 qlonglong imageId = getImageId(albumID, file);
02887
02888 d->db->execSql( QString("DELETE FROM Images WHERE id=?;"),
02889 imageId );
02890
02891 d->db->recordChangeset(CollectionImageChangeset(imageId, albumID, CollectionImageChangeset::Deleted));
02892 }
02893
02894 void AlbumDB::removeItemsFromAlbum(int albumID)
02895 {
02896 d->db->execSql( QString("UPDATE Images SET status=?, album=NULL WHERE album=?;"),
02897 (int)DatabaseItem::Removed, albumID );
02898
02899 d->db->recordChangeset(CollectionImageChangeset(QList<qlonglong>(), albumID, CollectionImageChangeset::RemovedAll));
02900 }
02901
02902 void AlbumDB::removeItems(QList<qlonglong> itemIDs, QList<int> albumIDs)
02903 {
02904 QSqlQuery query = d->db->prepareQuery( QString("UPDATE Images SET status=?, album=NULL WHERE id=?;") );
02905
02906 QVariantList imageIds;
02907 QVariantList status;
02908 foreach (const qlonglong& id, itemIDs)
02909 {
02910 status << (int)DatabaseItem::Removed;
02911 imageIds << id;
02912 }
02913
02914 query.addBindValue(status);
02915 query.addBindValue(imageIds);
02916 d->db->execBatch(query);
02917
02918 d->db->recordChangeset(CollectionImageChangeset(itemIDs, albumIDs, CollectionImageChangeset::Removed));
02919 }
02920
02921 void AlbumDB::deleteRemovedItems()
02922 {
02923 d->db->execSql( QString("DELETE FROM Images WHERE status=?;"),
02924 (int)DatabaseItem::Removed );
02925
02926 d->db->recordChangeset(CollectionImageChangeset(QList<qlonglong>(), QList<int>(), CollectionImageChangeset::RemovedDeleted));
02927 }
02928
02929 void AlbumDB::deleteRemovedItems(QList<int> albumIds)
02930 {
02931 QSqlQuery query = d->db->prepareQuery( QString("DELETE FROM Images WHERE status=? AND album=?;") );
02932
02933 QVariantList albumBindIds;
02934 QVariantList status;
02935 foreach(int albumId, albumIds)
02936 {
02937 status << (int)DatabaseItem::Removed;
02938 albumBindIds << albumId;
02939 }
02940
02941 query.addBindValue(status);
02942 query.addBindValue(albumBindIds);
02943 d->db->execBatch(query);
02944
02945 d->db->recordChangeset(CollectionImageChangeset(QList<qlonglong>(), albumIds, CollectionImageChangeset::RemovedDeleted));
02946 }
02947
02948 void AlbumDB::renameAlbum(int albumID, int newAlbumRoot, const QString& newRelativePath)
02949 {
02950 int albumRoot = getAlbumRootId(albumID);
02951 QString oldUrl = getAlbumRelativePath(albumID);
02952
02953 if (oldUrl == newRelativePath)
02954 return;
02955
02956
02957 d->db->execSql( QString("DELETE FROM Albums WHERE relativePath=? AND albumRoot=?;"),
02958 newRelativePath, albumRoot );
02959
02960
02961 d->db->execSql( QString("UPDATE Albums SET albumRoot=?, relativePath=? WHERE id=? AND albumRoot=?;"),
02962 newAlbumRoot, newRelativePath, albumID, albumRoot );
02963 d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::Renamed));
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988 }
02989
02990 void AlbumDB::setTagName(int tagID, const QString& name)
02991 {
02992 d->db->execSql( QString("UPDATE Tags SET name=? WHERE id=?;"),
02993 name, tagID );
02994 d->db->recordChangeset(TagChangeset(tagID, TagChangeset::Renamed));
02995 }
02996
02997 void AlbumDB::moveItem(int srcAlbumID, const QString& srcName,
02998 int dstAlbumID, const QString& dstName)
02999 {
03000
03001 qlonglong imageId = getImageId(srcAlbumID, srcName);
03002
03003 if (imageId == -1)
03004 return;
03005
03006
03007 deleteItem(dstAlbumID, dstName);
03008
03009 d->db->execSql( QString("UPDATE Images SET album=?, name=? "
03010 "WHERE id=?;"),
03011 dstAlbumID, dstName, imageId );
03012 d->db->recordChangeset(CollectionImageChangeset(imageId, srcAlbumID, CollectionImageChangeset::Moved));
03013 d->db->recordChangeset(CollectionImageChangeset(imageId, srcAlbumID, CollectionImageChangeset::Removed));
03014 d->db->recordChangeset(CollectionImageChangeset(imageId, dstAlbumID, CollectionImageChangeset::Added));
03015 }
03016
03017 int AlbumDB::copyItem(int srcAlbumID, const QString& srcName,
03018 int dstAlbumID, const QString& dstName)
03019 {
03020
03021 qlonglong srcId = getImageId(srcAlbumID, srcName);
03022
03023 if (srcId == -1 || dstAlbumID == -1 || dstName.isEmpty())
03024 return -1;
03025
03026
03027 if (srcAlbumID == dstAlbumID && srcName == dstName)
03028 return srcId;
03029
03030
03031 deleteItem(dstAlbumID, dstName);
03032
03033
03034 QVariant id;
03035 d->db->execSql ( QString ("INSERT INTO Images "
03036 " ( album, name, status, category, modificationDate, fileSize, uniqueHash ) "
03037 " SELECT ?, ?, status, category, modificationDate, fileSize, uniqueHash "
03038 " FROM Images WHERE id=?;"),
03039 dstAlbumID, dstName, srcId,
03040 0, &id);
03041
03042 if (id.isNull())
03043 return -1;
03044
03045 d->db->recordChangeset(ImageChangeset(id.toLongLong(), DatabaseFields::ImagesAll));
03046 d->db->recordChangeset(CollectionImageChangeset(id.toLongLong(), srcAlbumID, CollectionImageChangeset::Copied));
03047 d->db->recordChangeset(CollectionImageChangeset(id.toLongLong(), dstAlbumID, CollectionImageChangeset::Added));
03048
03049
03050 copyImageAttributes(srcId, id.toLongLong());
03051
03052 return id.toLongLong();
03053 }
03054
03055 void AlbumDB::copyImageAttributes(qlonglong srcId, qlonglong dstId)
03056 {
03057
03058
03059 DatabaseFields::Set fields;
03060
03061 d->db->execSql( QString("INSERT INTO ImageHaarMatrix "
03062 " (imageid, modificationDate, uniqueHash, matrix) "
03063 "SELECT ?, modificationDate, uniqueHash, matrix "
03064 "FROM ImageHaarMatrix WHERE imageid=?;"),
03065 dstId, srcId );
03066
03067 d->db->execSql( QString("INSERT INTO ImageInformation "
03068 " (imageid, rating, creationDate, digitizationDate, orientation, "
03069 " width, height, format, colorDepth, colorModel) "
03070 "SELECT ?, rating, creationDate, digitizationDate, orientation, "
03071 " width, height, format, colorDepth, colorModel "
03072 "FROM ImageInformation WHERE imageid=?;"),
03073 dstId, srcId );
03074 fields |= DatabaseFields::ImageInformationAll;
03075
03076 d->db->execSql( QString("INSERT INTO ImageMetadata "
03077 " (imageid, make, model, lens, aperture, focalLength, focalLength35, "
03078 " exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, "
03079 " whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory) "
03080 "SELECT ?, make, model, lens, aperture, focalLength, focalLength35, "
03081 " exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, "
03082 " whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory "
03083 "FROM ImageMetadata WHERE imageid=?;"),
03084 dstId, srcId );
03085 fields |= DatabaseFields::ImageMetadataAll;
03086
03087 d->db->execSql( QString("INSERT INTO ImagePositions "
03088 " (imageid, latitude, latitudeNumber, longitude, longitudeNumber, "
03089 " altitude, orientation, tilt, roll, accuracy, description) "
03090 "SELECT ?, latitude, latitudeNumber, longitude, longitudeNumber, "
03091 " altitude, orientation, tilt, roll, accuracy, description "
03092 "FROM ImagePositions WHERE imageid=?;"),
03093 dstId, srcId );
03094 fields |= DatabaseFields::ImagePositionsAll;
03095
03096 d->db->execSql( QString("INSERT INTO ImageComments "
03097 " (imageid, type, language, author, date, comment) "
03098 "SELECT ?, type, language, author, date, comment "
03099 "FROM ImageComments WHERE imageid=?;"),
03100 dstId, srcId );
03101 fields |= DatabaseFields::ImageCommentsAll;
03102
03103 d->db->execSql( QString("INSERT INTO ImageCopyright "
03104 " (imageid, property, value, extraValue) "
03105 "SELECT ?, property, value, extraValue "
03106 "FROM ImageCopyright WHERE imageid=?;"),
03107 dstId, srcId );
03108
03109 d->db->recordChangeset(ImageChangeset(dstId, fields));
03110
03111 d->db->execSql( QString("INSERT INTO ImageTags "
03112 " (imageid, tagid) "
03113 "SELECT ?, tagid "
03114 "FROM ImageTags WHERE imageid=?;"),
03115 dstId, srcId );
03116
03117 d->db->recordChangeset(ImageTagChangeset(dstId, QList<int>(), ImageTagChangeset::Added));
03118
03119 d->db->execSql( QString("INSERT INTO ImageProperties "
03120 " (imageid, property, value) "
03121 "SELECT ?, property, value "
03122 "FROM ImageProperties WHERE imageid=?;"),
03123 dstId, srcId );
03124 }
03125
03126 bool AlbumDB::copyAlbumProperties(int srcAlbumID, int dstAlbumID)
03127 {
03128 if (srcAlbumID == dstAlbumID)
03129 return true;
03130
03131 QList<QVariant> values;
03132 d->db->execSql( QString("SELECT date, caption, collection, icon "
03133 "FROM Albums WHERE id=?;"),
03134 srcAlbumID,
03135 &values );
03136
03137 if (values.isEmpty())
03138 {
03139 kWarning() << " src album ID " << srcAlbumID << " does not exist";
03140 return false;
03141 }
03142
03143 QList<QVariant> boundValues;
03144 boundValues << values[0] << values[1] << values[2] << values[3];
03145 boundValues << dstAlbumID;
03146
03147 d->db->execSql( QString("UPDATE Albums SET date=?, caption=?, "
03148 "collection=?, icon=? WHERE id=?"),
03149 boundValues );
03150 return true;
03151 }
03152
03153 }