diff options
author | montellese <montellese@xbmc.org> | 2012-06-30 13:20:45 +0200 |
---|---|---|
committer | montellese <montellese@xbmc.org> | 2012-07-08 23:36:03 +0200 |
commit | d6c13e210ae014c4f48934221f93e5ab721d53c1 (patch) | |
tree | 9009041c2767b3dd04c1251689e7c9141b82154b | |
parent | 29a16cd499f34ea8fc507f124d7b85ba5ef077ec (diff) |
integrate new "Tags" node into the video library
18 files changed, 404 insertions, 12 deletions
diff --git a/language/English/strings.po b/language/English/strings.po index 8219f01e2a..68ef88adb7 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -7427,8 +7427,32 @@ msgctxt "#20458" msgid "Group movies in sets" msgstr "" +msgctxt "#20459" +msgid "Tags" +msgstr "" + +msgctxt "#20460" +msgid "Add %s" +msgstr "" + +msgctxt "#20461" +msgid "Remove %s" +msgstr "" + +msgctxt "#20462" +msgid "New tag..." +msgstr "" + +msgctxt "#20463" +msgid "A tag with the name '%s' already exists." +msgstr "" + +msgctxt "#20464" +msgid "Select %s" +msgstr "" + #up to 21329 is reserved for the video db !! ! -#empty strings from id 20459 to 21329 +#empty strings from id 20465 to 21329 msgctxt "#21330" msgid "Show hidden files and directories" diff --git a/system/library/video/movies/tags.xml b/system/library/video/movies/tags.xml new file mode 100644 index 0000000000..c897a6a770 --- /dev/null +++ b/system/library/video/movies/tags.xml @@ -0,0 +1,5 @@ +<node order="7" type="folder" visible="Library.HasContent(MovieSets)"> + <label>20459</label> + <path>videodb://1/9</path> + <icon>DefaultTags.png</icon> +</node> diff --git a/xbmc/dialogs/GUIDialogContextMenu.h b/xbmc/dialogs/GUIDialogContextMenu.h index 9a9600f7fc..0771c7d50f 100644 --- a/xbmc/dialogs/GUIDialogContextMenu.h +++ b/xbmc/dialogs/GUIDialogContextMenu.h @@ -104,6 +104,8 @@ enum CONTEXT_BUTTON { CONTEXT_BUTTON_CANCELLED = 0, CONTEXT_BUTTON_SET_MOVIESET_FANART, CONTEXT_BUTTON_DELETE_PLUGIN, CONTEXT_BUTTON_PLAY_AND_QUEUE, + CONTEXT_BUTTON_TAGS_ADD_ITEMS, + CONTEXT_BUTTON_TAGS_REMOVE_ITEMS, CONTEXT_BUTTON_USER1, CONTEXT_BUTTON_USER2, CONTEXT_BUTTON_USER3, diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp index ce8ba392b8..1b7bbccedf 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp @@ -160,6 +160,10 @@ bool CVideoDatabaseDirectory::GetLabel(const CStdString& strDirectory, CStdStrin if (params.GetSetId() != -1) strLabel += videodatabase.GetSetById(params.GetSetId()); + // get tag + if (params.GetTagId() != -1) + strLabel += videodatabase.GetTagById(params.GetTagId()); + // get year if (params.GetYear() != -1) { @@ -190,6 +194,8 @@ bool CVideoDatabaseDirectory::GetLabel(const CStdString& strDirectory, CStdStrin strLabel = g_localizeStrings.Get(20348); break; case NODE_TYPE_SETS: // Sets strLabel = g_localizeStrings.Get(20434); break; + case NODE_TYPE_TAGS: // Tags + strLabel = g_localizeStrings.Get(20459); break; case NODE_TYPE_MOVIES_OVERVIEW: // Movies strLabel = g_localizeStrings.Get(342); break; case NODE_TYPE_TVSHOWS_OVERVIEW: // TV Shows @@ -253,6 +259,8 @@ CStdString CVideoDatabaseDirectory::GetIcon(const CStdString &strDirectory) return "DefaultCountry.png"; case NODE_TYPE_SETS: // Sets return "DefaultSets.png"; + case NODE_TYPE_TAGS: // Tags + return "DefaultTags.png"; case NODE_TYPE_YEAR: // Year return "DefaultYear.png"; case NODE_TYPE_DIRECTOR: // Director diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp index 6fcfeaa33e..1eb27b31ce 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp @@ -43,6 +43,7 @@ #include "DirectoryNodeRecentlyAddedMusicVideos.h" #include "DirectoryNodeTitleMusicVideos.h" #include "DirectoryNodeMusicVideoAlbum.h" +#include "DirectoryNodeTags.h" #include "video/VideoInfoTag.h" #include "URL.h" #include "settings/AdvancedSettings.h" @@ -122,6 +123,8 @@ CDirectoryNode* CDirectoryNode::CreateNode(NODE_TYPE Type, const CStdString& str return new CDirectoryNodeCountry(strName, pParent); case NODE_TYPE_SETS: return new CDirectoryNodeSets(strName, pParent); + case NODE_TYPE_TAGS: + return new CDirectoryNodeTags(strName, pParent); case NODE_TYPE_YEAR: return new CDirectoryNodeYear(strName, pParent); case NODE_TYPE_ACTOR: diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h index 8a51a50f86..0ba9896bf4 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h @@ -54,7 +54,8 @@ namespace XFILE NODE_TYPE_TITLE_MUSICVIDEOS, NODE_TYPE_MUSICVIDEOS_ALBUM, NODE_TYPE_SETS, - NODE_TYPE_COUNTRY + NODE_TYPE_COUNTRY, + NODE_TYPE_TAGS } NODE_TYPE; typedef struct { diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp index 1d9b7f6ec6..87c5370e89 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp @@ -36,6 +36,7 @@ Node MovieChildren[] = { { NODE_TYPE_STUDIO, 6, 20388 }, { NODE_TYPE_SETS, 7, 20434 }, { NODE_TYPE_COUNTRY, 8, 20451 }, + { NODE_TYPE_TAGS, 9, 20459 } }; CDirectoryNodeMoviesOverview::CDirectoryNodeMoviesOverview(const CStdString& strName, CDirectoryNode* pParent) diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp new file mode 100644 index 0000000000..d95da74ff4 --- /dev/null +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp @@ -0,0 +1,60 @@ +/* + * 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNodeTags.h" +#include "QueryParams.h" +#include "video/VideoDatabase.h" + +using namespace XFILE::VIDEODATABASEDIRECTORY; + +CDirectoryNodeTags::CDirectoryNodeTags(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_TAGS, strName, pParent) +{ + +} + +NODE_TYPE CDirectoryNodeTags::GetChildType() const +{ + return NODE_TYPE_TITLE_MOVIES; +} + +CStdString CDirectoryNodeTags::GetLocalizedName() const +{ + CVideoDatabase db; + if (db.Open()) + return db.GetTagById(GetID()); + return ""; +} + +bool CDirectoryNodeTags::GetContent(CFileItemList& items) const +{ + CVideoDatabase videodatabase; + if (!videodatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + + bool bSuccess = videodatabase.GetTagsNav(BuildPath(), items, params.GetContentType()); + videodatabase.Close(); + + return bSuccess; +} diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h new file mode 100644 index 0000000000..7ab10eca0a --- /dev/null +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h @@ -0,0 +1,41 @@ +#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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace XFILE +{ + namespace VIDEODATABASEDIRECTORY + { + class CDirectoryNodeTags : public CDirectoryNode + { + public: + CDirectoryNodeTags(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType() const; + virtual bool GetContent(CFileItemList& items) const; + virtual CStdString GetLocalizedName() const; + }; + } +} + + diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp index 07557c7bc0..7989c81049 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp @@ -41,7 +41,7 @@ bool CDirectoryNodeTitleMovies::GetContent(CFileItemList& items) const CollectQueryParams(params); CStdString strBaseDir=BuildPath(); - bool bSuccess=videodatabase.GetMoviesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId()); + bool bSuccess=videodatabase.GetMoviesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId(), params.GetTagId()); videodatabase.Close(); diff --git a/xbmc/filesystem/VideoDatabaseDirectory/Makefile b/xbmc/filesystem/VideoDatabaseDirectory/Makefile index 2bd4107670..bda9117570 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/Makefile +++ b/xbmc/filesystem/VideoDatabaseDirectory/Makefile @@ -15,6 +15,7 @@ SRCS=DirectoryNode.cpp \ DirectoryNodeSeasons.cpp \ DirectoryNodeSets.cpp \ DirectoryNodeStudio.cpp \ + DirectoryNodeTags.cpp \ DirectoryNodeTitleMovies.cpp \ DirectoryNodeTitleMusicVideos.cpp \ DirectoryNodeTitleTvShows.cpp \ diff --git a/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.cpp b/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.cpp index ea84cbe75f..5c2089ed59 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.cpp @@ -39,6 +39,7 @@ CQueryParams::CQueryParams() m_idMVideo = -1; m_idAlbum = -1; m_idSet = -1; + m_idTag = -1; } void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName) @@ -92,6 +93,9 @@ void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeNa case NODE_TYPE_SETS: m_idSet = idDb; break; + case NODE_TYPE_TAGS: + m_idTag = idDb; + break; default: break; } diff --git a/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.h b/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.h index 60adaeab90..9fb7efc028 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.h +++ b/xbmc/filesystem/VideoDatabaseDirectory/QueryParams.h @@ -44,6 +44,7 @@ namespace XFILE long GetStudioId() const { return m_idStudio; } long GetMVideoId() const { return m_idMVideo; } long GetSetId() const { return m_idSet; } + long GetTagId() const { return m_idTag; } protected: void SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName); @@ -64,6 +65,7 @@ namespace XFILE long m_idMVideo; long m_idAlbum; long m_idSet; + long m_idTag; }; } } diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp index c40db5fffe..0aa92fa2c0 100644 --- a/xbmc/video/GUIViewStateVideo.cpp +++ b/xbmc/video/GUIViewStateVideo.cpp @@ -211,6 +211,18 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it SetSortOrder(g_settings.m_viewStateVideoNavGenres.m_sortOrder); } break; + case NODE_TYPE_TAGS: + { + SORT_METHOD method = SORT_METHOD_LABEL_IGNORE_THE; + if (!g_guiSettings.GetBool("filelists.ignorethewhensorting")) + method = SORT_METHOD_LABEL; + + AddSortMethod(method, 551, LABEL_MASKS("%T","", "%T","")); // Title, empty | Title, empty + SetSortMethod(method); + SetViewAsControl(g_settings.m_viewStateVideoNavGenres.m_viewMode); + SetSortOrder(g_settings.m_viewStateVideoNavGenres.m_sortOrder); + } + break; case NODE_TYPE_EPISODES: { if (params.GetSeason() > -1) diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index bf59784c25..7406d35b3b 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -875,7 +875,8 @@ bool CGUIWindowVideoBase::OnSelect(int iItem) CFileItemPtr item = m_vecItems->Get(iItem); CStdString path = item->GetPath(); - if (!item->m_bIsFolder && path != "add" && path != "addons://more/video" && path.Left(19) != "newsmartplaylist://" && path.Left(14) != "newplaylist://") + if (!item->m_bIsFolder && path != "add" && path != "addons://more/video" && + path.Left(19) != "newsmartplaylist://" && path.Left(14) != "newplaylist://" && path.Left(9) != "newtag://") return OnFileAction(iItem, g_guiSettings.GetInt("myvideos.selectaction")); return CGUIMediaWindow::OnSelect(iItem); @@ -1187,7 +1188,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but buttons.Add(CONTEXT_BUTTON_PLAY_PART, 20324); } - if (!m_vecItems->GetPath().IsEmpty() && !item->GetPath().Left(19).Equals("newsmartplaylist://") + if (!m_vecItems->GetPath().IsEmpty() && !item->GetPath().Left(19).Equals("newsmartplaylist://") && !item->GetPath().Left(9).Equals("newtag://") && !m_vecItems->IsSourcesPath()) { buttons.Add(CONTEXT_BUTTON_QUEUE_ITEM, 13347); // Add to Playlist diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index b88a1dbf50..4d58b8cbe5 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -51,6 +51,7 @@ #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "TextureCache.h" +#include "dialogs/GUIDialogKeyboard.h" using namespace XFILE; using namespace VIDEODATABASEDIRECTORY; @@ -207,6 +208,14 @@ CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const return "MovieActors"; else if (strPath.Equals("videodb://1/5/")) return "MovieDirectors"; + else if (strPath.Equals("videodb://1/6/")) + return "MovieStudios"; + else if (strPath.Equals("videodb://1/7/")) + return "MovieSets"; + else if (strPath.Equals("videodb://1/8/")) + return "MovieCountries"; + else if (strPath.Equals("videodb://1/9/")) + return "MovieTags"; else if (strPath.Equals("videodb://1/")) return "Movies"; else if (strPath.Equals("videodb://2/1/")) @@ -315,6 +324,7 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL } else if (node == NODE_TYPE_TITLE_MOVIES || node == NODE_TYPE_SETS || + node == NODE_TYPE_TAGS || node == NODE_TYPE_RECENTLY_ADDED_MOVIES) items.SetContent("movies"); else if (node == NODE_TYPE_TITLE_TVSHOWS) @@ -352,6 +362,15 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL if (!items.IsSourcesPath()) LoadVideoInfo(items); } + + if (items.GetPath() == "videodb://1/9/" && !items.Contains("newtag://movie")) + { + CFileItemPtr newTag(new CFileItem("newtag://movie", false)); + newTag->SetLabel(g_localizeStrings.Get(20462)); + newTag->SetLabelPreformated(true); + newTag->SetSpecialSort(SortSpecialOnTop); + items.Add(newTag); + } } return bResult; } @@ -624,7 +643,8 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem) { if (!pItem->GetPath().Equals("newsmartplaylist://video") && !pItem->GetPath().Equals("special://videoplaylists/") && - !pItem->GetPath().Equals("sources://video/")) + !pItem->GetPath().Equals("sources://video/") && + !pItem->GetPath().Left(9).Equals("newtag://")) CGUIWindowVideoBase::OnDeleteItem(pItem); } else if (pItem->GetPath().Left(14).Equals("videodb://1/7/") && @@ -644,10 +664,28 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem) for (int i=0;i<items.Size();++i) OnDeleteItem(items[i]); - CVideoDatabaseDirectory dir; - CQueryParams params; - dir.GetQueryParams(pItem->GetPath(),params); - m_database.DeleteSet(params.GetSetId()); + CVideoDatabaseDirectory dir; + CQueryParams params; + dir.GetQueryParams(pItem->GetPath(),params); + m_database.DeleteSet(params.GetSetId()); + } + } + else if (pItem->GetPath().Left(14).Equals("videodb://1/9/") && + pItem->GetPath().size() > 14 && pItem->m_bIsFolder) + { + CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO); + pDialog->SetHeading(432); + CStdString strLabel; + strLabel.Format(g_localizeStrings.Get(433),pItem->GetLabel()); + pDialog->SetLine(1, strLabel); + pDialog->SetLine(2, "");; + pDialog->DoModal(); + if (pDialog->IsConfirmed()) + { + CVideoDatabaseDirectory dir; + CQueryParams params; + dir.GetQueryParams(pItem->GetPath(), params); + m_database.DeleteTag(params.GetTagId(), "movie"); } } else if (m_vecItems->GetPath().Equals(CUtil::VideoPlaylistsLocation()) || @@ -883,7 +921,9 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349); } if (!item->IsPlugin() && !item->IsScript() && !item->IsLiveTV() && !item->IsAddonsPath() && - item->GetPath() != "sources://video/" && item->GetPath() != "special://videoplaylists/") + item->GetPath() != "sources://video/" && item->GetPath() != "special://videoplaylists/" && + item->GetPath().Left(19) != "newsmartplaylist://" && item->GetPath().Left(14) != "newplaylist://" && + item->GetPath().Left(9) != "newtag://") { if (item->m_bIsFolder) { @@ -924,6 +964,15 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt buttons.Add(CONTEXT_BUTTON_DELETE, 646); } + if (item->GetPath().Left(14).Equals("videodb://1/9/") && item->GetPath().size() > 14 && item->m_bIsFolder) // tags + { + CStdString strLabelAdd; strLabelAdd.Format(g_localizeStrings.Get(20460), g_localizeStrings.Get(20342).c_str()); + CStdString strLabelRemove; strLabelRemove.Format(g_localizeStrings.Get(20461), g_localizeStrings.Get(20342).c_str()); + buttons.Add(CONTEXT_BUTTON_TAGS_ADD_ITEMS, strLabelAdd); + buttons.Add(CONTEXT_BUTTON_TAGS_REMOVE_ITEMS, strLabelRemove); + buttons.Add(CONTEXT_BUTTON_DELETE, 646); + } + if (node == NODE_TYPE_ACTOR && !dir.IsAllItem(item->GetPath()) && item->m_bIsFolder) { if (m_vecItems->GetPath().Left(11).Equals("videodb://3")) // mvids @@ -1195,6 +1244,74 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) Update(m_vecItems->GetPath()); return true; } + case CONTEXT_BUTTON_TAGS_ADD_ITEMS: + { + if (!item->GetPath().Left(10).Equals("videodb://")) + return false; + + std::string mediaType; + if (item->GetPath().Mid(9, 3).Equals("/1/")) + mediaType = "movie"; + else + return false; + + CFileItemList items; + CStdString localizedType = GetLocalizedType(mediaType); + CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str()); + if (!GetItemsForTag(strLabel, mediaType, items, item->GetVideoInfoTag()->m_iDbId)) + return true; + + CVideoDatabase videodb; + if (!videodb.Open()) + return true; + + for (int index = 0; index < items.Size(); index++) + { + if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0) + continue; + + videodb.AddTagToItem(items[index]->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_iDbId, mediaType); + } + + // we need to clear any cached version of this tag's listing + items.SetPath(item->GetPath()); + items.RemoveDiscCache(GetID()); + return true; + } + case CONTEXT_BUTTON_TAGS_REMOVE_ITEMS: + { + if (!item->GetPath().Left(10).Equals("videodb://")) + return false; + + std::string mediaType; + if (item->GetPath().Mid(9, 3).Equals("/1/")) + mediaType = "movie"; + else + return false; + + CFileItemList items; + CStdString localizedType = GetLocalizedType(mediaType); + CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str()); + if (!GetItemsForTag(strLabel, mediaType, items, item->GetVideoInfoTag()->m_iDbId, false)) + return true; + + CVideoDatabase videodb; + if (!videodb.Open()) + return true; + + for (int index = 0; index < items.Size(); index++) + { + if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0) + continue; + + videodb.RemoveTagFromItem(items[index]->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_iDbId, mediaType); + } + + // we need to clear any cached version of this tag's listing + items.SetPath(item->GetPath()); + items.RemoveDiscCache(GetID()); + return true; + } case CONTEXT_BUTTON_UPDATE_LIBRARY: { OnScan(""); @@ -1332,6 +1449,54 @@ bool CGUIWindowVideoNav::OnClick(int iItem) m_viewControl.SetSelectedItem(iItem); return true; } + else if (item->GetPath().Left(9).Equals("newtag://")) + { + // dont allow update while scanning + if (g_application.IsVideoScanning()) + { + CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0); + return true; + } + + //Get the new title + CStdString strTag; + if (!CGUIDialogKeyboard::ShowAndGetInput(strTag, g_localizeStrings.Get(20462), false)) + return true; + + CVideoDatabase videodb; + if (!videodb.Open()) + return true; + + CStdString mediaType = item->GetPath().Mid(9); + CStdString localizedType = GetLocalizedType(mediaType); + if (localizedType.empty()) + return true; + + if (!videodb.GetSingleValue("tag", "tag.idTag", videodb.PrepareSQL("tag.strTag = '%s' AND tag.idTag IN (SELECT taglinks.idTag FROM taglinks WHERE taglinks.media_type = '%s')", strTag.c_str(), mediaType.c_str())).empty()) + { + CStdString strError; strError.Format(g_localizeStrings.Get(20463), strTag.c_str()); + CGUIDialogOK::ShowAndGetInput(20462, strError, "", ""); + return true; + } + + int idTag = videodb.AddTag(strTag); + CFileItemList items; + CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str()); + if (GetItemsForTag(strLabel, mediaType, items, idTag)) + { + for (int index = 0; index < items.Size(); index++) + { + if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0) + continue; + + videodb.AddTagToItem(items[index]->GetVideoInfoTag()->m_iDbId, idTag, mediaType); + } + } + + m_vecItems->RemoveDiscCache(GetID()); + Update(m_vecItems->GetPath()); + return true; + } return CGUIWindowVideoBase::OnClick(iItem); } @@ -1354,6 +1519,8 @@ CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir) return "videodb://1/7/"; else if (dir.Equals("MovieCountries")) return "videodb://1/8/"; + else if (dir.Equals("MovieTags")) + return "videodb://1/9/"; else if (dir.Equals("Movies")) return "videodb://1/"; else if (dir.Equals("TvShowGenres")) @@ -1405,6 +1572,7 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) if (node == NODE_TYPE_EPISODES || node == NODE_TYPE_SEASONS || node == NODE_TYPE_SETS + || node == NODE_TYPE_TAGS || node == NODE_TYPE_TITLE_MOVIES || node == NODE_TYPE_TITLE_TVSHOWS || node == NODE_TYPE_TITLE_MUSICVIDEOS @@ -1443,3 +1611,59 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items) } } } + +bool CGUIWindowVideoNav::GetItemsForTag(const CStdString &strHeading, const std::string &type, CFileItemList &items, int idTag /* = -1 */, bool showAll /* = true */) +{ + CVideoDatabase videodb; + if (!videodb.Open()) + return false; + + CFileItemList listItems; + bool result = false; + if (idTag <= 0) + result = videodb.GetMoviesNav("videodb://1/2/", listItems); + else + { + if (showAll) + { + CVideoDatabase::Filter filter; + filter.where = videodb.PrepareSQL("movieview.idMovie NOT IN (SELECT taglinks.idMedia FROM taglinks WHERE taglinks.idTag = %d AND taglinks.media_type = '%s')", idTag, type.c_str()); + result = videodb.GetMoviesByWhere("videodb://1/2/", filter, listItems); + } + else + result = videodb.GetMoviesNav("videodb://1/9/", listItems, -1, -1, -1, -1, -1, -1, -1, idTag); + } + + if (!result || listItems.Size() <= 0) + return false; + + CGUIDialogSelect *dialog = (CGUIDialogSelect *)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + if (dialog == NULL) + return false; + + listItems.Sort(SORT_METHOD_LABEL_IGNORE_THE, SortOrderAscending); + + dialog->Reset(); + dialog->SetMultiSelection(true); + dialog->SetHeading(strHeading); + dialog->SetItems(&listItems); + dialog->EnableButton(true, 186); + dialog->DoModal(); + + items.Copy(dialog->GetSelectedItems()); + return items.Size() > 0; +} + +CStdString CGUIWindowVideoNav::GetLocalizedType(const std::string &strType) +{ + if (strType == "movie") + return g_localizeStrings.Get(20342); + else if (strType == "tvshow") + return g_localizeStrings.Get(20343); + else if (strType == "episode") + return g_localizeStrings.Get(20359); + else if (strType == "musicvideo") + return g_localizeStrings.Get(20391); + else + return ""; +} diff --git a/xbmc/video/windows/GUIWindowVideoNav.h b/xbmc/video/windows/GUIWindowVideoNav.h index 6ee0708917..631851ba4b 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.h +++ b/xbmc/video/windows/GUIWindowVideoNav.h @@ -67,5 +67,8 @@ protected: virtual CStdString GetQuickpathName(const CStdString& strPath) const; + bool GetItemsForTag(const CStdString &strHeading, const std::string &type, CFileItemList &items, int idTag = -1, bool showAll = true); + static CStdString GetLocalizedType(const std::string &strType); + VECSOURCES m_shares; }; diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 8d398ed899..02a2c361e2 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -1425,7 +1425,7 @@ void CGUIMediaWindow::GetContextButtons(int itemNumber, CContextButtons &buttons // TODO: FAVOURITES Conditions on masterlock and localisation if (!item->IsParentFolder() && !item->GetPath().Equals("add") && !item->GetPath().Equals("newplaylist://") && - !item->GetPath().Left(19).Equals("newsmartplaylist://")) + !item->GetPath().Left(19).Equals("newsmartplaylist://") && !item->GetPath().Left(9).Equals("newtag://")) { if (CFavourites::IsFavourite(item.get(), GetID())) buttons.Add(CONTEXT_BUTTON_ADD_FAVOURITE, 14077); // Remove Favourite |