You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
859 lines
26 KiB
859 lines
26 KiB
/* ============================================================
|
|
*
|
|
* This file is a part of digiKam project
|
|
* http://www.digikam.org
|
|
*
|
|
* Date : 2007-01-05
|
|
* Description : Metadata handling
|
|
*
|
|
* Copyright (C) 2007-2009 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
|
|
* Copyright (C) 2007-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
*
|
|
* This program is free software you can redistribute it
|
|
* and/or modify it under the terms of the GNU General
|
|
* Public License as published by the Free Software Foundation
|
|
* either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* ============================================================ */
|
|
|
|
// TQt includes.
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
// KDE includes.
|
|
|
|
// Local includes.
|
|
|
|
#include "ddebug.h"
|
|
#include "imageinfo.h"
|
|
#include "album.h"
|
|
#include "albummanager.h"
|
|
#include "albumsettings.h"
|
|
#include "imageattributeswatch.h"
|
|
#include "metadatahub.h"
|
|
|
|
namespace Digikam
|
|
{
|
|
|
|
class MetadataHubPriv
|
|
{
|
|
public:
|
|
|
|
MetadataHubPriv()
|
|
{
|
|
dateTimeStatus = MetadataHub::MetadataInvalid;
|
|
ratingStatus = MetadataHub::MetadataInvalid;
|
|
commentStatus = MetadataHub::MetadataInvalid;
|
|
|
|
rating = -1;
|
|
highestRating = -1;
|
|
|
|
count = 0;
|
|
|
|
dbmode = MetadataHub::ManagedTags;
|
|
|
|
dateTimeChanged = false;
|
|
commentChanged = false;
|
|
ratingChanged = false;
|
|
tagsChanged = false;
|
|
}
|
|
|
|
MetadataHub::Status dateTimeStatus;
|
|
MetadataHub::Status commentStatus;
|
|
MetadataHub::Status ratingStatus;
|
|
|
|
TQDateTime dateTime;
|
|
TQDateTime lastDateTime;
|
|
TQString comment;
|
|
int rating;
|
|
int highestRating;
|
|
|
|
int count;
|
|
|
|
TQMap<TAlbum *, MetadataHub::TagStatus> tags;
|
|
TQStringList tagList;
|
|
|
|
MetadataHub::DatabaseMode dbmode;
|
|
|
|
bool dateTimeChanged;
|
|
bool commentChanged;
|
|
bool ratingChanged;
|
|
bool tagsChanged;
|
|
|
|
template <class T> void loadWithInterval(const T &data, T &storage, T &highestStorage, MetadataHub::Status &status);
|
|
template <class T> void loadSingleValue(const T &data, T &storage, MetadataHub::Status &status);
|
|
};
|
|
|
|
MetadataWriteSettings::MetadataWriteSettings()
|
|
{
|
|
saveComments = false;
|
|
saveDateTime = false;
|
|
saveRating = false;
|
|
saveIptcTags = false;
|
|
saveIptcPhotographerId = false;
|
|
saveIptcCredits = false;
|
|
}
|
|
|
|
MetadataWriteSettings::MetadataWriteSettings(AlbumSettings *albumSettings)
|
|
{
|
|
saveComments = albumSettings->getSaveComments();
|
|
saveDateTime = albumSettings->getSaveDateTime();
|
|
saveRating = albumSettings->getSaveRating();
|
|
saveIptcTags = albumSettings->getSaveIptcTags();
|
|
saveIptcPhotographerId = albumSettings->getSaveIptcPhotographerId();
|
|
saveIptcCredits = albumSettings->getSaveIptcCredits();
|
|
|
|
iptcAuthor = albumSettings->getIptcAuthor();
|
|
iptcAuthorTitle = albumSettings->getIptcAuthorTitle();
|
|
iptcCredit = albumSettings->getIptcCredit();
|
|
iptcSource = albumSettings->getIptcSource();
|
|
iptcCopyright = albumSettings->getIptcCopyright();
|
|
}
|
|
|
|
MetadataHub::MetadataHub(DatabaseMode dbmode)
|
|
{
|
|
d = new MetadataHubPriv;
|
|
d->dbmode = dbmode;
|
|
}
|
|
|
|
MetadataHub::~MetadataHub()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
MetadataHub::MetadataHub(const MetadataHub &other)
|
|
{
|
|
d = new MetadataHubPriv(*other.d);
|
|
}
|
|
|
|
MetadataHub &MetadataHub::operator=(const MetadataHub &other)
|
|
{
|
|
(*d) = (*other.d);
|
|
return *this;
|
|
}
|
|
|
|
void MetadataHub::reset()
|
|
{
|
|
(*d) = MetadataHubPriv();
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
|
|
void MetadataHub::load(ImageInfo *info)
|
|
{
|
|
d->count++;
|
|
|
|
load(info->dateTime(), info->caption(), info->rating());
|
|
|
|
AlbumManager *man = AlbumManager::instance();
|
|
TQValueList<int> tagIDs = info->tagIDs();
|
|
TQValueList<TAlbum *> loadedTags;
|
|
|
|
if (d->dbmode == ManagedTags)
|
|
{
|
|
TQValueList<TAlbum *> loadedTags;
|
|
for (TQValueList<int>::iterator it = tagIDs.begin(); it != tagIDs.end(); ++it)
|
|
{
|
|
TAlbum *album = man->findTAlbum(*it);
|
|
if (!album)
|
|
{
|
|
DWarning() << k_funcinfo << "Tag id " << *it << " not found in database." << endl;
|
|
continue;
|
|
}
|
|
loadedTags.append(album);
|
|
}
|
|
|
|
loadTags(loadedTags);
|
|
}
|
|
else
|
|
{
|
|
loadTags(info->tagPaths(false));
|
|
}
|
|
}
|
|
|
|
void MetadataHub::load(const DMetadata &metadata)
|
|
{
|
|
d->count++;
|
|
|
|
TQString comment;
|
|
TQStringList keywords;
|
|
TQDateTime datetime;
|
|
int rating;
|
|
|
|
// Try to get comments from image :
|
|
// In first, from standard JPEG comments, or
|
|
// In second, from EXIF comments tag, or
|
|
// In third, from IPTC comments tag.
|
|
|
|
comment = metadata.getImageComment();
|
|
|
|
// Try to get date and time from image :
|
|
// In first, from EXIF date & time tags, or
|
|
// In second, from IPTC date & time tags.
|
|
|
|
datetime = metadata.getImageDateTime();
|
|
|
|
// Try to get image rating from IPTC Urgency tag
|
|
// else use file system time stamp.
|
|
rating = metadata.getImageRating();
|
|
|
|
if ( !datetime.isValid() )
|
|
{
|
|
TQFileInfo info( metadata.getFilePath() );
|
|
datetime = info.lastModified();
|
|
}
|
|
|
|
load(datetime, comment, rating);
|
|
|
|
// Try to get image tags from IPTC keywords tags.
|
|
|
|
if (d->dbmode == ManagedTags)
|
|
{
|
|
AlbumManager *man = AlbumManager::instance();
|
|
TQStringList tagPaths = metadata.getImageKeywords();
|
|
TQValueList<TAlbum *> loadedTags;
|
|
|
|
for (TQStringList::iterator it = tagPaths.begin(); it != tagPaths.end(); ++it)
|
|
{
|
|
TAlbum *album = man->findTAlbum(*it);
|
|
if (!album)
|
|
{
|
|
DWarning() << k_funcinfo << "Tag id " << *it << " not found in database. Use NewTagsImport mode?" << endl;
|
|
continue;
|
|
}
|
|
loadedTags.append(album);
|
|
}
|
|
|
|
loadTags(loadedTags);
|
|
}
|
|
else
|
|
{
|
|
loadTags(metadata.getImageKeywords());
|
|
}
|
|
}
|
|
|
|
bool MetadataHub::load(const TQString &filePath)
|
|
{
|
|
DMetadata metadata;
|
|
bool success = metadata.load(filePath);
|
|
load(metadata); // increments count
|
|
return success;
|
|
}
|
|
|
|
// private common code to merge tags
|
|
void MetadataHub::loadTags(const TQValueList<TAlbum *> &loadedTags)
|
|
{
|
|
// get copy of tags
|
|
TQValueList<TAlbum *> previousTags = d->tags.keys();
|
|
|
|
// first go through all tags contained in this set
|
|
for (TQValueList<TAlbum *>::const_iterator it = loadedTags.begin(); it != loadedTags.end(); ++it)
|
|
{
|
|
// that is a reference
|
|
TagStatus &status = d->tags[*it];
|
|
// if it was not contained in the list, the default constructor will mark it as invalid
|
|
if (status == MetadataInvalid)
|
|
{
|
|
if (d->count == 1)
|
|
// there were no previous sets that could have contained the set
|
|
status = TagStatus(MetadataAvailable, true);
|
|
else
|
|
// previous sets did not contain the tag, we do => disjoint
|
|
status = TagStatus(MetadataDisjoint, true);
|
|
}
|
|
else if (status == TagStatus(MetadataAvailable, false))
|
|
{
|
|
// set to explicitly not contained, but we contain it => disjoint
|
|
status = TagStatus(MetadataDisjoint, true);
|
|
}
|
|
// else if mapIt.data() == MetadataAvailable, true: all right, we contain it too
|
|
// else if mapIt.data() == MetadataDisjoint: it's already disjoint
|
|
|
|
// remove from the list to signal that this tag has been handled
|
|
previousTags.remove(*it);
|
|
}
|
|
|
|
// Those tags which had been set as MetadataAvailable before,
|
|
// but are not contained in this set, have to be set to MetadataDisjoint
|
|
for (TQValueList<TAlbum *>::iterator it = previousTags.begin(); it != previousTags.end(); ++it)
|
|
{
|
|
TQMap<TAlbum *, TagStatus>::iterator mapIt = d->tags.find(*it);
|
|
if (mapIt != d->tags.end() && mapIt.data() == TagStatus(MetadataAvailable, true))
|
|
{
|
|
mapIt.data() = TagStatus(MetadataDisjoint, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// private code to merge tags with d->tagList
|
|
void MetadataHub::loadTags(const TQStringList &loadedTagPaths)
|
|
{
|
|
if (d->count == 1)
|
|
{
|
|
d->tagList = loadedTagPaths;
|
|
}
|
|
else
|
|
{
|
|
// a simple intersection
|
|
TQStringList toBeAdded;
|
|
for (TQStringList::iterator it = d->tagList.begin(); it != d->tagList.end(); ++it)
|
|
{
|
|
TQStringList::const_iterator newTagListIt = loadedTagPaths.find(*it);
|
|
if (newTagListIt == loadedTagPaths.end())
|
|
{
|
|
// it's not in the loadedTagPaths list. Remove it from intersection list.
|
|
it = d->tagList.remove(it);
|
|
}
|
|
// else, it is in both lists, so no need to change d->tagList, it's already added.
|
|
}
|
|
}
|
|
}
|
|
|
|
// private common code to load dateTime, comment, rating
|
|
void MetadataHub::load(const TQDateTime &dateTime, const TQString &comment, int rating)
|
|
{
|
|
if (dateTime.isValid())
|
|
{
|
|
d->loadWithInterval<TQDateTime>(dateTime, d->dateTime, d->lastDateTime, d->dateTimeStatus);
|
|
}
|
|
|
|
d->loadWithInterval<int>(rating, d->rating, d->highestRating, d->ratingStatus);
|
|
|
|
d->loadSingleValue<TQString>(comment, d->comment, d->commentStatus);
|
|
}
|
|
|
|
// template method to share code for dateTime and rating
|
|
template <class T> void MetadataHubPriv::loadWithInterval(const T &data, T &storage, T &highestStorage, MetadataHub::Status &status)
|
|
{
|
|
switch (status)
|
|
{
|
|
case MetadataHub::MetadataInvalid:
|
|
storage = data;
|
|
status = MetadataHub::MetadataAvailable;
|
|
break;
|
|
case MetadataHub::MetadataAvailable:
|
|
// we have two values. If they are equal, status is unchanged
|
|
if (data == storage)
|
|
break;
|
|
// they are not equal. We need to enter the disjoint state.
|
|
status = MetadataHub::MetadataDisjoint;
|
|
if (data > storage)
|
|
{
|
|
highestStorage = data;
|
|
}
|
|
else
|
|
{
|
|
highestStorage = storage;
|
|
storage = data;
|
|
}
|
|
break;
|
|
case MetadataHub::MetadataDisjoint:
|
|
// smaller value is stored in storage
|
|
if (data < storage)
|
|
storage = data;
|
|
else if (highestStorage < data)
|
|
highestStorage = data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// template method used by comment
|
|
template <class T> void MetadataHubPriv::loadSingleValue(const T &data, T &storage, MetadataHub::Status &status)
|
|
{
|
|
switch (status)
|
|
{
|
|
case MetadataHub::MetadataInvalid:
|
|
storage = data;
|
|
status = MetadataHub::MetadataAvailable;
|
|
break;
|
|
case MetadataHub::MetadataAvailable:
|
|
// we have two values. If they are equal, status is unchanged
|
|
if (data == storage)
|
|
break;
|
|
// they are not equal. We need to enter the disjoint state.
|
|
status = MetadataHub::MetadataDisjoint;
|
|
break;
|
|
case MetadataHub::MetadataDisjoint:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
|
|
bool MetadataHub::write(ImageInfo *info, WriteMode writeMode)
|
|
{
|
|
bool changed = false;
|
|
|
|
// find out in advance if we have something to write - needed for FullWriteIfChanged mode
|
|
bool saveComment = d->commentStatus == MetadataAvailable;
|
|
bool saveDateTime = d->dateTimeStatus == MetadataAvailable;
|
|
bool saveRating = d->ratingStatus == MetadataAvailable;
|
|
bool saveTags = false;
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
if (it.data() == MetadataAvailable)
|
|
{
|
|
saveTags = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool writeAllFields;
|
|
if (writeMode == FullWrite)
|
|
writeAllFields = true;
|
|
else if (writeMode == FullWriteIfChanged)
|
|
writeAllFields = (
|
|
(saveComment && d->commentChanged) ||
|
|
(saveDateTime && d->dateTimeChanged) ||
|
|
(saveRating && d->ratingChanged) ||
|
|
(saveTags && d->tagsChanged)
|
|
);
|
|
else // PartialWrite
|
|
writeAllFields = false;
|
|
|
|
if (saveComment && (writeAllFields || d->commentChanged))
|
|
{
|
|
info->setCaption(d->comment);
|
|
changed = true;
|
|
}
|
|
if (saveDateTime && (writeAllFields || d->dateTimeChanged))
|
|
{
|
|
info->setDateTime(d->dateTime);
|
|
changed = true;
|
|
}
|
|
if (saveRating && (writeAllFields || d->ratingChanged))
|
|
{
|
|
info->setRating(d->rating);
|
|
changed = true;
|
|
}
|
|
|
|
if (writeAllFields || d->tagsChanged)
|
|
{
|
|
if (d->dbmode == ManagedTags)
|
|
{
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
if (it.data() == MetadataAvailable)
|
|
{
|
|
if (it.data().hasTag)
|
|
info->setTag(it.key()->id());
|
|
else
|
|
info->removeTag(it.key()->id());
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// tags not yet contained in database will be created
|
|
info->addTagPaths(d->tagList);
|
|
changed = changed || !d->tagList.isEmpty();
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
bool MetadataHub::write(DMetadata &metadata, WriteMode writeMode, const MetadataWriteSettings &settings)
|
|
{
|
|
bool dirty = false;
|
|
|
|
// find out in advance if we have something to write - needed for FullWriteIfChanged mode
|
|
bool saveComment = (settings.saveComments && d->commentStatus == MetadataAvailable);
|
|
bool saveDateTime = (settings.saveDateTime && d->dateTimeStatus == MetadataAvailable);
|
|
bool saveRating = (settings.saveRating && d->ratingStatus == MetadataAvailable);
|
|
bool saveTags = false;
|
|
if (settings.saveIptcTags)
|
|
{
|
|
saveTags = false;
|
|
// find at least one tag to write
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
if (it.data() == MetadataAvailable)
|
|
{
|
|
saveTags = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool writeAllFields;
|
|
if (writeMode == FullWrite)
|
|
writeAllFields = true;
|
|
else if (writeMode == FullWriteIfChanged)
|
|
writeAllFields = (
|
|
(saveComment && d->commentChanged) ||
|
|
(saveDateTime && d->dateTimeChanged) ||
|
|
(saveRating && d->ratingChanged) ||
|
|
(saveTags && d->tagsChanged)
|
|
);
|
|
else // PartialWrite
|
|
writeAllFields = false;
|
|
|
|
if (saveComment && (writeAllFields || d->commentChanged))
|
|
{
|
|
// Store comments in image as JFIF comments, Exif comments, and Iptc Comments.
|
|
dirty |= metadata.setImageComment(d->comment);
|
|
}
|
|
|
|
if (saveDateTime && (writeAllFields || d->dateTimeChanged))
|
|
{
|
|
// Store Image Date & Time as Exif and Iptc tags.
|
|
dirty |= metadata.setImageDateTime(d->dateTime, false);
|
|
}
|
|
|
|
if (saveRating && (writeAllFields || d->ratingChanged))
|
|
{
|
|
// Store Image rating as Iptc tag.
|
|
dirty |= metadata.setImageRating(d->rating);
|
|
}
|
|
|
|
if (saveTags && (writeAllFields || d->tagsChanged))
|
|
{
|
|
// Store tag paths as Iptc keywords tags.
|
|
|
|
// DatabaseMode == ManagedTags is assumed.
|
|
// To fix this constraint (not needed currently), an oldKeywords parameter is needed
|
|
|
|
// create list of keywords to be added and to be removed
|
|
TQStringList newKeywords, oldKeywords;
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
// it is important that MetadataDisjoint keywords are not touched
|
|
if (it.data() == MetadataAvailable)
|
|
{
|
|
// This works for single and multiple selection.
|
|
// In both situations, tags which had originally been loaded
|
|
// have explicitly been removed with setTag.
|
|
if (it.data().hasTag)
|
|
newKeywords.append(it.key()->tagPath(false));
|
|
else
|
|
oldKeywords.append(it.key()->tagPath(false));
|
|
}
|
|
}
|
|
// NOTE: See B.K.O #175321 : we remove all old keyword from IPTC and XMP before to
|
|
// synchronize metadata, else contents is not coherent.
|
|
dirty |= metadata.setImageKeywords(metadata.getImageKeywords(), newKeywords);
|
|
}
|
|
|
|
if (settings.saveIptcPhotographerId && writeAllFields)
|
|
{
|
|
// Store Photograph identity into the Iptc tags.
|
|
dirty |= metadata.setImagePhotographerId(settings.iptcAuthor,
|
|
settings.iptcAuthorTitle);
|
|
}
|
|
|
|
if (settings.saveIptcCredits && writeAllFields)
|
|
{
|
|
// Store Photograph identity into the Iptc tags.
|
|
dirty |= metadata.setImageCredits(settings.iptcCredit,
|
|
settings.iptcSource,
|
|
settings.iptcCopyright);
|
|
}
|
|
|
|
return dirty;
|
|
}
|
|
|
|
bool MetadataHub::write(const TQString &filePath, WriteMode writeMode, const MetadataWriteSettings &settings)
|
|
{
|
|
// if no DMetadata object is needed at all, don't construct one -
|
|
// important optimization if writing to file is turned off in setup!
|
|
if (!needWriteMetadata(writeMode, settings))
|
|
return false;
|
|
|
|
DMetadata metadata(filePath);
|
|
if (write(metadata, writeMode, settings))
|
|
{
|
|
bool success = metadata.applyChanges();
|
|
ImageAttributesWatch::instance()->fileMetadataChanged(filePath);
|
|
return success;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MetadataHub::write(DImg &image, WriteMode writeMode, const MetadataWriteSettings &settings)
|
|
{
|
|
// if no DMetadata object is needed at all, don't construct one
|
|
if (!needWriteMetadata(writeMode, settings))
|
|
return false;
|
|
|
|
// See DImgLoader::readMetadata() and saveMetadata()
|
|
DMetadata metadata;
|
|
metadata.setComments(image.getComments());
|
|
metadata.setExif(image.getExif());
|
|
metadata.setIptc(image.getIptc());
|
|
|
|
if (write(metadata, writeMode, settings))
|
|
{
|
|
// Do not insert null data into metaData map:
|
|
// Even if byte array is null, if there is a key in the map, it will
|
|
// be interpreted as "There was data, so write it again to the file".
|
|
if (!metadata.getComments().isNull())
|
|
image.setComments(metadata.getComments());
|
|
if (!metadata.getExif().isNull())
|
|
image.setExif(metadata.getExif());
|
|
if (!metadata.getIptc().isNull())
|
|
image.setIptc(metadata.getIptc());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MetadataHub::needWriteMetadata(WriteMode writeMode, const MetadataWriteSettings &settings) const
|
|
{
|
|
// This is the same logic as in write(DMetadata) but without actually writing.
|
|
// Adapt if the method above changes
|
|
|
|
bool saveComment = (settings.saveComments && d->commentStatus == MetadataAvailable);
|
|
bool saveDateTime = (settings.saveDateTime && d->dateTimeStatus == MetadataAvailable);
|
|
bool saveRating = (settings.saveRating && d->ratingStatus == MetadataAvailable);
|
|
bool saveTags = false;
|
|
if (settings.saveIptcTags)
|
|
{
|
|
saveTags = false;
|
|
// find at least one tag to write
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
if (it.data() == MetadataAvailable)
|
|
{
|
|
saveTags = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool writeAllFields;
|
|
if (writeMode == FullWrite)
|
|
writeAllFields = true;
|
|
else if (writeMode == FullWriteIfChanged)
|
|
writeAllFields = (
|
|
(saveComment && d->commentChanged) ||
|
|
(saveDateTime && d->dateTimeChanged) ||
|
|
(saveRating && d->ratingChanged) ||
|
|
(saveTags && d->tagsChanged)
|
|
);
|
|
else // PartialWrite
|
|
writeAllFields = false;
|
|
|
|
return (
|
|
(saveComment && (writeAllFields || d->commentChanged)) ||
|
|
(saveDateTime && (writeAllFields || d->dateTimeChanged)) ||
|
|
(saveRating && (writeAllFields || d->ratingChanged)) ||
|
|
(saveTags && (writeAllFields || d->tagsChanged)) ||
|
|
(settings.saveIptcPhotographerId && writeAllFields) ||
|
|
(settings.saveIptcCredits && writeAllFields)
|
|
);
|
|
}
|
|
|
|
MetadataWriteSettings MetadataHub::defaultWriteSettings()
|
|
{
|
|
if (AlbumSettings::instance())
|
|
return MetadataWriteSettings(AlbumSettings::instance());
|
|
else
|
|
// is this check necessary?
|
|
return MetadataWriteSettings();
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
|
|
MetadataHub::Status MetadataHub::dateTimeStatus() const
|
|
{
|
|
return d->dateTimeStatus;
|
|
}
|
|
|
|
MetadataHub::Status MetadataHub::commentStatus() const
|
|
{
|
|
return d->commentStatus;
|
|
}
|
|
|
|
MetadataHub::Status MetadataHub::ratingStatus() const
|
|
{
|
|
return d->ratingStatus;
|
|
}
|
|
|
|
MetadataHub::TagStatus MetadataHub::tagStatus(int albumId) const
|
|
{
|
|
if (d->dbmode == NewTagsImport)
|
|
return TagStatus(MetadataInvalid);
|
|
return tagStatus(AlbumManager::instance()->findTAlbum(albumId));
|
|
}
|
|
|
|
MetadataHub::TagStatus MetadataHub::tagStatus(const TQString &tagPath) const
|
|
{
|
|
if (d->dbmode == NewTagsImport)
|
|
return TagStatus(MetadataInvalid);
|
|
return tagStatus(AlbumManager::instance()->findTAlbum(tagPath));
|
|
}
|
|
|
|
MetadataHub::TagStatus MetadataHub::tagStatus(TAlbum *album) const
|
|
{
|
|
if (!album)
|
|
return TagStatus(MetadataInvalid);
|
|
TQMap<TAlbum *, TagStatus>::iterator mapIt = d->tags.find(album);
|
|
if (mapIt == d->tags.end())
|
|
return TagStatus(MetadataInvalid);
|
|
return mapIt.data();
|
|
}
|
|
|
|
|
|
bool MetadataHub::dateTimeChanged() const
|
|
{
|
|
return d->dateTimeChanged;
|
|
}
|
|
|
|
bool MetadataHub::commentChanged() const
|
|
{
|
|
return d->commentChanged;
|
|
}
|
|
|
|
bool MetadataHub::ratingChanged() const
|
|
{
|
|
return d->ratingChanged;
|
|
}
|
|
|
|
bool MetadataHub::tagsChanged() const
|
|
{
|
|
return d->tagsChanged;
|
|
}
|
|
|
|
TQDateTime MetadataHub::dateTime() const
|
|
{
|
|
return d->dateTime;
|
|
}
|
|
|
|
TQString MetadataHub::comment() const
|
|
{
|
|
return d->comment;
|
|
}
|
|
|
|
int MetadataHub::rating() const
|
|
{
|
|
return d->rating;
|
|
}
|
|
|
|
void MetadataHub::dateTimeInterval(TQDateTime &lowest, TQDateTime &highest) const
|
|
{
|
|
switch (d->dateTimeStatus)
|
|
{
|
|
case MetadataInvalid:
|
|
lowest = highest = TQDateTime();
|
|
break;
|
|
case MetadataAvailable:
|
|
lowest = highest = d->dateTime;
|
|
break;
|
|
case MetadataDisjoint:
|
|
lowest = d->dateTime;
|
|
highest = d->lastDateTime;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MetadataHub::ratingInterval(int &lowest, int &highest) const
|
|
{
|
|
switch (d->ratingStatus)
|
|
{
|
|
case MetadataInvalid:
|
|
lowest = highest = -1;
|
|
break;
|
|
case MetadataAvailable:
|
|
lowest = highest = d->rating;
|
|
break;
|
|
case MetadataDisjoint:
|
|
lowest = d->rating;
|
|
highest = d->highestRating;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TQStringList MetadataHub::keywords() const
|
|
{
|
|
if (d->dbmode == NewTagsImport)
|
|
return d->tagList;
|
|
else
|
|
{
|
|
TQStringList tagList;
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
if (it.data() == TagStatus(MetadataAvailable, true))
|
|
tagList.append(it.key()->tagPath(false));
|
|
}
|
|
return tagList;
|
|
}
|
|
}
|
|
|
|
TQMap<TAlbum *, MetadataHub::TagStatus> MetadataHub::tags() const
|
|
{
|
|
// DatabaseMode == ManagedTags is assumed
|
|
return d->tags;
|
|
}
|
|
|
|
TQMap<int, MetadataHub::TagStatus> MetadataHub::tagIDs() const
|
|
{
|
|
// DatabaseMode == ManagedTags is assumed
|
|
TQMap<int, TagStatus> intmap;
|
|
for (TQMap<TAlbum *, TagStatus>::iterator it = d->tags.begin(); it != d->tags.end(); ++it)
|
|
{
|
|
intmap.insert(it.key()->id(), it.data());
|
|
}
|
|
return intmap;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
void MetadataHub::setDateTime(const TQDateTime &dateTime, Status status)
|
|
{
|
|
d->dateTimeStatus = status;
|
|
d->dateTime = dateTime;
|
|
d->dateTimeChanged = true;
|
|
}
|
|
|
|
void MetadataHub::setComment(const TQString &comment, Status status)
|
|
{
|
|
d->commentStatus = status;
|
|
d->comment = comment;
|
|
d->commentChanged = true;
|
|
}
|
|
|
|
void MetadataHub::setRating(int rating, Status status)
|
|
{
|
|
d->ratingStatus = status;
|
|
d->rating = rating;
|
|
d->ratingChanged = true;
|
|
}
|
|
|
|
void MetadataHub::setTag(TAlbum *tag, bool hasTag, Status status)
|
|
{
|
|
// DatabaseMode == ManagedTags is assumed
|
|
d->tags[tag] = TagStatus(status, hasTag);
|
|
d->tagsChanged = true;
|
|
}
|
|
|
|
void MetadataHub::setTag(int albumID, bool hasTag, Status status)
|
|
{
|
|
// DatabaseMode == ManagedTags is assumed
|
|
TAlbum *album = AlbumManager::instance()->findTAlbum(albumID);
|
|
if (!album)
|
|
{
|
|
DWarning() << k_funcinfo << "Tag ID " << albumID << " not found in database." << endl;
|
|
return;
|
|
}
|
|
setTag(album, hasTag, status);
|
|
}
|
|
|
|
void MetadataHub::resetChanged()
|
|
{
|
|
d->dateTimeChanged = false;
|
|
d->commentChanged = false;
|
|
d->ratingChanged = false;
|
|
d->tagsChanged = false;
|
|
}
|
|
|
|
} // namespace Digikam
|
|
|