File indexing completed on 2025-01-19 03:53:37

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-04-21
0007  * Description : Handling access to one item and associated data - Groups
0008  *
0009  * SPDX-FileCopyrightText: 2005      by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2007-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2013      by Michael G. Hansen <mike at mghansen dot de>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "iteminfo_p.h"
0019 
0020 namespace Digikam
0021 {
0022 
0023 bool ItemInfo::hasGroupedImages() const
0024 {
0025     return numberOfGroupedImages();
0026 }
0027 
0028 int ItemInfo::numberOfGroupedImages() const
0029 {
0030     if (!m_data)
0031     {
0032         return 0;
0033     }
0034 
0035     return ItemInfoStatic::cache()->getImageGroupedCount(m_data->id);
0036 }
0037 
0038 qlonglong ItemInfo::groupImageId() const
0039 {
0040     if (!m_data)
0041     {
0042         return -1;
0043     }
0044 
0045     RETURN_IF_CACHED(groupImage)
0046 
0047     QList<qlonglong> ids = CoreDbAccess().db()->getImagesRelatedFrom(m_data->id, DatabaseRelation::Grouped);
0048     // list size should be 0 or 1
0049     int groupImage       = ids.isEmpty() ? -1 : ids.first();
0050 
0051     ItemInfoWriteLocker lock;
0052     m_data.data()->groupImage       = groupImage;
0053     m_data.data()->groupImageCached = true;
0054 
0055     return m_data->groupImage;
0056 }
0057 
0058 void ItemInfoList::loadGroupImageIds() const
0059 {
0060     ItemInfoList infoList;
0061 
0062     Q_FOREACH (const ItemInfo& info, *this)
0063     {
0064         if (info.m_data && !info.m_data->groupImageCached)
0065         {
0066             infoList << info;
0067         }
0068     }
0069 
0070     if (infoList.isEmpty())
0071     {
0072         return;
0073     }
0074 
0075     QVector<QList<qlonglong> > allGroupIds = CoreDbAccess().db()->getImagesRelatedFrom(infoList.toImageIdList(),
0076                                                                                        DatabaseRelation::Grouped);
0077 
0078     ItemInfoWriteLocker lock;
0079 
0080     for (int i = 0 ; i < infoList.size() ; ++i)
0081     {
0082         const ItemInfo& info             = infoList.at(i);
0083         const QList<qlonglong>& groupIds = allGroupIds.at(i);
0084 
0085         if (!info.m_data)
0086         {
0087             continue;
0088         }
0089 
0090         info.m_data.data()->groupImage       = groupIds.isEmpty() ? -1 : groupIds.first();
0091         info.m_data.data()->groupImageCached = true;
0092     }
0093 }
0094 
0095 bool ItemInfo::isGrouped() const
0096 {
0097     return (groupImageId() != -1);
0098 }
0099 
0100 ItemInfo ItemInfo::groupImage() const
0101 {
0102     qlonglong id = groupImageId();
0103 
0104     if (id == -1)
0105     {
0106         return ItemInfo();
0107     }
0108 
0109     return ItemInfo(id);
0110 }
0111 
0112 QList<ItemInfo> ItemInfo::groupedImages() const
0113 {
0114     if (!m_data || !hasGroupedImages())
0115     {
0116         return QList<ItemInfo>();
0117     }
0118 
0119     return ItemInfoList(CoreDbAccess().db()->getImagesRelatingTo(m_data->id, DatabaseRelation::Grouped));
0120 }
0121 
0122 void ItemInfo::addToGroup(const ItemInfo& givenLeader)
0123 {
0124     if (!m_data || givenLeader.isNull() || (givenLeader.id() == m_data->id))
0125     {
0126         return;
0127     }
0128 
0129     // Take care: Once we start this, we cannot rely on change notifications and cache invalidation!
0130 
0131     CoreDbOperationGroup group;
0132 
0133     // Handle grouping on an already grouped image, and prevent circular grouping
0134 
0135     ItemInfo leader;
0136     QList<qlonglong> alreadySeen;
0137     alreadySeen << m_data->id;
0138 
0139     for (leader = givenLeader ; leader.isGrouped() ; )
0140     {
0141         ItemInfo nextLeader = leader.groupImage();
0142 
0143         // is the new leader currently grouped on this image, or do we have a circular grouping?
0144 
0145         if (alreadySeen.contains(nextLeader.id()))
0146         {
0147             // break loop (special case: remove b->a where we want to add a->b)
0148 
0149             leader.removeFromGroup();
0150             break;
0151         }
0152         else
0153         {
0154             alreadySeen << leader.id();
0155             leader = nextLeader;
0156         }
0157     }
0158 
0159     // Already grouped correctly?
0160 
0161     if (groupImageId() == leader.id())
0162     {
0163         return;
0164     }
0165 
0166     // All images grouped on this image need a new group leader
0167 
0168     QList<qlonglong> idsToBeGrouped  = CoreDbAccess().db()->getImagesRelatingTo(m_data->id, DatabaseRelation::Grouped);
0169 
0170     // and finally, this image needs to be grouped
0171 
0172     idsToBeGrouped << m_data->id;
0173 
0174     Q_FOREACH (const qlonglong& ids, idsToBeGrouped)
0175     {
0176         // remove current grouping
0177 
0178         CoreDbAccess().db()->removeAllImageRelationsFrom(ids, DatabaseRelation::Grouped);
0179 
0180         // add the new grouping
0181 
0182         CoreDbAccess().db()->addImageRelation(ids, leader.id(), DatabaseRelation::Grouped);
0183     }
0184 }
0185 
0186 void ItemInfo::removeFromGroup()
0187 {
0188     if (!m_data)
0189     {
0190         return;
0191     }
0192 
0193     if (!isGrouped())
0194     {
0195         return;
0196     }
0197 
0198     CoreDbAccess().db()->removeAllImageRelationsFrom(m_data->id, DatabaseRelation::Grouped);
0199 }
0200 
0201 void ItemInfo::clearGroup()
0202 {
0203     if (!m_data)
0204     {
0205         return;
0206     }
0207 
0208     if (!hasGroupedImages())
0209     {
0210         return;
0211     }
0212 
0213     CoreDbAccess().db()->removeAllImageRelationsTo(m_data->id, DatabaseRelation::Grouped);
0214 }
0215 
0216 } // namespace Digikam