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