diff options
Diffstat (limited to 'xbmc/utils/GroupUtils.cpp')
| -rw-r--r-- | xbmc/utils/GroupUtils.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/xbmc/utils/GroupUtils.cpp b/xbmc/utils/GroupUtils.cpp new file mode 100644 index 0000000..340c11a --- /dev/null +++ b/xbmc/utils/GroupUtils.cpp | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012-2018 Team Kodi | ||
| 3 | * This file is part of Kodi - https://kodi.tv | ||
| 4 | * | ||
| 5 | * SPDX-License-Identifier: GPL-2.0-or-later | ||
| 6 | * See LICENSES/README.md for more information. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include "GroupUtils.h" | ||
| 10 | |||
| 11 | #include "FileItem.h" | ||
| 12 | #include "filesystem/MultiPathDirectory.h" | ||
| 13 | #include "utils/StringUtils.h" | ||
| 14 | #include "utils/URIUtils.h" | ||
| 15 | #include "video/VideoDbUrl.h" | ||
| 16 | #include "video/VideoInfoTag.h" | ||
| 17 | |||
| 18 | #include <map> | ||
| 19 | #include <set> | ||
| 20 | |||
| 21 | using SetMap = std::map<int, std::set<CFileItemPtr> >; | ||
| 22 | |||
| 23 | bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileItemList &items, CFileItemList &groupedItems, GroupAttribute groupAttributes /* = GroupAttributeNone */) | ||
| 24 | { | ||
| 25 | CFileItemList ungroupedItems; | ||
| 26 | return Group(groupBy, baseDir, items, groupedItems, ungroupedItems, groupAttributes); | ||
| 27 | } | ||
| 28 | |||
| 29 | bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileItemList &items, CFileItemList &groupedItems, CFileItemList &ungroupedItems, GroupAttribute groupAttributes /* = GroupAttributeNone */) | ||
| 30 | { | ||
| 31 | if (groupBy == GroupByNone) | ||
| 32 | return false; | ||
| 33 | |||
| 34 | // nothing to do if there are no items to group | ||
| 35 | if (items.Size() <= 0) | ||
| 36 | return true; | ||
| 37 | |||
| 38 | SetMap setMap; | ||
| 39 | for (int index = 0; index < items.Size(); index++) | ||
| 40 | { | ||
| 41 | bool ungrouped = true; | ||
| 42 | const CFileItemPtr item = items.Get(index); | ||
| 43 | |||
| 44 | // group by sets | ||
| 45 | if ((groupBy & GroupBySet) && | ||
| 46 | item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_set.id > 0) | ||
| 47 | { | ||
| 48 | ungrouped = false; | ||
| 49 | setMap[item->GetVideoInfoTag()->m_set.id].insert(item); | ||
| 50 | } | ||
| 51 | |||
| 52 | if (ungrouped) | ||
| 53 | ungroupedItems.Add(item); | ||
| 54 | } | ||
| 55 | |||
| 56 | if ((groupBy & GroupBySet) && !setMap.empty()) | ||
| 57 | { | ||
| 58 | CVideoDbUrl itemsUrl; | ||
| 59 | if (!itemsUrl.FromString(baseDir)) | ||
| 60 | return false; | ||
| 61 | |||
| 62 | for (SetMap::const_iterator set = setMap.begin(); set != setMap.end(); ++set) | ||
| 63 | { | ||
| 64 | // only one item in the set, so add it to the ungrouped items | ||
| 65 | if (set->second.size() == 1 && (groupAttributes & GroupAttributeIgnoreSingleItems)) | ||
| 66 | { | ||
| 67 | ungroupedItems.Add(*set->second.begin()); | ||
| 68 | continue; | ||
| 69 | } | ||
| 70 | |||
| 71 | CFileItemPtr pItem(new CFileItem((*set->second.begin())->GetVideoInfoTag()->m_set.title)); | ||
| 72 | pItem->GetVideoInfoTag()->m_iDbId = set->first; | ||
| 73 | pItem->GetVideoInfoTag()->m_type = MediaTypeVideoCollection; | ||
| 74 | |||
| 75 | std::string basePath = StringUtils::Format("videodb://movies/sets/%i/", set->first); | ||
| 76 | CVideoDbUrl videoUrl; | ||
| 77 | if (!videoUrl.FromString(basePath)) | ||
| 78 | pItem->SetPath(basePath); | ||
| 79 | else | ||
| 80 | { | ||
| 81 | videoUrl.AddOptions((*set->second.begin())->GetURL().GetOptions()); | ||
| 82 | pItem->SetPath(videoUrl.ToString()); | ||
| 83 | } | ||
| 84 | pItem->m_bIsFolder = true; | ||
| 85 | |||
| 86 | CVideoInfoTag* setInfo = pItem->GetVideoInfoTag(); | ||
| 87 | setInfo->m_strPath = pItem->GetPath(); | ||
| 88 | setInfo->m_strTitle = pItem->GetLabel(); | ||
| 89 | setInfo->m_strPlot = (*set->second.begin())->GetVideoInfoTag()->m_set.overview; | ||
| 90 | |||
| 91 | int ratings = 0; | ||
| 92 | float totalRatings = 0; | ||
| 93 | int iWatched = 0; // have all the movies been played at least once? | ||
| 94 | std::set<std::string> pathSet; | ||
| 95 | for (std::set<CFileItemPtr>::const_iterator movie = set->second.begin(); movie != set->second.end(); ++movie) | ||
| 96 | { | ||
| 97 | CVideoInfoTag* movieInfo = (*movie)->GetVideoInfoTag(); | ||
| 98 | // handle rating | ||
| 99 | if (movieInfo->GetRating().rating > 0.0f) | ||
| 100 | { | ||
| 101 | ratings++; | ||
| 102 | totalRatings += movieInfo->GetRating().rating; | ||
| 103 | } | ||
| 104 | |||
| 105 | // handle year | ||
| 106 | if (movieInfo->GetYear() > setInfo->GetYear()) | ||
| 107 | setInfo->SetYear(movieInfo->GetYear()); | ||
| 108 | |||
| 109 | // handle lastplayed | ||
| 110 | if (movieInfo->m_lastPlayed.IsValid() && movieInfo->m_lastPlayed > setInfo->m_lastPlayed) | ||
| 111 | setInfo->m_lastPlayed = movieInfo->m_lastPlayed; | ||
| 112 | |||
| 113 | // handle dateadded | ||
| 114 | if (movieInfo->m_dateAdded.IsValid() && movieInfo->m_dateAdded > setInfo->m_dateAdded) | ||
| 115 | setInfo->m_dateAdded = movieInfo->m_dateAdded; | ||
| 116 | |||
| 117 | // handle playcount/watched | ||
| 118 | setInfo->SetPlayCount(setInfo->GetPlayCount() + movieInfo->GetPlayCount()); | ||
| 119 | if (movieInfo->GetPlayCount() > 0) | ||
| 120 | iWatched++; | ||
| 121 | |||
| 122 | //accumulate the path for a multipath construction | ||
| 123 | CFileItem video(movieInfo->m_basePath, false); | ||
| 124 | if (video.IsVideo()) | ||
| 125 | pathSet.insert(URIUtils::GetParentPath(movieInfo->m_basePath)); | ||
| 126 | else | ||
| 127 | pathSet.insert(movieInfo->m_basePath); | ||
| 128 | } | ||
| 129 | setInfo->m_basePath = XFILE::CMultiPathDirectory::ConstructMultiPath(pathSet); | ||
| 130 | |||
| 131 | if (ratings > 1) | ||
| 132 | pItem->GetVideoInfoTag()->SetRating(totalRatings / ratings); | ||
| 133 | |||
| 134 | setInfo->SetPlayCount(iWatched >= static_cast<int>(set->second.size()) ? (setInfo->GetPlayCount() / set->second.size()) : 0); | ||
| 135 | pItem->SetProperty("total", (int)set->second.size()); | ||
| 136 | pItem->SetProperty("watched", iWatched); | ||
| 137 | pItem->SetProperty("unwatched", (int)set->second.size() - iWatched); | ||
| 138 | pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, setInfo->GetPlayCount() > 0); | ||
| 139 | |||
| 140 | groupedItems.Add(pItem); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | return true; | ||
| 145 | } | ||
| 146 | |||
| 147 | bool GroupUtils::GroupAndMix(GroupBy groupBy, const std::string &baseDir, const CFileItemList &items, CFileItemList &groupedItemsMixed, GroupAttribute groupAttributes /* = GroupAttributeNone */) | ||
| 148 | { | ||
| 149 | CFileItemList ungroupedItems; | ||
| 150 | if (!Group(groupBy, baseDir, items, groupedItemsMixed, ungroupedItems, groupAttributes)) | ||
| 151 | return false; | ||
| 152 | |||
| 153 | // add all the ungrouped items as well | ||
| 154 | groupedItemsMixed.Append(ungroupedItems); | ||
| 155 | |||
| 156 | return true; | ||
| 157 | } | ||
