• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

digikam

albumdb.cpp

Go to the documentation of this file.
00001 /* ============================================================
00002  *
00003  * This file is a part of digiKam project
00004  * http://www.digikam.org
00005  *
00006  * Date        : 2004-06-18
00007  * Description :database album interface.
00008  *
00009  * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
00010  * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
00011  * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
00012  *
00013  * This program is free software; you can redistribute it
00014  * and/or modify it under the terms of the GNU General
00015  * Public License as published by the Free Software Foundation;
00016  * either version 2, or (at your option)
00017  * any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * ============================================================ */
00025 
00028 // C Ansi includes.
00029 
00030 extern "C"
00031 {
00032 #include <sys/time.h>
00033 }
00034 
00035 // C++ includes.
00036 
00037 #include <cstdio>
00038 #include <cstdlib>
00039 #include <ctime>
00040 
00041 // Qt includes.
00042 
00043 #include <QFile>
00044 #include <QFileInfo>
00045 #include <QDir>
00046 
00047 // KDE includes.
00048 
00049 #include <kdebug.h>
00050 #include <klocale.h>
00051 
00052 // Local includes.
00053 
00054 #include "databasebackend.h"
00055 #include "collectionmanager.h"
00056 #include "collectionlocation.h"
00057 #include "albumdb.h"
00058 
00059 namespace Digikam
00060 {
00061 
00062 class AlbumDBPriv
00063 {
00064 
00065 public:
00066 
00067     AlbumDBPriv()
00068     {
00069         db = 0;
00070     }
00071 
00072     DatabaseBackend *db;
00073     QList<int>  recentlyAssignedTags;
00074 };
00075 
00076 AlbumDB::AlbumDB(DatabaseBackend *backend)
00077 {
00078     d = new AlbumDBPriv;
00079     d->db = backend;
00080 }
00081 
00082 AlbumDB::~AlbumDB()
00083 {
00084     delete d;
00085 }
00086 
00087 QList<AlbumRootInfo> AlbumDB::getAlbumRoots()
00088 {
00089     QList<AlbumRootInfo> list;
00090 
00091     QList<QVariant> values;
00092     d->db->execSql( "SELECT id, label, status, type, identifier, specificPath FROM AlbumRoots;", &values );
00093 
00094     for (QList<QVariant>::iterator it = values.begin(); it != values.end();)
00095     {
00096         AlbumRootInfo info;
00097         info.id           = (*it).toInt();
00098         ++it;
00099         info.label        = (*it).toString();
00100         ++it;
00101         info.status       = (*it).toInt();
00102         ++it;
00103         info.type         = (AlbumRoot::Type)(*it).toInt();
00104         ++it;
00105         info.identifier   = (*it).toString();
00106         ++it;
00107         info.specificPath = (*it).toString();
00108         ++it;
00109 
00110         list << info;
00111     }
00112 
00113     return list;
00114 }
00115 
00116 int AlbumDB::addAlbumRoot(AlbumRoot::Type type, const QString &identifier, const QString &specificPath, const QString &label)
00117 {
00118     QVariant id;
00119     d->db->execSql( QString("REPLACE INTO AlbumRoots (type, label, status, identifier, specificPath) "
00120                             "VALUES(?, ?, 0, ?, ?);"),
00121                     (int)type, label, identifier, specificPath, 0, &id);
00122 
00123     d->db->recordChangeset(AlbumRootChangeset(id.toInt(), AlbumRootChangeset::Added));
00124     return id.toInt();
00125 }
00126 
00127 void AlbumDB::deleteAlbumRoot(int rootId)
00128 {
00129     d->db->execSql( QString("DELETE FROM AlbumRoots WHERE id=?;"),
00130                     rootId );
00131     d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::Deleted));
00132 }
00133 
00134 void AlbumDB::setAlbumRootLabel(int rootId, const QString &newLabel)
00135 {
00136     d->db->execSql( QString("UPDATE AlbumRoots SET label=? WHERE id=?;"),
00137                     newLabel, rootId);
00138     d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::PropertiesChanged));
00139 }
00140 
00141 void AlbumDB::changeAlbumRootType(int rootId, AlbumRoot::Type newType)
00142 {
00143     d->db->execSql( QString("UPDATE AlbumRoots SET type=? WHERE id=?;"),
00144                     (int)newType, rootId);
00145     d->db->recordChangeset(AlbumRootChangeset(rootId, AlbumRootChangeset::PropertiesChanged));
00146 }
00147 
00148 
00149 
00150 AlbumInfo::List AlbumDB::scanAlbums()
00151 {
00152     AlbumInfo::List aList;
00153 
00154     QList<QVariant> values;
00155     d->db->execSql( "SELECT A.albumRoot, A.id, A.relativePath, A.date, A.caption, A.collection, B.albumRoot, B.relativePath, I.name \n "
00156                     "FROM Albums AS A \n "
00157                     "  LEFT OUTER JOIN Images AS I ON A.icon=I.id \n"
00158                     "  LEFT OUTER JOIN Albums AS B ON B.id=I.album \n"
00159                     " WHERE A.albumRoot != 0;", // exclude stale albums
00160                     &values);
00161 
00162     QString iconAlbumUrl, iconName;
00163 
00164     for (QList<QVariant>::iterator it = values.begin(); it != values.end();)
00165     {
00166         AlbumInfo info;
00167 
00168         info.albumRootId = (*it).toInt();
00169         ++it;
00170         info.id = (*it).toInt();
00171         ++it;
00172         info.relativePath = (*it).toString();
00173         ++it;
00174         info.date = QDate::fromString((*it).toString(), Qt::ISODate);
00175         ++it;
00176         info.caption = (*it).toString();
00177         ++it;
00178         info.collection = (*it).toString();
00179         ++it;
00180         info.iconAlbumRootId = (*it).toInt(); // will be 0 if null
00181         ++it;
00182         iconAlbumUrl = (*it).toString();
00183         ++it;
00184         iconName = (*it).toString();
00185         ++it;
00186 
00187         if (!iconName.isEmpty())
00188             info.iconRelativePath = iconAlbumUrl + '/' + iconName;
00189 
00190         aList.append(info);
00191     }
00192 
00193     return aList;
00194 }
00195 
00196 TagInfo::List AlbumDB::scanTags()
00197 {
00198     TagInfo::List tList;
00199 
00200     QList<QVariant> values;
00201     d->db->execSql( "SELECT T.id, T.pid, T.name, A.relativePath, I.name, T.iconkde, A.albumRoot \n "
00202                     "FROM Tags AS T \n"
00203                     "  LEFT OUTER JOIN Images AS I ON I.id=T.icon \n "
00204                     "  LEFT OUTER JOIN Albums AS A ON A.id=I.album; ", &values );
00205 
00206     QString iconName, iconKDE, albumURL;
00207     int iconAlbumRootId;
00208 
00209     for (QList<QVariant>::iterator it = values.begin(); it != values.end();)
00210     {
00211         TagInfo info;
00212 
00213         info.id     = (*it).toInt();
00214         ++it;
00215         info.pid    = (*it).toInt();
00216         ++it;
00217         info.name   = (*it).toString();
00218         ++it;
00219         albumURL    = (*it).toString();
00220         ++it;
00221         iconName    = (*it).toString();
00222         ++it;
00223         iconKDE     = (*it).toString();
00224         ++it;
00225         iconAlbumRootId = (*it).toInt(); // will be 0 if null
00226         ++it;
00227 
00228         if (albumURL.isEmpty())
00229         {
00230             info.icon = iconKDE;
00231         }
00232         else
00233         {
00234             info.iconAlbumRootId  = iconAlbumRootId;
00235             info.iconRelativePath = albumURL + '/' + iconName;
00236         }
00237 
00238         tList.append(info);
00239     }
00240 
00241     return tList;
00242 }
00243 
00244 SearchInfo::List AlbumDB::scanSearches()
00245 {
00246     SearchInfo::List searchList;
00247 
00248     QList<QVariant> values;
00249     d->db->execSql( "SELECT id, type, name, query FROM Searches;", &values);
00250 
00251     for (QList<QVariant>::iterator it = values.begin(); it != values.end();)
00252     {
00253         SearchInfo info;
00254 
00255         info.id    = (*it).toInt();
00256         ++it;
00257         info.type  = (DatabaseSearch::Type)(*it).toInt();
00258         ++it;
00259         info.name  = (*it).toString();
00260         ++it;
00261         info.query = (*it).toString();
00262         ++it;
00263 
00264         searchList.append(info);
00265     }
00266 
00267     return searchList;
00268 }
00269 
00270 QList<AlbumShortInfo> AlbumDB::getAlbumShortInfos()
00271 {
00272     QList<QVariant> values;
00273     d->db->execSql( QString("SELECT Albums.id, Albums.relativePath, Albums.albumRoot from Albums; "),
00274                     &values);
00275 
00276     QList<AlbumShortInfo> albumList;
00277 
00278     for (QList<QVariant>::iterator it = values.begin(); it != values.end();)
00279     {
00280         AlbumShortInfo info;
00281 
00282         info.id           = (*it).toLongLong();
00283         ++it;
00284         info.relativePath = (*it).toString();
00285         ++it;
00286         info.albumRootId  = (*it).toInt();
00287         ++it;
00288 
00289         albumList << info;
00290     }
00291 
00292     return albumList;
00293 }
00294 
00295 /*
00296 QStringList AlbumDB::getSubalbumsForPath(const QString &albumRoot,
00297                                          const QString& path,
00298                                          bool onlyDirectSubalbums)
00299 {
00300     CollectionLocation location = CollectionManager::instance()->locationForAlbumRootPath(albumRoot);
00301     if (location.isNull())
00302         return QStringList();
00303 
00304     QString subURL = path;
00305     if (!path.endsWith("/"))
00306         subURL += '/';
00307     subURL = (subURL);
00308 
00309     QList<QVariant> values;
00310 
00311     if (onlyDirectSubalbums)
00312     {
00313         d->db->execSql( QString("SELECT relativePath FROM Albums WHERE albumRoot=? AND relativePath LIKE '") +
00314                         subURL + QString("%' ") + QString("AND relativePath NOT LIKE '") +
00315                         subURL + QString("%/%'; "),
00316                         location.id(),
00317                         &values );
00318     }
00319     else
00320     {
00321         d->db->execSql( QString("SELECT relativePath FROM Albums WHERE albumRoot=? AND relativePath LIKE '") +
00322                         subURL + QString("%'; "),
00323                         location.id(),
00324                         &values );
00325     }
00326 
00327     QStringList subalbums;
00328     QString albumRootPath = location.albumRootPath();
00329     for (QList<QVariant>::iterator it = values.begin(); it != values.end(); ++it)
00330         subalbums << albumRootPath + it->toString();
00331     return subalbums;
00332 }
00333 */
00334 
00335 /*
00336 int AlbumDB::addAlbum(const QString &albumRoot, const QString& relativePath,
00337                       const QString& caption,
00338                       const QDate& date, const QString& collection)
00339 {
00340     CollectionLocation location = CollectionManager::instance()->locationForAlbumRootPath(albumRoot);
00341     if (location.isNull())
00342         return -1;
00343 
00344     return addAlbum(location.id(), relativePath, caption, date, collection);
00345 }
00346 */
00347 
00348 int AlbumDB::addAlbum(int albumRootId, const QString& relativePath,
00349                       const QString& caption,
00350                       const QDate& date, const QString& collection)
00351 {
00352     QVariant id;
00353     QList<QVariant> boundValues;
00354     boundValues << albumRootId << relativePath << date.toString(Qt::ISODate) << caption << collection;
00355 
00356     d->db->execSql( QString("REPLACE INTO Albums (albumRoot, relativePath, date, caption, collection) "
00357                             "VALUES(?, ?, ?, ?, ?);"),
00358                     boundValues, 0, &id);
00359 
00360     d->db->recordChangeset(AlbumChangeset(id.toInt(), AlbumChangeset::Added));
00361     return id.toInt();
00362 }
00363 
00364 void AlbumDB::setAlbumCaption(int albumID, const QString& caption)
00365 {
00366     d->db->execSql( QString("UPDATE Albums SET caption=? WHERE id=?;"),
00367                     caption, albumID );
00368     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00369 }
00370 
00371 void AlbumDB::setAlbumCollection(int albumID, const QString& collection)
00372 {
00373     d->db->execSql( QString("UPDATE Albums SET collection=? WHERE id=?;"),
00374                     collection, albumID );
00375     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00376 }
00377 
00378 void AlbumDB::setAlbumDate(int albumID, const QDate& date)
00379 {
00380     d->db->execSql( QString("UPDATE Albums SET date=? WHERE id=?;"),
00381                     date.toString(Qt::ISODate),
00382                     albumID );
00383     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00384 }
00385 
00386 void AlbumDB::setAlbumIcon(int albumID, qlonglong iconID)
00387 {
00388     d->db->execSql( QString("UPDATE Albums SET icon=? WHERE id=?;"),
00389                     iconID,
00390                     albumID );
00391     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::PropertiesChanged));
00392 }
00393 
00394 bool AlbumDB::getAlbumIcon(int albumID, int *albumRootId, QString *iconRelativePath)
00395 {
00396     QList<QVariant> values;
00397     d->db->execSql( QString("SELECT B.relativePath, I.name, B.albumRoot \n "
00398                             "FROM Albums AS A \n "
00399                             "  LEFT OUTER JOIN Images AS I ON I.id=A.icon \n "
00400                             "  LEFT OUTER JOIN Albums AS B ON B.id=I.album \n "
00401                             "WHERE A.id=?;"),
00402                     albumID, &values );
00403     if (values.isEmpty())
00404         return false;
00405 
00406     QList<QVariant>::iterator it = values.begin();
00407     QString album     = (*it).toString();
00408     ++it;
00409     QString iconName  = (*it).toString();
00410     ++it;
00411     *albumRootId = (*it).toInt();
00412 
00413     *iconRelativePath = album + '/' + iconName;
00414 
00415     return !iconName.isEmpty();
00416 }
00417 
00418 void AlbumDB::deleteAlbum(int albumID)
00419 {
00420     d->db->execSql( QString("DELETE FROM Albums WHERE id=?;"),
00421                     albumID );
00422     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::Deleted));
00423 }
00424 
00425 void AlbumDB::makeStaleAlbum(int albumID)
00426 {
00427     // We need to work around the table constraint, no we want to delete older stale albums with
00428     // the same relativePath, and adjust relativePaths depending on albumRoot.
00429     QList<QVariant> values;
00430 
00431     // retrieve information
00432     d->db->execSql( QString("SELECT Albums.albumRoot, Albums.relativePath from Albums WHERE id=?;"),
00433                     albumID, &values);
00434 
00435     if (values.isEmpty())
00436         return;
00437 
00438     // prepend albumRootId to relativePath. relativePath is unused and officially undefined after this call.
00439     QString newRelativePath = values[0].toString() + '-' + values[1].toString();
00440 
00441     // delete older stale albums
00442     d->db->execSql( QString("DELETE FROM Albums WHERE albumRoot=0 AND relativePath=?;"),
00443                     newRelativePath );
00444 
00445     // now do our update
00446     d->db->execSql( QString("UPDATE Albums SET albumRoot=0, relativePath=? WHERE id=?;"),
00447                     newRelativePath, albumID );
00448 
00449     // for now, we make no distinction to deleteAlbums wrt to changeset
00450     d->db->recordChangeset(AlbumChangeset(albumID, AlbumChangeset::Deleted));
00451 }
00452 
00453 void AlbumDB::deleteStaleAlbums()
00454 {
00455     d->db->execSql( QString("DELETE FROM Albums WHERE albumRoot=0;") );
00456     // deliberately no changeset here, is done above
00457 }
00458 
00459 int AlbumDB::addTag(int parentTagID, const QString& name, const QString& iconKDE,
00460                     qlonglong iconID)
00461 {
00462     QVariant id;
00463     if (!d->db->execSql( QString("INSERT INTO Tags (pid, name) "
00464                                  "VALUES( ?, ?);"),
00465                          parentTagID,
00466                          name,
00467                          0, &id) )
00468     {
00469         return -1;
00470     }
00471 
00472     if (!iconKDE.isEmpty())
00473     {
00474         d->db->execSql( QString("UPDATE Tags SET iconkde=? WHERE id=?;"),
00475                         iconKDE,
00476                         id.toInt() );
00477     }
00478     else
00479     {
00480         d->db->execSql( QString("UPDATE Tags SET icon=? WHERE id=?;"),
00481                         iconID,
00482                         id.toInt());
00483     }
00484 
00485     d->db->recordChangeset(TagChangeset(id.toInt(), TagChangeset::Added));
00486     return id.toInt();
00487 }
00488 
00489 void AlbumDB::deleteTag(int tagID)
00490 {
00491     d->db->execSql( QString("DELETE FROM Tags WHERE id=?;"),
00492                     tagID );
00493     d->db->recordChangeset(TagChangeset(tagID, TagChangeset::Deleted));
00494 }
00495 
00496 void AlbumDB::setTagIcon(int tagID, const QString& iconKDE, qlonglong iconID)
00497 {
00498     if (!iconKDE.isEmpty())
00499     {
00500         d->db->execSql( QString("UPDATE Tags SET iconkde=?, icon=0 WHERE id=?;"),
00501                         iconKDE, tagID );
00502     }
00503     else
00504     {
00505         d->db->execSql( QString("UPDATE Tags SET icon=? WHERE id=?;"),
00506                         iconID, tagID );
00507     }
00508     d->db->recordChangeset(TagChangeset(tagID, TagChangeset::IconChanged));
00509 }
00510 
00511 bool AlbumDB::getTagIcon(int tagID, int *iconAlbumRootId, QString *iconAlbumRelativePath, QString *icon)
00512 {
00513     QList<QVariant> values;
00514     d->db->execSql( QString("SELECT A.relativePath, I.name, T.iconkde, A.albumRoot \n "
00515                             "FROM Tags AS T \n "
00516                             "  LEFT OUTER JOIN Images AS I ON I.id=T.icon \n "
00517                             "  LEFT OUTER JOIN Albums AS A ON A.id=I.album \n "
00518                             "WHERE T.id=?;"),
00519                     tagID, &values );
00520 
00521     if (values.isEmpty())
00522         return false;
00523 
00524     QString iconName, iconKDE, albumURL;
00525 
00526     QList<QVariant>::iterator it = values.begin();
00527 
00528     albumURL    = (*it).toString();
00529     ++it;
00530     iconName    = (*it).toString();
00531     ++it;
00532     iconKDE     = (*it).toString();
00533     ++it;
00534 
00535     *iconAlbumRootId = (*it).toInt();
00536     ++it;
00537 
00538     if (albumURL.isEmpty())
00539     {
00540         *iconAlbumRelativePath = QString();
00541         *icon = iconKDE;
00542         return !iconKDE.isEmpty();
00543     }
00544     else
00545     {
00546         *iconAlbumRelativePath = albumURL + '/' + iconName;
00547         *icon = QString();
00548         return true;
00549     }
00550 }
00551 
00552 void AlbumDB::setTagParentID(int tagID, int newParentTagID)
00553 {
00554     d->db->execSql( QString("UPDATE Tags SET pid=? WHERE id=?;"),
00555                     newParentTagID, tagID );
00556     d->db->recordChangeset(TagChangeset(tagID, TagChangeset::Reparented));
00557 }
00558 
00559 int AlbumDB::addSearch(DatabaseSearch::Type type, const QString& name, const QString &query)
00560 {
00561     QVariant id;
00562     if (!d->db->execSql(QString("INSERT INTO Searches (type, name, query) VALUES(?, ?, ?);"),
00563                         type, name, query, 0, &id) )
00564     {
00565         return -1;
00566     }
00567 
00568     d->db->recordChangeset(SearchChangeset(id.toInt(), SearchChangeset::Added));
00569     return id.toInt();
00570 }
00571 
00572 void AlbumDB::updateSearch(int searchID, DatabaseSearch::Type type,
00573                            const QString& name, const QString &query)
00574 {
00575     d->db->execSql(QString("UPDATE Searches SET type=?, name=?, query=? WHERE id=?"),
00576                    type, name, query, searchID);
00577     d->db->recordChangeset(SearchChangeset(searchID, SearchChangeset::Changed));
00578 }
00579 
00580 void AlbumDB::deleteSearch(int searchID)
00581 {
00582     d->db->execSql( QString("DELETE FROM Searches WHERE id=?"),
00583                     searchID );
00584     d->db->recordChangeset(SearchChangeset(searchID, SearchChangeset::Deleted));
00585 }
00586 
00587 void AlbumDB::deleteSearches(DatabaseSearch::Type type)
00588 {
00589     d->db->execSql( QString("DELETE FROM Searches WHERE type=?"),
00590                     type );
00591     d->db->recordChangeset(SearchChangeset(0, SearchChangeset::Deleted));
00592 }
00593 
00594 QString AlbumDB::getSearchQuery(int searchId)
00595 {
00596     QList<QVariant> values;
00597     d->db->execSql( QString("SELECT query FROM Searches WHERE id=?;"),
00598                     searchId, &values );
00599 
00600     if (values.isEmpty())
00601         return QString();
00602     else
00603         return values.first().toString();
00604 }
00605 
00606 SearchInfo AlbumDB::getSearchInfo(int searchId)
00607 {
00608     SearchInfo info;
00609 
00610     QList<QVariant> values;
00611     d->db->execSql( "SELECT id, type, name, query FROM Searches WHERE id=?;",
00612                     searchId, &values);
00613 
00614     if (values.size() == 4)
00615     {
00616         QList<QVariant>::iterator it = values.begin();
00617         info.id    = (*it).toInt();
00618         ++it;
00619         info.type  = (DatabaseSearch::Type)(*it).toInt();
00620         ++it;
00621         info.name  = (*it).toString();
00622         ++it;
00623         info.query = (*it).toString();
00624         ++it;
00625     }
00626 
00627     return info;
00628 }
00629 
00630 void AlbumDB::setSetting(const QString& keyword,
00631                          const QString& value )
00632 {
00633     d->db->execSql( QString("REPLACE into Settings VALUES (?,?);"),
00634                     keyword, value );
00635 }
00636 
00637 QString AlbumDB::getSetting(const QString& keyword)
00638 {
00639     QList<QVariant> values;
00640     d->db->execSql( QString("SELECT value FROM Settings "
00641                             "WHERE keyword=?;"),
00642                     keyword, &values );
00643 
00644     if (values.isEmpty())
00645         return QString();
00646     else
00647         return values.first().toString();
00648 }
00649 
00650 // helper method
00651 static QStringList joinMainAndUserFilterString(const QString &filter, const QString &userFilter)
00652 {
00653     QSet<QString> filterSet;
00654     QStringList userFilterList;
00655 
00656     filterSet = filter.split(';', QString::SkipEmptyParts).toSet();
00657     userFilterList = userFilter.split(';', QString::SkipEmptyParts);
00658     foreach (const QString &userFormat, userFilterList)
00659     {
00660         if (userFormat.startsWith('-'))
00661             filterSet.remove(userFormat.mid(1));
00662         else
00663             filterSet << userFormat;
00664     }
00665     return filterSet.toList();
00666 }
00667 
00668 void AlbumDB::getFilterSettings(QStringList *imageFilter, QStringList *videoFilter, QStringList *audioFilter)
00669 {
00670     QString imageFormats, videoFormats, audioFormats, userImageFormats, userVideoFormats, userAudioFormats;
00671 
00672     if (imageFilter)
00673     {
00674         imageFormats = getSetting("databaseImageFormats");
00675         userImageFormats = getSetting("databaseUserImageFormats");
00676         *imageFilter = joinMainAndUserFilterString(imageFormats, userImageFormats);
00677     }
00678 
00679     if (videoFilter)
00680     {
00681         videoFormats = getSetting("databaseVideoFormats");
00682         userVideoFormats = getSetting("databaseUserVideoFormats");
00683         *videoFilter = joinMainAndUserFilterString(videoFormats, userVideoFormats);
00684     }
00685 
00686     if (audioFilter)
00687     {
00688         audioFormats = getSetting("databaseAudioFormats");
00689         userAudioFormats = getSetting("databaseUserAudioFormats");
00690         *audioFilter = joinMainAndUserFilterString(audioFormats, userAudioFormats);
00691     }
00692 }
00693 
00694 void AlbumDB::getUserFilterSettings(QString *imageFilterString, QString *videoFilterString, QString *audioFilterString)
00695 {
00696     if (imageFilterString)
00697         *imageFilterString = getSetting("databaseUserImageFormats");
00698     if (videoFilterString)
00699         *videoFilterString = getSetting("databaseUserVideoFormats");
00700     if (audioFilterString)
00701         *audioFilterString = getSetting("databaseUserAudioFormats");
00702 }
00703 
00704 void AlbumDB::setFilterSettings(const QStringList &imageFilter, const QStringList &videoFilter, const QStringList &audioFilter)
00705 {
00706     setSetting("databaseImageFormats", imageFilter.join(";"));
00707     setSetting("databaseVideoFormats", videoFilter.join(";"));
00708     setSetting("databaseAudioFormats", audioFilter.join(";"));
00709 }
00710 
00711 // helper method
00712 static QStringList cleanUserFilterString(const QString &filterString)
00713 {
00714     // splits by either ; or space, removes "*.", trims
00715     QStringList filterList;
00716 
00717     QString wildcard("*.");
00718     QString minusWildcard("-*.");
00719     QChar dot('.');
00720     QString minusDot("-.");
00721     QChar sep( ';' );
00722     int i = filterString.indexOf( sep );
00723     if ( i == -1 && filterString.indexOf( ' ') != -1 )
00724         sep = QChar( ' ' );
00725 
00726     QStringList sepList = filterString.split(sep, QString::SkipEmptyParts);
00727     foreach (const QString &f, sepList)
00728     {
00729         if (f.startsWith(wildcard))
00730             filterList << f.mid(2).trimmed().toLower();
00731         else if (f.startsWith(minusWildcard))
00732             filterList << '-' + f.mid(3).trimmed().toLower();
00733         else if (f.startsWith(dot))
00734             filterList << f.mid(1).trimmed().toLower();
00735         else if (f.startsWith(minusDot))
00736             filterList << '-' + f.mid(2).trimmed().toLower();
00737         else
00738             filterList << f.trimmed().toLower();
00739     }
00740     return filterList;
00741 }
00742 
00743 void AlbumDB::setUserFilterSettings(const QString &imageFilterString, const QString &videoFilterString, const QString &audioFilterString)
00744 {
00745     setUserFilterSettings(cleanUserFilterString(imageFilterString),
00746                           cleanUserFilterString(videoFilterString),
00747                           cleanUserFilterString(audioFilterString));
00748 }
00749 
00750 void AlbumDB::setUserFilterSettings(const QStringList &imageFilter, const QStringList &videoFilter, const QStringList &audioFilter)
00751 {
00752     setSetting("databaseUserImageFormats", imageFilter.join(";"));
00753     setSetting("databaseUserVideoFormats", videoFilter.join(";"));
00754     setSetting("databaseUserAudioFormats", audioFilter.join(";"));
00755 }
00756 
00757 void AlbumDB::addToUserImageFilterSettings(const QString &filterString)
00758 {
00759     QStringList addList = cleanUserFilterString(filterString);
00760 
00761     QStringList currentList = getSetting("databaseUserImageFormats").split(';', QString::SkipEmptyParts);
00762 
00763     // merge lists
00764     foreach(const QString &addedFilter, addList)
00765     {
00766         if (!currentList.contains(addedFilter))
00767             currentList << addedFilter;
00768     }
00769 
00770     setSetting("databaseUserImageFormats", currentList.join(";"));
00771 }
00772 
00773 QUuid AlbumDB::databaseUuid()
00774 {
00775     QString uuidString = getSetting("databaseUUID");
00776     QUuid uuid = QUuid(uuidString);
00777     if (uuidString.isNull() || uuid.isNull())
00778     {
00779         uuid = QUuid::createUuid();
00780         setSetting("databaseUUID", uuid.toString());
00781     }
00782     return uuid;
00783 }
00784 
00785 /*
00786 QString AlbumDB::getItemCaption(qlonglong imageID)
00787 {
00788     QList<QVariant> values;
00789 
00790     d->db->execSql( QString("SELECT caption FROM Images "
00791                             "WHERE id=?;"),
00792                     imageID, &values );
00793 
00794     if (!values.isEmpty())
00795         return values.first().toString();
00796     else
00797         return QString();
00798 }
00799 
00800 QString AlbumDB::getItemCaption(int albumID, const QString& name)
00801 {
00802     QList<QVariant> values;
00803 
00804     d->db->execSql( QString("SELECT caption FROM Images "
00805                             "WHERE dirid=? AND name=?;"),
00806                     albumID,
00807                     name,
00808                     &values );
00809 
00810     if (!values.isEmpty())
00811         return values.first().toString();
00812     else
00813         return QString();
00814 }
00815 
00816 
00817 QDateTime AlbumDB::getItemDate(qlonglong imageID)
00818 {
00819     QList<QVariant> values;
00820 
00821     d->db->execSql( QString("SELECT datetime FROM Images "
00822                             "WHERE id=?;"),
00823                     imageID,
00824                     &values );
00825 
00826     if (!values.isEmpty())
00827         return QDateTime::fromString(values.first().toString(), Qt::ISODate);
00828     else
00829         return QDateTime();
00830 }
00831 
00832 QDateTime AlbumDB::getItemDate(int albumID, const QString& name)
00833 {
00834     QList<QVariant> values;
00835 
00836     d->db->execSql( QString("SELECT datetime FROM Images "
00837                             "WHERE dirid=? AND name=?;"),
00838                     albumID,
00839                     name,
00840                     &values );
00841 
00842     if (values.isEmpty())
00843         return QDateTime::fromString(values.first().toString(), Qt::ISODate);
00844     else
00845         return QDateTime();
00846 }
00847 */
00848 
00849 qlonglong AlbumDB::getImageId(int albumID, const QString& name)
00850 {
00851     QList<QVariant> values;
00852 
00853     d->db->execSql( QString("SELECT id FROM Images "
00854                             "WHERE album=? AND name=?;"),
00855                     albumID,
00856                     name,
00857                     &values );
00858 
00859     if (values.isEmpty())
00860         return -1;
00861     else
00862         return values.first().toLongLong();
00863 }
00864 
00865 QStringList AlbumDB::getItemTagNames(qlonglong imageID)
00866 {
00867     QList<QVariant> values;
00868 
00869     d->db->execSql( QString("SELECT name FROM Tags \n "
00870                             "WHERE id IN (SELECT tagid FROM ImageTags \n "
00871                             "             WHERE imageid=?) \n "
00872                             "ORDER BY name;"),
00873                     imageID,
00874                     &values );
00875 
00876     QStringList names;
00877     for (QList<QVariant>::iterator it = values.begin(); it != values.end(); ++it)
00878         names << it->toString();
00879     return names;
00880 }
00881 
00882 QList<int> AlbumDB::getItemTagIDs(qlonglong imageID)
00883 {
00884     QList<QVariant> values;
00885 
00886     d->db->execSql( QString("SELECT tagid FROM ImageTags \n "
00887                             "WHERE imageID=?;"),
00888                     imageID,
00889                     &values );
00890 
00891     QList<int> ids;
00892 
00893     if (values.isEmpty())
00894         return ids;
00895 
00896     for (QList<QVariant>::iterator it=values.begin(); it != values.end(); ++it)
00897         ids << it->toInt();
00898     return ids;
00899 }
00900 
00901 ItemShortInfo AlbumDB::getItemShortInfo(qlonglong imageID)
00902 {
00903     QList<QVariant> values;
00904 
00905     d->db->execSql( QString("SELECT Images.name, Albums.albumRoot, Albums.relativePath, Albums.id "
00906                             "FROM Images "
00907                             "  LEFT OUTER JOIN Albums ON Albums.id=Images.album "
00908                             "WHERE Images.id=?;"),
00909                     imageID,
00910                     &values );
00911 
00912     ItemShortInfo info;
00913 
00914     if (!values.isEmpty())
00915     {
00916         info.id          = imageID;
00917         info.itemName    = values[0].toString();
00918         info.albumRootID = values[1].toInt();
00919         info.album       = values[2].toString();
00920         info.albumID     = values[3].toInt();
00921     }
00922 
00923     return info;
00924 }
00925 
00926 bool AlbumDB::hasTags(const QList<qlonglong>& imageIDList)
00927 {
00928     QList<int> ids;
00929 
00930     if (imageIDList.isEmpty())
00931         return false;
00932 
00933     QList<QVariant> values;
00934     QList<QVariant> boundValues;
00935 
00936     QString sql = QString("SELECT count(tagid) FROM ImageTags "
00937                           "WHERE imageid=? ");
00938     boundValues << imageIDList.first();
00939 
00940     QList<qlonglong>::const_iterator it = imageIDList.begin();
00941     ++it;
00942     for (; it != imageIDList.end(); ++it)
00943     {
00944         sql += QString(" OR imageid=? ");
00945         boundValues << (*it);
00946     }
00947 
00948     sql += QString(";");
00949     d->db->execSql( sql, boundValues, &values );
00950 
00951     if (values.isEmpty() || values.first().toInt() == 0)
00952         return false;
00953     else
00954         return true;
00955 }
00956 
00957 QList<int> AlbumDB::getItemCommonTagIDs(const QList<qlonglong>& imageIDList)
00958 {
00959     QList<int> ids;
00960 
00961     if (imageIDList.isEmpty())
00962         return ids;
00963 
00964     QList<QVariant> values;
00965     QList<QVariant> boundValues;
00966 
00967     QString sql = QString("SELECT DISTINCT tagid FROM ImageTags "
00968                           "WHERE imageid=? ");
00969     boundValues << imageIDList.first();
00970 
00971     QList<qlonglong>::const_iterator it = imageIDList.begin();
00972     ++it;
00973     for (; it != imageIDList.end(); ++it)
00974     {
<