diff --git a/core/libs/database/item/containers/iteminfocache.cpp b/core/libs/database/item/containers/iteminfocache.cpp index 75e3a56c7c..c44996f09b 100644 --- a/core/libs/database/item/containers/iteminfocache.cpp +++ b/core/libs/database/item/containers/iteminfocache.cpp @@ -1,386 +1,385 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-05-01 * Description : ItemInfo common data * * Copyright (C) 2007-2013 by Marcel Wiesweg * Copyright (C) 2014-2020 by Gilles Caulier * Copyright (C) 2013 by Michael G. Hansen * * 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. * * ============================================================ */ #include "iteminfocache.h" // Local includes #include "coredb.h" #include "coredbalbuminfo.h" #include "iteminfo.h" #include "iteminfolist.h" #include "iteminfodata.h" #include "digikam_debug.h" namespace Digikam { ItemInfoCache::ItemInfoCache() : m_needUpdateAlbums(true), m_needUpdateGrouped(true) { qRegisterMetaType("ItemInfo"); qRegisterMetaType("ItemInfoList"); qRegisterMetaType >("QList"); CoreDbWatch* const dbwatch = CoreDbAccess::databaseWatch(); connect(dbwatch, SIGNAL(imageChange(ImageChangeset)), this, SLOT(slotImageChanged(ImageChangeset)), Qt::DirectConnection); connect(dbwatch, SIGNAL(imageTagChange(ImageTagChangeset)), this, SLOT(slotImageTagChanged(ImageTagChangeset)), Qt::DirectConnection); connect(dbwatch, SIGNAL(albumChange(AlbumChangeset)), this, SLOT(slotAlbumChange(AlbumChangeset)), Qt::DirectConnection); } ItemInfoCache::~ItemInfoCache() { } static bool lessThanForAlbumShortInfo(const AlbumShortInfo& first, const AlbumShortInfo& second) { return first.id < second.id; } void ItemInfoCache::checkAlbums() { if (m_needUpdateAlbums) { // list comes sorted from db QList infos = CoreDbAccess().db()->getAlbumShortInfos(); ItemInfoWriteLocker lock; m_albums = infos; m_needUpdateAlbums = false; } } int ItemInfoCache::getImageGroupedCount(qlonglong id) { if (m_needUpdateGrouped) { QList ids = CoreDbAccess().db()->getRelatedImagesToByType(DatabaseRelation::Grouped); ItemInfoWriteLocker lock; m_grouped = ids; m_needUpdateGrouped = false; } ItemInfoReadLocker lock; return m_grouped.count(id); } QExplicitlySharedDataPointer ItemInfoCache::infoForId(qlonglong id) { { ItemInfoReadLocker lock; - QExplicitlySharedDataPointer ptr(m_infos.value(id)); + QExplicitlySharedDataPointer ptr(m_infoHash.value(id)); if (ptr) { return ptr; } } ItemInfoWriteLocker lock; ItemInfoData* const data = new ItemInfoData(); data->id = id; - m_infos[id] = data; + m_infoHash[id] = data; return QExplicitlySharedDataPointer(data); } -void ItemInfoCache::cacheByName(const QExplicitlySharedDataPointer& ptr) +void ItemInfoCache::cacheByName(const QExplicitlySharedDataPointer& infoPtr) { // Called with Write lock - ItemInfoData* const data = ptr.data(); + ItemInfoData* const data = infoPtr.data(); if (!data || data->id == -1 || data->name.isEmpty()) { return; } // Called in a context where we can assume that the entry is not yet cached by name (newly created data) m_nameHash.remove(m_dataHash.value(data), data); m_nameHash.insert(data->name, data); m_dataHash.insert(data, data->name); } QExplicitlySharedDataPointer ItemInfoCache::infoForPath(int albumRootId, const QString& relativePath, const QString& name) { ItemInfoReadLocker lock; // We check all entries in the multi hash with matching file name QMultiHash::const_iterator it; for (it = m_nameHash.constFind(name) ; it != m_nameHash.constEnd() && it.key() == name ; ++it) { // first check that album root matches if (it.value()->albumRootId != albumRootId) { continue; } // check that relativePath matches. We get relativePath from entry's id and compare to given name. QList::const_iterator albumIt = findAlbum(it.value()->albumId); if (albumIt == m_albums.constEnd() || albumIt->relativePath != relativePath) { continue; } // we have now a match by name, albumRootId and relativePath return QExplicitlySharedDataPointer(it.value()); } return QExplicitlySharedDataPointer(); } -void ItemInfoCache::dropInfo(const QExplicitlySharedDataPointer& ptr) +void ItemInfoCache::dropInfo(const QExplicitlySharedDataPointer& infoPtr) { - if (!ptr) + if (!infoPtr) { return; } ItemInfoWriteLocker lock; - ItemInfoData* const data = ptr.data(); + ItemInfoData* const data = infoPtr.data(); if (!data || (data->ref > 1)) { return; } - m_infos.remove(data->id); - m_nameHash.remove(m_dataHash.value(data), data); m_nameHash.remove(data->name, data); + m_infoHash.remove(data->id); m_dataHash.remove(data); } QList::const_iterator ItemInfoCache::findAlbum(int id) { // Called with read lock AlbumShortInfo info; info.id = id; // we use the fact that d->infos is sorted by id QList::const_iterator it; it = std::lower_bound(m_albums.constBegin(), m_albums.constEnd(), info, lessThanForAlbumShortInfo); if (it == m_albums.constEnd() || info.id < (*it).id) { return m_albums.constEnd(); } return it; } QString ItemInfoCache::albumRelativePath(int albumId) { checkAlbums(); ItemInfoReadLocker lock; QList::const_iterator it = findAlbum(albumId); if (it != m_albums.constEnd()) { return it->relativePath; } return QString(); } void ItemInfoCache::invalidate() { ItemInfoWriteLocker lock; QHash::iterator it; - for (it = m_infos.begin() ; it != m_infos.end() ; ++it) + for (it = m_infoHash.begin() ; it != m_infoHash.end() ; ++it) { (*it)->invalid = true; (*it)->id = -1; } - m_infos.clear(); m_albums.clear(); m_grouped.clear(); m_nameHash.clear(); + m_infoHash.clear(); m_dataHash.clear(); m_needUpdateAlbums = true; m_needUpdateGrouped = true; } void ItemInfoCache::slotImageChanged(const ImageChangeset& changeset) { ItemInfoWriteLocker lock; foreach (const qlonglong& imageId, changeset.ids()) { - QHash::iterator it = m_infos.find(imageId); + QHash::iterator it = m_infoHash.find(imageId); - if (it != m_infos.end()) + if (it != m_infoHash.end()) { // invalidate the relevant field. It will be lazy-loaded at first access. DatabaseFields::Set changes = changeset.changes(); if (changes & DatabaseFields::ItemCommentsAll) { (*it)->defaultCommentCached = false; (*it)->defaultTitleCached = false; } if (changes & DatabaseFields::Category) { (*it)->categoryCached = false; } if (changes & DatabaseFields::Format) { (*it)->formatCached = false; } if (changes & DatabaseFields::PickLabel) { (*it)->pickLabelCached = false; } if (changes & DatabaseFields::ColorLabel) { (*it)->colorLabelCached = false; } if (changes & DatabaseFields::Rating) { (*it)->ratingCached = false; } if (changes & DatabaseFields::CreationDate) { (*it)->creationDateCached = false; } if (changes & DatabaseFields::ModificationDate) { (*it)->modificationDateCached = false; } if (changes & DatabaseFields::FileSize) { (*it)->fileSizeCached = false; } if (changes & DatabaseFields::ManualOrder) { (*it)->manualOrderCached = false; } if ((changes & DatabaseFields::Width) || (changes & DatabaseFields::Height)) { (*it)->imageSizeCached = false; } if (changes & DatabaseFields::LatitudeNumber || changes & DatabaseFields::LongitudeNumber || changes & DatabaseFields::Altitude) { (*it)->positionsCached = false; } if (changes & DatabaseFields::ImageRelations) { (*it)->groupImageCached = false; m_needUpdateGrouped = true; } if (changes.hasFieldsFromVideoMetadata()) { const DatabaseFields::VideoMetadata changedVideoMetadata = changes.getVideoMetadata(); (*it)->videoMetadataCached &= ~changedVideoMetadata; (*it)->hasVideoMetadata = true; (*it)->databaseFieldsHashRaw.removeAllFields(changedVideoMetadata); } if (changes.hasFieldsFromImageMetadata()) { const DatabaseFields::ImageMetadata changedImageMetadata = changes.getImageMetadata(); (*it)->imageMetadataCached &= ~changedImageMetadata; (*it)->hasImageMetadata = true; (*it)->databaseFieldsHashRaw.removeAllFields(changedImageMetadata); } } else { m_needUpdateGrouped = true; } } } void ItemInfoCache::slotImageTagChanged(const ImageTagChangeset& changeset) { if (changeset.propertiesWereChanged()) { return; } ItemInfoWriteLocker lock; foreach (const qlonglong& imageId, changeset.ids()) { - QHash::iterator it = m_infos.find(imageId); + QHash::iterator it = m_infoHash.find(imageId); - if (it != m_infos.end()) + if (it != m_infoHash.end()) { (*it)->tagIdsCached = false; (*it)->colorLabelCached = false; (*it)->pickLabelCached = false; } } } void ItemInfoCache::slotAlbumChange(const AlbumChangeset& changeset) { switch (changeset.operation()) { case AlbumChangeset::Added: case AlbumChangeset::Deleted: case AlbumChangeset::Renamed: case AlbumChangeset::PropertiesChanged: m_needUpdateAlbums = true; break; case AlbumChangeset::Unknown: break; } } } // namespace Digikam diff --git a/core/libs/database/item/containers/iteminfocache.h b/core/libs/database/item/containers/iteminfocache.h index 71daf976bf..7036cc0bf0 100644 --- a/core/libs/database/item/containers/iteminfocache.h +++ b/core/libs/database/item/containers/iteminfocache.h @@ -1,122 +1,122 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-05-01 * Description : ItemInfo common data * * Copyright (C) 2007-2013 by Marcel Wiesweg * Copyright (C) 2013-2020 by Gilles Caulier * * 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. * * ============================================================ */ #ifndef DIGIKAM_ITEM_INFO_CACHE_H #define DIGIKAM_ITEM_INFO_CACHE_H // Qt includes #include #include #include #include // Local includes #include "coredbwatch.h" namespace Digikam { class AlbumShortInfo; class ItemInfoData; // No EXPORT class class ItemInfoCache : public QObject { Q_OBJECT public: explicit ItemInfoCache(); ~ItemInfoCache(); /** * Return an ItemInfoData object for the given image id. * A new object is created, or an existing object is returned. * If a new object is created, the id field will be initialized. */ QExplicitlySharedDataPointer infoForId(qlonglong id); /** * Call this when the data has been dereferenced, * before deletion. */ - void dropInfo(const QExplicitlySharedDataPointer& ptr); + void dropInfo(const QExplicitlySharedDataPointer& infoPtr); /** * Call this to put data in the hash by file name if you have newly created data * and the name is filled. * Call under write lock. */ - void cacheByName(const QExplicitlySharedDataPointer& ptr); + void cacheByName(const QExplicitlySharedDataPointer& infoPtr); /** * Return an ItemInfoData object for the given album root, relativePath and file name triple. * Works if previously cached with cacheByName. * Returns 0 if not found. */ QExplicitlySharedDataPointer infoForPath(int albumRootId, const QString& relativePath, const QString& name); /** * Returns the cached relativePath for the given album id. */ QString albumRelativePath(int albumId); /** * Returns the cached grouped count for the given image id. */ int getImageGroupedCount(qlonglong id); /** * Invalidate the cache and all its cached data */ void invalidate(); private Q_SLOTS: void slotImageChanged(const ImageChangeset& changeset); void slotImageTagChanged(const ImageTagChangeset& changeset); void slotAlbumChange(const AlbumChangeset&); private: QList::const_iterator findAlbum(int id); void checkAlbums(); private: - QHash m_infos; - QHash m_dataHash; QMultiHash m_nameHash; + QHash m_infoHash; + QHash m_dataHash; volatile bool m_needUpdateAlbums; volatile bool m_needUpdateGrouped; QList m_grouped; QList m_albums; }; } // namespace Digikam #endif // DIGIKAM_ITEM_INFO_CACHE_H