File indexing completed on 2024-04-28 15:39:55

0001 /* SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team
0002 
0003    SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "GroupCounter.h"
0007 
0008 #include "ImageDB.h"
0009 #include "MemberMap.h"
0010 
0011 #include <kpabase/StringSet.h>
0012 using namespace DB;
0013 
0014 /**
0015  * \class DB::GroupCounter
0016  * \brief Utility class to help counting matches for member groups.
0017  *
0018  * This class is used to count the member group matches when
0019  * categorizing. The class is instantiating with the category we currently
0020  * are counting items for.
0021  *
0022  * The class builds the inverse member map, that is a map pointing from items
0023  * to parent.
0024  *
0025  * As an example, imagine we have the following member map (stored in the
0026  * variable groupToMemberMap in  the code):
0027  * \code
0028  *    { USA |-> [Chicago, Santa Clara],
0029  *      California |-> [Santa Clara, Los Angeles] }
0030  * \endcode
0031  *
0032  * The inverse map (stored in m_memberToGroup in the code ) will then look
0033  * like this:
0034  * \code
0035  *  { Chicago |-> [USA],
0036  *    Sanata Clara |-> [ USA, California ],
0037  *    Los Angeless |-> [ California ] }
0038  * \endcode
0039  */
0040 GroupCounter::GroupCounter(const QString &category)
0041 {
0042     const MemberMap map = DB::ImageDB::instance()->memberMap();
0043     QMap<QString, StringSet> groupToMemberMap = map.groupMap(category);
0044 
0045     m_memberToGroup.reserve(2729 /* A large prime */);
0046     m_groupCount.reserve(2729 /* A large prime */);
0047 
0048     // Populate the m_memberToGroup map
0049     for (QMap<QString, StringSet>::Iterator groupToMemberIt = groupToMemberMap.begin(); groupToMemberIt != groupToMemberMap.end(); ++groupToMemberIt) {
0050         const StringSet members = groupToMemberIt.value();
0051         const QString group = groupToMemberIt.key();
0052 
0053         for (const auto &member : members) {
0054             m_memberToGroup[member].append(group);
0055         }
0056         m_groupCount.insert(group, CountWithRange());
0057     }
0058 }
0059 
0060 /**
0061  * categories is the selected categories for one image, members may be Las Vegas, Chicago, and Los Angeles if the
0062  * category in question is Places.
0063  * This function then increases m_groupCount with 1 for each of the groups the relavant items belongs to
0064  * Las Vegas might increase the m_groupCount[Nevada] by one.
0065  * The tricky part is to avoid increasing it by more than 1 per image, that is what the countedGroupDict is
0066  * used for.
0067  */
0068 void GroupCounter::count(const StringSet &categories, const ImageDate &date)
0069 {
0070     static StringSet countedGroupDict;
0071 
0072     countedGroupDict.clear();
0073     for (StringSet::const_iterator categoryIt = categories.begin(); categoryIt != categories.end(); ++categoryIt) {
0074         if (m_memberToGroup.contains(*categoryIt)) {
0075             const QStringList groups = m_memberToGroup[*categoryIt];
0076             for (const QString &group : groups) {
0077                 if (!countedGroupDict.contains(group)) {
0078                     countedGroupDict.insert(group);
0079                     m_groupCount[group].add(date);
0080                 }
0081             }
0082         }
0083         // The item Nevada should itself go into the group Nevada.
0084         if (!countedGroupDict.contains(*categoryIt) && m_groupCount.contains(*categoryIt)) {
0085             countedGroupDict.insert(*categoryIt);
0086             m_groupCount[*categoryIt].add(date);
0087         }
0088     }
0089 }
0090 
0091 QMap<QString, CountWithRange> GroupCounter::result()
0092 {
0093     QMap<QString, CountWithRange> res;
0094 
0095     for (QHash<QString, CountWithRange>::const_iterator it = m_groupCount.constBegin(); it != m_groupCount.constEnd(); ++it) {
0096         if (it.value().count != 0)
0097             res.insert(it.key(), it.value());
0098     }
0099     return res;
0100 }
0101 // vi:expandtab:tabstop=4 shiftwidth=4: