From 3ff48bfe75aa804a8462acbfff44ec772df2bcc0 Mon Sep 17 00:00:00 2001 From: montellese Date: Thu, 28 Jun 2012 23:27:20 +0200 Subject: add GroupUtils for generic grouping of items in a list (e.g. into movie sets) --- xbmc/utils/GroupUtils.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++ xbmc/utils/GroupUtils.h | 42 +++++++++++++++ xbmc/utils/Makefile | 1 + 3 files changed, 174 insertions(+) create mode 100644 xbmc/utils/GroupUtils.cpp create mode 100644 xbmc/utils/GroupUtils.h diff --git a/xbmc/utils/GroupUtils.cpp b/xbmc/utils/GroupUtils.cpp new file mode 100644 index 0000000000..a0b31db45e --- /dev/null +++ b/xbmc/utils/GroupUtils.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include +#include + +#include "GroupUtils.h" +#include "FileItem.h" +#include "utils/StringUtils.h" +#include "utils/Variant.h" +#include "video/VideoInfoTag.h" + +using namespace std; + +typedef map > SetMap; + +bool GroupUtils::Group(GroupBy groupBy, const CFileItemList &items, CFileItemList &groupedItems, GroupAttribute groupAttributes /* = GroupAttributeNone */) +{ + if (items.Size() <= 0 || groupBy == GroupByNone) + return false; + + SetMap setMap; + for (int index = 0; index < items.Size(); index++) + { + bool add = true; + const CFileItemPtr item = items.Get(index); + + // group by sets + if ((groupBy & GroupBySet) && + item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iSetId > 0) + { + add = false; + setMap[item->GetVideoInfoTag()->m_iSetId].insert(item); + } + + if (add) + groupedItems.Add(item); + } + + if ((groupBy & GroupBySet) && setMap.size() > 0) + { + for (SetMap::const_iterator set = setMap.begin(); set != setMap.end(); set++) + { + // only one item in the set, so just re-add it + if (set->second.size() == 1 && (groupAttributes & GroupAttributeIgnoreSingleItems)) + { + groupedItems.Add(*set->second.begin()); + continue; + } + + CFileItemPtr pItem(new CFileItem((*set->second.begin())->GetVideoInfoTag()->m_strSet)); + pItem->GetVideoInfoTag()->m_iDbId = set->first; + pItem->GetVideoInfoTag()->m_type = "set"; + pItem->SetPath(StringUtils::Format("videodb://1/7/%ld/", set->first)); + pItem->m_bIsFolder = true; + + CVideoInfoTag* setInfo = pItem->GetVideoInfoTag(); + setInfo->m_strPath = pItem->GetPath(); + setInfo->m_strTitle = pItem->GetLabel(); + + int ratings = 0; + int iWatched = 0; // have all the movies been played at least once? + for (std::set::const_iterator movie = set->second.begin(); movie != set->second.end(); movie++) + { + CVideoInfoTag* movieInfo = (*movie)->GetVideoInfoTag(); + // handle rating + if (movieInfo->m_fRating > 0.0f) + { + ratings++; + setInfo->m_fRating += movieInfo->m_fRating; + } + + // handle year + if (movieInfo->m_iYear > setInfo->m_iYear) + setInfo->m_iYear = movieInfo->m_iYear; + + // handle lastplayed + if (movieInfo->m_lastPlayed.IsValid() && movieInfo->m_lastPlayed > setInfo->m_lastPlayed) + setInfo->m_lastPlayed = movieInfo->m_lastPlayed; + + // handle dateadded + if (movieInfo->m_dateAdded.IsValid() && movieInfo->m_dateAdded > setInfo->m_dateAdded) + setInfo->m_dateAdded = movieInfo->m_dateAdded; + + // handle playcount/watched + setInfo->m_playCount += movieInfo->m_playCount; + if (movieInfo->m_playCount > 0) + iWatched++; + } + + if (ratings > 1) + pItem->GetVideoInfoTag()->m_fRating /= ratings; + + setInfo->m_playCount = iWatched >= (int)set->second.size() ? (setInfo->m_playCount / set->second.size()) : 0; + pItem->SetProperty("total", (int)set->second.size()); + pItem->SetProperty("watched", iWatched); + pItem->SetProperty("unwatched", (int)set->second.size() - iWatched); + pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, setInfo->m_playCount > 0); + + groupedItems.Add(pItem); + } + } + + return true; +} + +bool GroupUtils::GroupAndSort(GroupBy groupBy, const CFileItemList &items, const SortDescription &sortDescription, CFileItemList &groupedItems, GroupAttribute groupAttributes /* = GroupAttributeNone */) +{ + if (!Group(groupBy, items, groupedItems, groupAttributes)) + return false; + + groupedItems.Sort(sortDescription); + return true; +} diff --git a/xbmc/utils/GroupUtils.h b/xbmc/utils/GroupUtils.h new file mode 100644 index 0000000000..0e09450998 --- /dev/null +++ b/xbmc/utils/GroupUtils.h @@ -0,0 +1,42 @@ +#pragma once +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "SortUtils.h" + +class CFileItemList; + +// can be used as a flag +typedef enum { + GroupByNone = 0x0, + GroupBySet = 0x1 +} GroupBy; + +typedef enum { + GroupAttributeNone = 0x0, + GroupAttributeIgnoreSingleItems = 0x1 +} GroupAttribute; + +class GroupUtils +{ +public: + static bool Group(GroupBy groupBy, const CFileItemList &items, CFileItemList &groupedItems, GroupAttribute groupAttributes = GroupAttributeNone); + static bool GroupAndSort(GroupBy groupBy, const CFileItemList &items, const SortDescription &sortDescription, CFileItemList &groupedItems, GroupAttribute groupAttributes = GroupAttributeNone); +}; diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile index b2a5c5fc3b..d2018846d5 100644 --- a/xbmc/utils/Makefile +++ b/xbmc/utils/Makefile @@ -23,6 +23,7 @@ SRCS=AlarmClock.cpp \ fstrcmp.c \ fft.cpp \ GLUtils.cpp \ + GroupUtils.cpp \ HTMLTable.cpp \ HTMLUtil.cpp \ HttpHeader.cpp \ -- cgit v1.2.3 From 142ddeaf87564d00a3221520770a2738d61fa303 Mon Sep 17 00:00:00 2001 From: montellese Date: Wed, 12 Sep 2012 12:00:43 +0200 Subject: [win32] updated project files --- project/VS2010Express/XBMC.vcxproj | 2 ++ project/VS2010Express/XBMC.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index f0fd8c9f35..0ecd8896dd 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -1249,6 +1249,7 @@ true true + @@ -2395,6 +2396,7 @@ true true + diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 8923bfe3d7..4ff509fc01 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -2942,6 +2942,9 @@ filesystem + + utils + @@ -5749,6 +5752,9 @@ filesystem + + utils + -- cgit v1.2.3 From a88a8e76d0f300847fd42b0e13e317d41999f083 Mon Sep 17 00:00:00 2001 From: montellese Date: Thu, 28 Jun 2012 23:29:45 +0200 Subject: videodb: change retrieval of sets based on GroupUtils GetSetsByWhere calls GetMoviesByWhere with custom JOIN clauses to only retrieve movies being part of a set and the uses GroupUtils to group them into sets. GetMoviesByWhere (and therefore GetMoviesNav) returns a list of movies with no sets in it. To get sets GroupUtils::Group() has to be called afterwards. --- xbmc/filesystem/SmartPlaylistDirectory.cpp | 2 +- xbmc/utils/EdenVideoArtUpdater.cpp | 2 +- xbmc/video/VideoDatabase.cpp | 184 +++-------------------------- xbmc/video/VideoDatabase.h | 4 +- 4 files changed, 23 insertions(+), 169 deletions(-) diff --git a/xbmc/filesystem/SmartPlaylistDirectory.cpp b/xbmc/filesystem/SmartPlaylistDirectory.cpp index 175159f743..95c7a1cf65 100644 --- a/xbmc/filesystem/SmartPlaylistDirectory.cpp +++ b/xbmc/filesystem/SmartPlaylistDirectory.cpp @@ -114,7 +114,7 @@ namespace XFILE videoUrl.AddOption(option, xsp); CDatabase::Filter dbfilter; - success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, dbfilter, true); + success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, dbfilter); db.Close(); // if we retrieve a list of episodes and we didn't receive diff --git a/xbmc/utils/EdenVideoArtUpdater.cpp b/xbmc/utils/EdenVideoArtUpdater.cpp index 390f9a7ad5..7f221aa4bb 100644 --- a/xbmc/utils/EdenVideoArtUpdater.cpp +++ b/xbmc/utils/EdenVideoArtUpdater.cpp @@ -76,7 +76,7 @@ void CEdenVideoArtUpdater::Process() handle->SetTitle(g_localizeStrings.Get(12349)); // movies - db.GetMoviesByWhere("videodb://1/2/", CDatabase::Filter(), items, false); + db.GetMoviesByWhere("videodb://1/2/", CDatabase::Filter(), items); for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 8096edabfb..fc60e61d9e 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -55,6 +55,7 @@ #include "URL.h" #include "video/VideoDbUrl.h" #include "playlists/SmartPlayList.h" +#include "utils/GroupUtils.h" using namespace std; using namespace dbiplus; @@ -4815,111 +4816,21 @@ bool CVideoDatabase::GetSetsByWhere(const CStdString& strBaseDir, const Filter & if (!videoUrl.FromString(strBaseDir)) return false; - CStdString strSQL = "SELECT movieview.*, sets.strSet FROM movieview" - " JOIN sets ON movieview.idSet = sets.idSet "; - if (!filter.join.empty()) - strSQL += filter.join; - if (!filter.where.empty()) - strSQL += " WHERE (" + filter.where + ")"; - strSQL += " ORDER BY sets.idSet"; - if (!filter.order.empty()) - strSQL += "," + filter.order; - if (!filter.limit.empty()) - strSQL += " LIMIT " + filter.limit; + Filter setFilter = filter; + setFilter.join += " JOIN sets ON movieview.idSet = sets.idSet"; + if (!setFilter.order.empty()) + setFilter.order += ","; + setFilter.order += "sets.idSet"; - int iRowsFound = RunQuery(strSQL); - if (iRowsFound <= 0) - return iRowsFound == 0; - - map mapSets; - map::iterator it; - while (!m_pDS->eof()) - { - if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser && - !g_passwordManager.IsDatabasePathUnlocked(CStdString(m_pDS->fv("movieview.strPath").get_asString()),g_settings.m_videoSources)) - continue; - - // get the setid and check if we already have this set - int idSet = m_pDS->fv("movieview.idSet").get_asInt(); - if ((it = mapSets.find(idSet)) == mapSets.end()) - { - // add the set to the list of sets - CSetInfo set; - set.name = m_pDS->fv("sets.strSet").get_asString(); - - pair::iterator, bool> insertIt = mapSets.insert(make_pair(idSet, set)); - it = insertIt.first; - } - - // add the movie's details to the set - it->second.movies.push_back(GetDetailsForMovie(m_pDS)); - - m_pDS->next(); - } - m_pDS->close(); - - for (it = mapSets.begin(); it != mapSets.end(); it++) - { - // we only handle sets with at least 2 movies - if (it->second.movies.size() <= 0 || - (ignoreSingleMovieSets && it->second.movies.size() == 1)) - continue; - - CFileItemPtr pItem(new CFileItem(it->second.name)); - pItem->GetVideoInfoTag()->m_iDbId = it->first; - pItem->GetVideoInfoTag()->m_type = "set"; - - CVideoDbUrl itemUrl = videoUrl; - CStdString strDir; strDir.Format("%ld/", it->first); - itemUrl.AppendPath(strDir); - pItem->SetPath(itemUrl.ToString()); - - pItem->m_bIsFolder = true; - pItem->GetVideoInfoTag()->m_strPath = pItem->GetPath(); - pItem->GetVideoInfoTag()->m_strTitle = pItem->GetLabel(); + if (!GetMoviesByWhere(strBaseDir, setFilter, items)) + return false; - // calculate the remaining metadata from the movies - int ratings = 0; - int iWatched = 0; // have all the movies been played at least once? - for (VECMOVIES::const_iterator movie = it->second.movies.begin(); movie != it->second.movies.end(); movie++) - { - // handle rating - if (movie->m_fRating > 0.0f) - { - ratings++; - pItem->GetVideoInfoTag()->m_fRating += movie->m_fRating; - } - - // handle year - if (movie->m_iYear > pItem->GetVideoInfoTag()->m_iYear) - pItem->GetVideoInfoTag()->m_iYear = movie->m_iYear; - - // handle lastplayed - if (movie->m_lastPlayed.IsValid() && movie->m_lastPlayed > pItem->GetVideoInfoTag()->m_lastPlayed) - pItem->GetVideoInfoTag()->m_lastPlayed = movie->m_lastPlayed; - - // handle dateadded - if (movie->m_dateAdded.IsValid() && movie->m_dateAdded > pItem->GetVideoInfoTag()->m_dateAdded) - pItem->GetVideoInfoTag()->m_dateAdded = movie->m_dateAdded; - - // handle playcount/watched - pItem->GetVideoInfoTag()->m_playCount += movie->m_playCount; - if (movie->m_playCount > 0) - iWatched++; - } - - if (ratings > 1) - pItem->GetVideoInfoTag()->m_fRating /= ratings; - - pItem->GetVideoInfoTag()->m_playCount = iWatched >= (int)it->second.movies.size() ? (pItem->GetVideoInfoTag()->m_playCount / it->second.movies.size()) : 0; - pItem->SetProperty("total", (int)it->second.movies.size()); - pItem->SetProperty("watched", iWatched); - pItem->SetProperty("unwatched", (int)it->second.movies.size() - iWatched); - pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pItem->GetVideoInfoTag()->m_playCount > 0); + CFileItemList sets; + if (!GroupUtils::Group(GroupBySet, items, sets)) + return false; - if (!items.Contains(pItem->GetPath())) - items.Add(pItem); - } + items.ClearItems(); + items.Append(sets); return true; } @@ -5686,7 +5597,7 @@ bool CVideoDatabase::GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& return false; } -bool CVideoDatabase::GetSortedVideos(MediaType mediaType, const CStdString& strBaseDir, const SortDescription &sortDescription, CFileItemList& items, const Filter &filter /* = Filter() */, bool fetchSets /* = false */) +bool CVideoDatabase::GetSortedVideos(MediaType mediaType, const CStdString& strBaseDir, const SortDescription &sortDescription, CFileItemList& items, const Filter &filter /* = Filter() */) { if (NULL == m_pDB.get() || NULL == m_pDS.get()) return false; @@ -5710,7 +5621,7 @@ bool CVideoDatabase::GetSortedVideos(MediaType mediaType, const CStdString& strB switch (mediaType) { case MediaTypeMovie: - success = GetMoviesByWhere(strBaseDir, filter, items, fetchSets, sorting); + success = GetMoviesByWhere(strBaseDir, filter, items, sorting); break; case MediaTypeTvShow: @@ -5760,10 +5671,10 @@ bool CVideoDatabase::GetMoviesNav(const CStdString& strBaseDir, CFileItemList& i videoUrl.AddOption("tagid", idTag); Filter filter; - return GetMoviesByWhere(videoUrl.ToString(), filter, items, idSet == -1, sortDescription); + return GetMoviesByWhere(videoUrl.ToString(), filter, items, sortDescription); } -bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, bool fetchSets /* = false */, const SortDescription &sortDescription /* = SortDescription() */) +bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */) { try { @@ -5780,50 +5691,10 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter if (!videoUrl.FromString(strBaseDir) || !GetFilter(videoUrl, extFilter, sorting)) return false; - // if we have a "setid" option we don't want to retrieve sets - CVariant setId; - if (fetchSets && videoUrl.GetOption("setid", setId) && - setId.isInteger() && setId.asInteger() > 0) - fetchSets = false; - int total = -1; CStdString strSQL = "select %s from movieview "; CStdString strSQLExtra; - CFileItemList setItems; - if (fetchSets && g_guiSettings.GetBool("videolibrary.groupmoviesets")) - { - // user wants sets (and we're not fetching a particular set node), so grab all sets that match this where clause first - Filter setsFilter; - if (!extFilter.where.empty() || !extFilter.join.empty()) - { - setsFilter.where = "movieview.idMovie in (select movieview.idMovie from movieview "; - if (!extFilter.join.empty()) - setsFilter.where += extFilter.join; - if (!extFilter.where.empty()) - setsFilter.where += " WHERE " + extFilter.where; - setsFilter.where += ")"; - } - - CVideoDbUrl setUrl; - if (!setUrl.FromString("videodb://1/7/")) - return false; - - setUrl.AddOptions(videoUrl.GetOptionsString()); - GetSetsByWhere(setUrl.ToString(), setsFilter, setItems, true); - - CStdString movieSetsWhere; - if (setItems.Size() > 0) - { - movieSetsWhere = "movieview.idMovie NOT IN (SELECT idMovie FROM movieview WHERE movieview.idSet IN ("; - for (int index = 0; index < setItems.Size(); index++) - movieSetsWhere.AppendFormat("%s%d", index > 0 ? "," : "", setItems[index]->GetVideoInfoTag()->m_iDbId); - movieSetsWhere += "))"; - - extFilter.AppendWhere(movieSetsWhere); - } - } - if (!CDatabase::BuildSQL(strSQLExtra, extFilter, strSQLExtra)) return false; @@ -5839,10 +5710,9 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter strSQL = PrepareSQL(strSQL, !extFilter.fields.empty() ? extFilter.fields.c_str() : "*") + strSQLExtra; int iRowsFound = RunQuery(strSQL); - if (iRowsFound <= 0 && setItems.Size() == 0) + if (iRowsFound <= 0) return iRowsFound == 0; - iRowsFound += setItems.Size(); // store the total value of items as a property if (total < iRowsFound) total = iRowsFound; @@ -5851,16 +5721,7 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter DatabaseResults results; results.reserve(iRowsFound); - // Add the previously retrieved sets - for (int index = 0; index < setItems.Size(); index++) - { - DatabaseResult result; - setItems[index]->ToSortable(result); - result[FieldRow] = (unsigned int)index; - results.push_back(result); - } - - if (!SortUtils::SortFromDataset(sorting, MediaTypeMovie, m_pDS, results)) + if (!SortUtils::SortFromDataset(sortDescription, MediaTypeMovie, m_pDS, results)) return false; // get data from returned rows @@ -5869,13 +5730,6 @@ bool CVideoDatabase::GetMoviesByWhere(const CStdString& strBaseDir, const Filter for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); it++) { unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger(); - if (targetRow < (unsigned int)setItems.Size()) - { - items.Add(setItems[targetRow]); - continue; - } - targetRow -= setItems.Size(); - const dbiplus::sql_record* const record = data.at(targetRow); CVideoInfoTag movie = GetDetailsForMovie(record); diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h index 225dc4964d..13de593dbb 100644 --- a/xbmc/video/VideoDatabase.h +++ b/xbmc/video/VideoDatabase.h @@ -640,14 +640,14 @@ public: bool ImportArtFromXML(const TiXmlNode *node, std::map &artwork); // smart playlists and main retrieval work in these functions - bool GetMoviesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, bool fetchSets = false, const SortDescription &sortDescription = SortDescription()); + bool GetMoviesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); bool GetSetsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, bool ignoreSingleMovieSets = false); bool GetTvShowsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription()); bool GetEpisodesByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, bool appendFullShowPath = true, const SortDescription &sortDescription = SortDescription()); bool GetMusicVideosByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList& items, bool checkLocks = true, const SortDescription &sortDescription = SortDescription()); // retrieve sorted and limited items - bool GetSortedVideos(MediaType mediaType, const CStdString& strBaseDir, const SortDescription &sortDescription, CFileItemList& items, const Filter &filter = Filter(), bool fetchSets = false); + bool GetSortedVideos(MediaType mediaType, const CStdString& strBaseDir, const SortDescription &sortDescription, CFileItemList& items, const Filter &filter = Filter()); // partymode int GetMusicVideoCount(const CStdString& strWhere); -- cgit v1.2.3 From fc44e6f9914231e013ba2799ddbc512de0145fd3 Mon Sep 17 00:00:00 2001 From: montellese Date: Wed, 12 Sep 2012 17:28:37 +0200 Subject: media library: integrate grouping by sets --- xbmc/video/windows/GUIWindowVideoBase.cpp | 19 +++++- xbmc/video/windows/GUIWindowVideoBase.h | 2 +- xbmc/video/windows/GUIWindowVideoNav.cpp | 17 ++--- xbmc/windows/GUIMediaWindow.cpp | 102 +++++++++++++++++++----------- xbmc/windows/GUIMediaWindow.h | 4 +- 5 files changed, 90 insertions(+), 54 deletions(-) diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index a147bf3252..d6fec70331 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -71,6 +71,7 @@ #include "URL.h" #include "utils/EdenVideoArtUpdater.h" #include "GUIInfoManager.h" +#include "utils/GroupUtils.h" using namespace std; using namespace XFILE; @@ -1839,8 +1840,24 @@ bool CGUIWindowVideoBase::StackingAvailable(const CFileItemList &items) const url.GetProtocol() == "playlistvideo"); } -void CGUIWindowVideoBase::OnPrepareFileItems(CFileItemList &items) +void CGUIWindowVideoBase::GetGroupedItems(CFileItemList &items) { + CGUIMediaWindow::GetGroupedItems(items); + + CQueryParams params; + CVideoDatabaseDirectory dir; + dir.GetQueryParams(items.GetPath(), params); + if (items.GetContent().Equals("movies") && params.GetSetId() <= 0 && + CVideoDatabaseDirectory::GetDirectoryChildType(items.GetPath()) != NODE_TYPE_RECENTLY_ADDED_MOVIES && + g_guiSettings.GetBool("videolibrary.groupmoviesets")) + { + CFileItemList groupedItems; + if (GroupUtils::Group(GroupBySet, items, groupedItems, GroupAttributeIgnoreSingleItems)) + { + items.ClearItems(); + items.Append(groupedItems); + } + } } bool CGUIWindowVideoBase::CheckFilterAdvanced(CFileItemList &items) const diff --git a/xbmc/video/windows/GUIWindowVideoBase.h b/xbmc/video/windows/GUIWindowVideoBase.h index b4d555db9a..439f6c28d1 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.h +++ b/xbmc/video/windows/GUIWindowVideoBase.h @@ -88,7 +88,7 @@ protected: virtual bool Update(const CStdString &strDirectory, bool updateFilterPath = true); virtual bool GetDirectory(const CStdString &strDirectory, CFileItemList &items); virtual void OnItemLoaded(CFileItem* pItem) {}; - virtual void OnPrepareFileItems(CFileItemList &items); + virtual void GetGroupedItems(CFileItemList &items); virtual bool CheckFilterAdvanced(CFileItemList &items) const; virtual bool CanContainFilter(const CStdString &strDirectory) const; diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index fab7d9d808..a4e9c7ccbb 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -537,23 +537,14 @@ void CGUIWindowVideoNav::UpdateButtons() bool CGUIWindowVideoNav::GetFilteredItems(const CStdString &filter, CFileItemList &items) { - bool listchanged = false; - bool updateItems = false; - if (!m_canFilterAdvanced) - listchanged = CGUIMediaWindow::GetFilteredItems(filter, items); - else - listchanged = CGUIMediaWindow::GetAdvanceFilteredItems(items, updateItems); - + bool listchanged = CGUIMediaWindow::GetFilteredItems(filter, items); listchanged |= ApplyWatchedFilter(items); // there are new items so we need to run the thumbloader - if (updateItems) - { - if (m_thumbLoader.IsLoading()) - m_thumbLoader.StopThread(); + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); - m_thumbLoader.Load(items); - } + m_thumbLoader.Load(items); return listchanged; } diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index bf01668354..0f391b61ab 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -617,10 +617,6 @@ void CGUIMediaWindow::SortItems(CFileItemList &items) if (!sorted) items.Sort(sortMethod, guiState->GetDisplaySortOrder()); - - // Should these items be saved to the hdd - if (items.CacheToDiscAlways() && !IsFiltered()) - items.Save(GetID()); } } @@ -657,8 +653,9 @@ void CGUIMediaWindow::FormatAndSort(CFileItemList &items) LABEL_MASKS labelMasks; viewState->GetSortMethodLabelMasks(labelMasks); FormatItemLabels(items, labelMasks); + + items.Sort(viewState->GetSortMethod(), viewState->GetDisplaySortOrder()); } - SortItems(items); } /*! @@ -892,7 +889,16 @@ bool CGUIMediaWindow::Update(const CStdString &strDirectory, bool updateFilterPa m_guiState.reset(CGUIViewState::GetViewState(GetID(), *m_vecItems)); - FormatAndSort(*m_vecItems); + // remember the original (untouched) list of items (for filtering etc) + m_unfilteredItems->SetPath(m_vecItems->GetPath()); // use the original path - it'll likely be relied on for other things later. + m_unfilteredItems->Append(*m_vecItems); + + // Cache the list of items if possible + OnCacheFileItems(*m_vecItems); + + // Filter and group the items if necessary + CStdString titleFilter = GetProperty("filter").asString(); + OnFilterItems(titleFilter); // Ask the devived class if it wants to do custom list operations, // eg. changing the label @@ -968,17 +974,22 @@ void CGUIMediaWindow::OnPrepareFileItems(CFileItemList &items) } +// \brief This function will be called by Update() before +// any additional formatting, filtering or sorting is applied. +// Override this function to define a custom caching behaviour. +void CGUIMediaWindow::OnCacheFileItems(CFileItemList &items) +{ + // Should these items be saved to the hdd + if (items.CacheToDiscAlways() && !IsFiltered()) + items.Save(GetID()); +} + // \brief This function will be called by Update() after the // labels of the fileitems are formatted. Override this function // to modify the fileitems. Eg. to modify the item label void CGUIMediaWindow::OnFinalizeFileItems(CFileItemList &items) { - m_unfilteredItems->SetPath(items.GetPath()); // use the original path - it'll likely be relied on for other things later. - m_unfilteredItems->Append(items); - - CStdString filter(GetProperty("filter").asString()); - OnFilterItems(filter); } // \brief With this function you can react on a users click in the list/thumb panel. @@ -1695,24 +1706,52 @@ void CGUIMediaWindow::OnFilterItems(const CStdString &filter) CFileItemList items(m_vecItems->GetPath()); // use the original path - it'll likely be relied on for other things later. items.Append(*m_unfilteredItems); - if (GetFilteredItems(filter, items) || m_vecItems->Size() != items.Size()) + bool filtered = GetFilteredItems(filter, items); + + m_vecItems->ClearItems(); + // we need to clear the sort state and re-sort the items + m_vecItems->ClearSortState(); + m_vecItems->Append(items); + + // if the filter has changed, get the new filter path + if (filtered && m_canFilterAdvanced) { - m_vecItems->ClearItems(); - m_vecItems->Append(items); + if (items.HasProperty(PROPERTY_PATH_DB)) + m_strFilterPath = items.GetProperty(PROPERTY_PATH_DB).asString(); + else + m_strFilterPath = items.GetPath(); + } + + GetGroupedItems(*m_vecItems); + FormatAndSort(*m_vecItems); - // we need to clear the sort state and re-sort the items - m_vecItems->ClearSortState(); - SortItems(*m_vecItems); + // get the "filter" option + CStdString filterOption; + CURL filterUrl(m_strFilterPath); + if (filterUrl.HasOption("filter")) + filterOption = filterUrl.GetOption("filter"); + + // apply the "filter" option to any folder item so that + // the filter can be passed down to the sub-directory + for (int index = 0; index < m_vecItems->Size(); index++) + { + CFileItemPtr pItem = m_vecItems->Get(index); + // if the item is a folder we need to copy the path of + // the filtered item to be able to keep the applied filters + if (pItem->m_bIsFolder) + { + CURL itemUrl(pItem->GetPath()); + itemUrl.SetOption("filter", filterOption); + pItem->SetPath(itemUrl.Get()); + } + } + if (filtered) + { if (!m_canFilterAdvanced) SetProperty("filter", filter); else { - if (items.HasProperty(PROPERTY_PATH_DB)) - m_strFilterPath = items.GetProperty(PROPERTY_PATH_DB).asString(); - else - m_strFilterPath = items.GetPath(); - // to be able to select the same item as before we need to adjust // the path of the item i.e. add or remove the "filter=" URL option // but that's only necessary for folder items @@ -1738,10 +1777,7 @@ void CGUIMediaWindow::OnFilterItems(const CStdString &filter) bool CGUIMediaWindow::GetFilteredItems(const CStdString &filter, CFileItemList &items) { if (m_canFilterAdvanced) - { - bool hasNewItems; - return GetAdvanceFilteredItems(items, hasNewItems); - } + return GetAdvanceFilteredItems(items); CStdString trimmedFilter(filter); trimmedFilter.TrimLeft().ToLower(); @@ -1786,10 +1822,8 @@ bool CGUIMediaWindow::GetFilteredItems(const CStdString &filter, CFileItemList & return items.GetObjectCount() > 0; } -bool CGUIMediaWindow::GetAdvanceFilteredItems(CFileItemList &items, bool &hasNewItems) +bool CGUIMediaWindow::GetAdvanceFilteredItems(CFileItemList &items) { - hasNewItems = false; - // don't run the advanced filter if the filter is empty // and there hasn't been a filter applied before which // would have to be removed @@ -1831,11 +1865,6 @@ bool CGUIMediaWindow::GetAdvanceFilteredItems(CFileItemList &items, bool &hasNew map::iterator itItem = lookup.find(path); if (itItem != lookup.end()) { - // if the item is a folder we need to copy the path of - // the filtered item to be able to keep the applied filters - if (item->m_bIsFolder) - item->SetPath(itItem->second->GetPath()); - // add the item to the list of filtered items filteredItems.Add(item); @@ -1846,10 +1875,7 @@ bool CGUIMediaWindow::GetAdvanceFilteredItems(CFileItemList &items, bool &hasNew } if (resultItems.Size() > 0) - { - filteredItems.Append(resultItems); - hasNewItems = true; - } + CLog::Log(LOGWARNING, "CGUIMediaWindow::GetAdvanceFilteredItems(): %d unknown items", resultItems.Size()); items.ClearItems(); items.Append(filteredItems); diff --git a/xbmc/windows/GUIMediaWindow.h b/xbmc/windows/GUIMediaWindow.h index b8230432e5..aa1ae3dbde 100644 --- a/xbmc/windows/GUIMediaWindow.h +++ b/xbmc/windows/GUIMediaWindow.h @@ -86,7 +86,9 @@ protected: virtual bool Refresh(bool clearCache = false); virtual void FormatAndSort(CFileItemList &items); virtual void OnPrepareFileItems(CFileItemList &items); + virtual void OnCacheFileItems(CFileItemList &items); virtual void OnFinalizeFileItems(CFileItemList &items); + virtual void GetGroupedItems(CFileItemList &items) { } void ClearFileItems(); virtual void SortItems(CFileItemList &items); @@ -123,7 +125,7 @@ protected: which were not present in the original list \sa GetFilteredItems */ - virtual bool GetAdvanceFilteredItems(CFileItemList &items, bool &hasNewItems); + virtual bool GetAdvanceFilteredItems(CFileItemList &items); // check for a disc or connection virtual bool HaveDiscOrConnection(const CStdString& strPath, int iDriveType); -- cgit v1.2.3 From 8c517ac2360d457bf752e964988ba098697a58b0 Mon Sep 17 00:00:00 2001 From: montellese Date: Thu, 4 Oct 2012 22:04:41 +0200 Subject: CGUIWindowVideoBase: always exectue the videothumbloader after filtering and grouping --- xbmc/video/windows/GUIWindowVideoBase.cpp | 10 +++++++++- xbmc/video/windows/GUIWindowVideoNav.cpp | 6 ------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index d6fec70331..937f8b7d4c 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -1788,7 +1788,9 @@ bool CGUIWindowVideoBase::Update(const CStdString &strDirectory, bool updateFilt if (!CGUIMediaWindow::Update(strDirectory, updateFilterPath)) return false; - m_thumbLoader.Load(*m_unfilteredItems); + // might already be running from GetGroupedItems + if (!m_thumbLoader.IsLoading()) + m_thumbLoader.Load(*m_vecItems); return true; } @@ -1858,6 +1860,12 @@ void CGUIWindowVideoBase::GetGroupedItems(CFileItemList &items) items.Append(groupedItems); } } + + // reload thumbs after filtering and grouping + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); + + m_thumbLoader.Load(items); } bool CGUIWindowVideoBase::CheckFilterAdvanced(CFileItemList &items) const diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index a4e9c7ccbb..8a268805cc 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -540,12 +540,6 @@ bool CGUIWindowVideoNav::GetFilteredItems(const CStdString &filter, CFileItemLis bool listchanged = CGUIMediaWindow::GetFilteredItems(filter, items); listchanged |= ApplyWatchedFilter(items); - // there are new items so we need to run the thumbloader - if (m_thumbLoader.IsLoading()) - m_thumbLoader.StopThread(); - - m_thumbLoader.Load(items); - return listchanged; } -- cgit v1.2.3