From 8c7f35d638437d031b142ed9a3cbdb41e5d9b6e9 Mon Sep 17 00:00:00 2001 From: Carcharius Date: Mon, 23 Feb 2015 12:42:04 +0000 Subject: [PATCH] [video] refactor select first unwatched season/episode item Undo previous changes made to add selection of first unplayed item. Add settings videolibrary.tvshowselectfirstunwatcheditem (renamed from videolibrary.jumptofirstunplayeditem) and videolibrary.tvshowsincludeallseasonsandspecials Add unwatched item selection to CGUIWindowVideoNav. --- language/English/strings.po | 51 +++++++++-- system/settings/settings.xml | 29 +++++- xbmc/video/GUIViewStateVideo.cpp | 25 ------ xbmc/video/GUIViewStateVideo.h | 1 - xbmc/video/windows/GUIWindowVideoNav.cpp | 108 +++++++++++++++++++++++ xbmc/video/windows/GUIWindowVideoNav.h | 22 +++++ xbmc/view/GUIViewState.cpp | 5 -- xbmc/view/GUIViewState.h | 1 - xbmc/windows/GUIMediaWindow.cpp | 30 +------ 9 files changed, 204 insertions(+), 68 deletions(-) diff --git a/language/English/strings.po b/language/English/strings.po index bc39872e6523e..0023f0f91701f 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -11338,7 +11338,7 @@ msgstr "" #: system/settings/settings.xml msgctxt "#21416" -msgid "Jump to first unwatched TV show season/episode" +msgid "Select the first unwatched TV show season/episode" msgstr "" #: system/settings/settings.xml @@ -11562,10 +11562,10 @@ msgctxt "#21465" msgid "Above video" msgstr "" -#. Description of setting "Videos -> Library -> Jump to first unwatched TV show season/episode" with label #21416 +#. Description of setting "Videos -> Library -> Select first unwatched TV show season/episode" with label #21416 #: system/settings/settings.xml msgctxt "#21466" -msgid "When entering a TV show season or episode view automatically jump to the first unwatched season or episode." +msgid "When entering a TV show season or episode view automatically select the first unwatched season or episode. [On first entry] the first unwatched item will be selected only when a view is entered for the first time. [Always] the first unwatched item will be selected every time a view is entered." msgstr "" #. Filter (media data) from float value to float value @@ -11593,7 +11593,48 @@ msgctxt "#21470" msgid "%s [%d]" msgstr "" -#empty strings from id 21471 to 21601 +#. One of the values valid for "Videos -> Library -> Select first unwatched TV show season/episode" with label #21416 +#: system/settings/settings.xml +msgctxt "#21471" +msgid "On first entry" +msgstr "" + +#: system/settings/settings.xml +msgctxt "#21472" +msgid "Include All Seasons and Specials" +msgstr "" + +#. Description of setting "Videos -> Library -> Include All Seasons and Specials" with label #21472 +#: system/settings/settings.xml +msgctxt "#21473" +msgid "Whether or not to consider All Seasons and Special items in the unwatched item selection." +msgstr "" + +#. One of the values valid for "Videos -> Library -> Include All Seasons and Specials" with label #21472 +#: system/settings/settings.xml +msgctxt "#21474" +msgid "Neither" +msgstr "" + +#. One of the values valid for "Videos -> Library -> Include All Seasons and Specials" with label #21472 +#: system/settings/settings.xml +msgctxt "#21475" +msgid "Both" +msgstr "" + +#. One of the values valid for "Videos -> Library -> Include All Seasons and Specials" with label #21472 +#: system/settings/settings.xml +msgctxt "#21476" +msgid "Just All Seasons" +msgstr "" + +#. One of the values valid for "Videos -> Library -> Include All Seasons and Specials" with label #21472 +#: system/settings/settings.xml +msgctxt "#21477" +msgid "Just Specials" +msgstr "" + +#empty strings from id 21478 to 21601 #: xbmc/Util.cpp msgctxt "#21602" @@ -16346,4 +16387,4 @@ msgstr "" #: system/settings/settings.xml msgctxt "#38012" msgid "Hide "All Items" entry in directory (for example All Albums or All Seasons)" -msgstr "" \ No newline at end of file +msgstr "" diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 12a57652de603..beb316f257258 100644 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -349,10 +349,33 @@ - + 1 - false - + 0 + + + + + + + + + + + 2 + 0 + + + + + + + + + + 0 + + 2 diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp index 2d4a3fc9adbb9..21cc661a8ef2d 100644 --- a/xbmc/video/GUIViewStateVideo.cpp +++ b/xbmc/video/GUIViewStateVideo.cpp @@ -436,31 +436,6 @@ bool CGUIViewStateWindowVideoNav::AutoPlayNextItem() return CSettings::Get().GetBool("videoplayer.autoplaynextitem"); } -bool CGUIViewStateWindowVideoNav::JumpToFirstUnplayedItem() -{ - if (m_items.IsVideoDb()) - { - NODE_TYPE NodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_items.GetPath()); - switch (NodeType) - { - case NODE_TYPE_EPISODES: - if (GetSortMethod().sortBy == SortBy::SortByEpisodeNumber) - return CSettings::Get().GetBool("videolibrary.jumptofirstunplayeditem"); - else - return false; - - case NODE_TYPE_SEASONS: - return CSettings::Get().GetBool("videolibrary.jumptofirstunplayeditem"); - - default: - return false; - break; - } - } - - return CGUIViewStateWindowVideo::JumpToFirstUnplayedItem(); -} - CGUIViewStateWindowVideoPlaylist::CGUIViewStateWindowVideoPlaylist(const CFileItemList& items) : CGUIViewStateWindowVideo(items) { AddSortMethod(SortByNone, 551, LABEL_MASKS("%L", "", "%L", "")); // Label, empty | Label, empty diff --git a/xbmc/video/GUIViewStateVideo.h b/xbmc/video/GUIViewStateVideo.h index 532e59aa6ffdd..31d7dba5cdc4d 100644 --- a/xbmc/video/GUIViewStateVideo.h +++ b/xbmc/video/GUIViewStateVideo.h @@ -49,7 +49,6 @@ class CGUIViewStateWindowVideoNav : public CGUIViewStateWindowVideo public: CGUIViewStateWindowVideoNav(const CFileItemList& items); virtual bool AutoPlayNextItem(); - virtual bool JumpToFirstUnplayedItem(); protected: virtual void SaveViewState(); diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index bf60f81d63a00..118ed43471889 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -269,6 +269,114 @@ std::string CGUIWindowVideoNav::GetQuickpathName(const std::string& strPath) con } } +SelectFirstUnwatchedItem CGUIWindowVideoNav::GetSettingSelectFirstUnwatchedItem() +{ + if (m_vecItems->IsVideoDb()) + { + NODE_TYPE nodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_vecItems->GetPath()); + + if (nodeType == NODE_TYPE_SEASONS || nodeType == NODE_TYPE_EPISODES) + { + int iValue = CSettings::Get().GetInt("videolibrary.tvshowsselectfirstunwatcheditem"); + if (iValue >= SelectFirstUnwatchedItem::NEVER && iValue <= SelectFirstUnwatchedItem::ALWAYS) + return (SelectFirstUnwatchedItem)iValue; + } + } + + return SelectFirstUnwatchedItem::NEVER; +} + +IncludeAllSeasonsAndSpecials CGUIWindowVideoNav::GetSettingIncludeAllSeasonsAndSpecials() +{ + int iValue = CSettings::Get().GetInt("videolibrary.tvshowsincludeallseasonsandspecials"); + if (iValue >= IncludeAllSeasonsAndSpecials::NEITHER && iValue <= IncludeAllSeasonsAndSpecials::SPECIALS) + return (IncludeAllSeasonsAndSpecials)iValue; + + return IncludeAllSeasonsAndSpecials::NEITHER; +} + +int CGUIWindowVideoNav::GetFirstUnwatchedItemIndex(bool includeAllSeasons, bool includeSpecials) +{ + int iIndex = 0; + int iUnwatchedSeason = INT_MAX; + + // Run through the list of items and find the season number of the first season with unwatched episodes + for (int i = 0; i < m_vecItems->Size(); ++i) + { + CFileItemPtr pItem = m_vecItems->Get(i); + if (pItem->IsParentFolder() || !pItem->HasVideoInfoTag()) + continue; + + CVideoInfoTag *pTag = pItem->GetVideoInfoTag(); + + if ((!includeAllSeasons && pTag->m_iSeason < 0) || (!includeSpecials && pTag->m_iSeason == 0)) + continue; + + // Is the season unwatched, and is its season number lower than the currently identified + // first unwatched season + if (pTag->m_playCount == 0 && pTag->m_iSeason < iUnwatchedSeason) + { + iUnwatchedSeason = pTag->m_iSeason; + iIndex = i; + } + } + + NODE_TYPE nodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_vecItems->GetPath()); + if (nodeType == NODE_TYPE::NODE_TYPE_EPISODES) + { + iIndex = 0; + int iUnwatchedEpisode = INT_MAX; + + // Now run through the list of items and check episodes from the season identified above + // to find the first (lowest episode number) unwatched epsisode. + for (int i = 0; i < m_vecItems->Size(); ++i) + { + CFileItemPtr pItem = m_vecItems->Get(i); + if (pItem->IsParentFolder() || !pItem->HasVideoInfoTag()) + continue; + + CVideoInfoTag *pTag = pItem->GetVideoInfoTag(); + + // Does the episode belong to the unwatched season and Is the episode unwatched, and is its epsiode number + // lower than the currently identified first unwatched episode + if (pTag->m_iSeason == iUnwatchedSeason && pTag->m_playCount == 0 && pTag->m_iEpisode < iUnwatchedEpisode) + { + iUnwatchedEpisode = pTag->m_iEpisode; + iIndex = i; + } + } + } + + return iIndex; +} + +bool CGUIWindowVideoNav::Update(const std::string &strDirectory, bool updateFilterPath /* = true */) +{ + if (!CGUIWindowVideoBase::Update(strDirectory, updateFilterPath)) + return false; + + // Check if we should select the first unwatched item + SelectFirstUnwatchedItem selectFirstUnwatched = GetSettingSelectFirstUnwatchedItem(); + if (selectFirstUnwatched != SelectFirstUnwatchedItem::NEVER) + { + bool bIsItemSelected = (m_viewControl.GetSelectedItem() > 0); + + if (selectFirstUnwatched == SelectFirstUnwatchedItem::ALWAYS || + (selectFirstUnwatched == SelectFirstUnwatchedItem::ON_FIRST_ENTRY && !bIsItemSelected)) + { + IncludeAllSeasonsAndSpecials incAllSeasonsSpecials = GetSettingIncludeAllSeasonsAndSpecials(); + + bool bIncludeAllSeasons = (incAllSeasonsSpecials == IncludeAllSeasonsAndSpecials::BOTH || incAllSeasonsSpecials == IncludeAllSeasonsAndSpecials::ALL_SEASONS); + bool bIncludeSpecials = (incAllSeasonsSpecials == IncludeAllSeasonsAndSpecials::BOTH || incAllSeasonsSpecials == IncludeAllSeasonsAndSpecials::SPECIALS); + + int iIndex = GetFirstUnwatchedItemIndex(bIncludeAllSeasons, bIncludeSpecials); + m_viewControl.SetSelectedItem(iIndex); + } + } + + return true; +} + bool CGUIWindowVideoNav::GetDirectory(const std::string &strDirectory, CFileItemList &items) { if (m_thumbLoader.IsLoading()) diff --git a/xbmc/video/windows/GUIWindowVideoNav.h b/xbmc/video/windows/GUIWindowVideoNav.h index c91c6a652b2a9..f828135546cc2 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.h +++ b/xbmc/video/windows/GUIWindowVideoNav.h @@ -24,6 +24,21 @@ class CFileItemList; +enum SelectFirstUnwatchedItem +{ + NEVER = 0, + ON_FIRST_ENTRY = 1, + ALWAYS = 2 +}; + +enum IncludeAllSeasonsAndSpecials +{ + NEITHER = 0, + BOTH = 1, + ALL_SEASONS = 2, + SPECIALS = 3 +}; + class CGUIWindowVideoNav : public CGUIWindowVideoBase { public: @@ -55,7 +70,9 @@ class CGUIWindowVideoNav : public CGUIWindowVideoBase virtual bool GetFilteredItems(const std::string &filter, CFileItemList &items); virtual void OnItemLoaded(CFileItem* pItem) {}; + // override base class methods + virtual bool Update(const std::string &strDirectory, bool updateFilterPath = true); virtual bool GetDirectory(const std::string &strDirectory, CFileItemList &items); virtual void UpdateButtons(); virtual void DoSearch(const std::string& strSearch, CFileItemList& items); @@ -69,4 +86,9 @@ class CGUIWindowVideoNav : public CGUIWindowVideoBase virtual std::string GetQuickpathName(const std::string& strPath) const; VECSOURCES m_shares; + +private: + virtual SelectFirstUnwatchedItem GetSettingSelectFirstUnwatchedItem(); + virtual IncludeAllSeasonsAndSpecials GetSettingIncludeAllSeasonsAndSpecials(); + virtual int GetFirstUnwatchedItemIndex(bool includeAllSeasons, bool includeSpecials); }; diff --git a/xbmc/view/GUIViewState.cpp b/xbmc/view/GUIViewState.cpp index e2988a1f9f574..fbc81be19a23a 100644 --- a/xbmc/view/GUIViewState.cpp +++ b/xbmc/view/GUIViewState.cpp @@ -395,11 +395,6 @@ bool CGUIViewState::AutoPlayNextItem() return false; } -bool CGUIViewState::JumpToFirstUnplayedItem() -{ - return false; -} - std::string CGUIViewState::GetLockType() { return ""; diff --git a/xbmc/view/GUIViewState.h b/xbmc/view/GUIViewState.h index 2b207951edbb9..2a6eba6feb8a0 100644 --- a/xbmc/view/GUIViewState.h +++ b/xbmc/view/GUIViewState.h @@ -56,7 +56,6 @@ class CGUIViewState void SetPlaylistDirectory(const std::string& strDirectory); bool IsCurrentPlaylistDirectory(const std::string& strDirectory); virtual bool AutoPlayNextItem(); - virtual bool JumpToFirstUnplayedItem(); virtual std::string GetLockType(); virtual std::string GetExtensions(); diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 9d7d5db7bc6e1..52ce0d6cb57ff 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -853,35 +853,9 @@ bool CGUIMediaWindow::Update(const std::string &strDirectory, bool updateFilterP } } - // if we haven't found the selected item, see if we should select the first unplayed item - // if yes, find the first unplayed item and select it - // if no, select the first item + // if we haven't found the selected item, select the first item if (!bSelectedFound) - { - int iIndex = 0; // index of the item to select, default to the first item - - // Check if we should select the first unplayed item - if (m_guiState.get()->JumpToFirstUnplayedItem()) - { - // Find the index of the - for (int i = 0; i < m_vecItems->Size(); ++i) - { - CFileItemPtr pItem = m_vecItems->Get(i); - // We don't want to jump to the parent folder item or an All Seasons item - if (pItem->IsParentFolder() || !pItem->HasVideoInfoTag() || - (pItem->GetVideoInfoTag()->m_type == MediaTypeSeason && pItem->GetVideoInfoTag()->m_iSeason < 0)) - continue; - - if (pItem->GetVideoInfoTag()->m_playCount == 0) - { - iIndex = i; - break; - } - } - } - - m_viewControl.SetSelectedItem(iIndex); - } + m_viewControl.SetSelectedItem(0); m_history.AddPath(m_vecItems->GetPath(), m_strFilterPath);