2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "DirectoryNode.h"
23 #include "utils/URIUtils.h"
24 #include "QueryParams.h"
25 #include "DirectoryNodeRoot.h"
26 #include "DirectoryNodeOverview.h"
27 #include "DirectoryNodeGenre.h"
28 #include "DirectoryNodeCountry.h"
29 #include "DirectoryNodeSets.h"
30 #include "DirectoryNodeTitleMovies.h"
31 #include "DirectoryNodeTitleTvShows.h"
32 #include "DirectoryNodeYear.h"
33 #include "DirectoryNodeActor.h"
34 #include "DirectoryNodeDirector.h"
35 #include "DirectoryNodeMoviesOverview.h"
36 #include "DirectoryNodeTvShowsOverview.h"
37 #include "DirectoryNodeSeasons.h"
38 #include "DirectoryNodeEpisodes.h"
39 #include "DirectoryNodeRecentlyAddedMovies.h"
40 #include "DirectoryNodeRecentlyAddedEpisodes.h"
41 #include "DirectoryNodeStudio.h"
42 #include "DirectoryNodeMusicVideosOverview.h"
43 #include "DirectoryNodeRecentlyAddedMusicVideos.h"
44 #include "DirectoryNodeTitleMusicVideos.h"
45 #include "DirectoryNodeMusicVideoAlbum.h"
46 #include "video/VideoInfoTag.h"
48 #include "settings/AdvancedSettings.h"
50 #include "filesystem/File.h"
51 #include "utils/StringUtils.h"
52 #include "guilib/LocalizeStrings.h"
53 #include "utils/Variant.h"
54 #include "video/VideoDatabase.h"
57 using namespace XFILE::VIDEODATABASEDIRECTORY;
59 // Constructor is protected use ParseURL()
60 CDirectoryNode::CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent)
67 CDirectoryNode::~CDirectoryNode()
72 // Parses a given path and returns the current node of the path
73 CDirectoryNode* CDirectoryNode::ParseURL(const CStdString& strPath)
77 CStdString strDirectory=url.GetFileName();
78 URIUtils::RemoveSlashAtEnd(strDirectory);
81 StringUtils::SplitString(strDirectory, "/", Path);
82 if (!strDirectory.IsEmpty())
83 Path.insert(Path.begin(), "");
85 CDirectoryNode* pNode=NULL;
86 CDirectoryNode* pParent=NULL;
87 NODE_TYPE NodeType=NODE_TYPE_ROOT;
89 for (int i=0; i<(int)Path.size(); ++i)
91 pNode=CDirectoryNode::CreateNode(NodeType, Path[i], pParent);
92 NodeType= pNode ? pNode->GetChildType() : NODE_TYPE_NONE;
99 // returns the database ids of the path,
100 void CDirectoryNode::GetDatabaseInfo(const CStdString& strPath, CQueryParams& params)
102 auto_ptr<CDirectoryNode> pNode(CDirectoryNode::ParseURL(strPath));
107 pNode->CollectQueryParams(params);
110 // Create a node object
111 CDirectoryNode* CDirectoryNode::CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent)
116 return new CDirectoryNodeRoot(strName, pParent);
117 case NODE_TYPE_OVERVIEW:
118 return new CDirectoryNodeOverview(strName, pParent);
119 case NODE_TYPE_GENRE:
120 return new CDirectoryNodeGenre(strName, pParent);
121 case NODE_TYPE_COUNTRY:
122 return new CDirectoryNodeCountry(strName, pParent);
124 return new CDirectoryNodeSets(strName, pParent);
126 return new CDirectoryNodeYear(strName, pParent);
127 case NODE_TYPE_ACTOR:
128 return new CDirectoryNodeActor(strName, pParent);
129 case NODE_TYPE_DIRECTOR:
130 return new CDirectoryNodeDirector(strName, pParent);
131 case NODE_TYPE_TITLE_MOVIES:
132 return new CDirectoryNodeTitleMovies(strName, pParent);
133 case NODE_TYPE_TITLE_TVSHOWS:
134 return new CDirectoryNodeTitleTvShows(strName, pParent);
135 case NODE_TYPE_MOVIES_OVERVIEW:
136 return new CDirectoryNodeMoviesOverview(strName, pParent);
137 case NODE_TYPE_TVSHOWS_OVERVIEW:
138 return new CDirectoryNodeTvShowsOverview(strName, pParent);
139 case NODE_TYPE_SEASONS:
140 return new CDirectoryNodeSeasons(strName, pParent);
141 case NODE_TYPE_EPISODES:
142 return new CDirectoryNodeEpisodes(strName, pParent);
143 case NODE_TYPE_RECENTLY_ADDED_MOVIES:
144 return new CDirectoryNodeRecentlyAddedMovies(strName,pParent);
145 case NODE_TYPE_RECENTLY_ADDED_EPISODES:
146 return new CDirectoryNodeRecentlyAddedEpisodes(strName,pParent);
147 case NODE_TYPE_STUDIO:
148 return new CDirectoryNodeStudio(strName,pParent);
149 case NODE_TYPE_MUSICVIDEOS_OVERVIEW:
150 return new CDirectoryNodeMusicVideosOverview(strName,pParent);
151 case NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS:
152 return new CDirectoryNodeRecentlyAddedMusicVideos(strName,pParent);
153 case NODE_TYPE_TITLE_MUSICVIDEOS:
154 return new CDirectoryNodeTitleMusicVideos(strName,pParent);
155 case NODE_TYPE_MUSICVIDEOS_ALBUM:
156 return new CDirectoryNodeMusicVideoAlbum(strName,pParent);
165 const CStdString& CDirectoryNode::GetName() const
170 int CDirectoryNode::GetID() const
172 return atoi(m_strName.c_str());
175 CStdString CDirectoryNode::GetLocalizedName() const
181 NODE_TYPE CDirectoryNode::GetType() const
186 // Return the parent directory node or NULL, if there is no
187 CDirectoryNode* CDirectoryNode::GetParent() const
192 void CDirectoryNode::RemoveParent()
197 // should be overloaded by a derived class
198 // to get the content of a node. Will be called
199 // by GetChilds() of a parent node
200 bool CDirectoryNode::GetContent(CFileItemList& items) const
205 // Creates a videodb url
206 CStdString CDirectoryNode::BuildPath() const
208 CStdStringArray array;
210 if (!m_strName.IsEmpty())
211 array.insert(array.begin(), m_strName);
213 CDirectoryNode* pParent=m_pParent;
214 while (pParent!=NULL)
216 const CStdString& strNodeName=pParent->GetName();
217 if (!strNodeName.IsEmpty())
218 array.insert(array.begin(), strNodeName);
220 pParent=pParent->GetParent();
223 CStdString strPath="videodb://";
224 for (int i=0; i<(int)array.size(); ++i)
225 strPath+=array[i]+"/";
230 // Collects Query params from this and all parent nodes. If a NODE_TYPE can
231 // be used as a database parameter, it will be added to the
233 void CDirectoryNode::CollectQueryParams(CQueryParams& params) const
235 params.SetQueryParam(m_Type, m_strName);
237 CDirectoryNode* pParent=m_pParent;
238 while (pParent!=NULL)
240 params.SetQueryParam(pParent->GetType(), pParent->GetName());
241 pParent=pParent->GetParent();
245 // Should be overloaded by a derived class.
246 // Returns the NODE_TYPE of the child nodes.
247 NODE_TYPE CDirectoryNode::GetChildType() const
249 return NODE_TYPE_NONE;
252 // Get the child fileitems of this node
253 bool CDirectoryNode::GetChilds(CFileItemList& items)
255 if (CanCache() && items.Load())
258 auto_ptr<CDirectoryNode> pNode(CDirectoryNode::CreateNode(GetChildType(), "", this));
263 bSuccess=pNode->GetContent(items);
266 AddQueuingFolder(items);
268 items.SetCacheToDisc(CFileItemList::CACHE_ALWAYS);
273 pNode->RemoveParent();
279 // Add an "* All ..." folder to the CFileItemList
280 // depending on the child node
281 void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const
285 // always hide "all" items
286 if (g_advancedSettings.m_bVideoLibraryHideAllItems)
289 // no need for "all" item when only one item
290 if (items.GetObjectCount() <= 1)
293 // hack - as the season node might return episodes
294 auto_ptr<CDirectoryNode> pNode(ParseURL(items.GetPath()));
296 switch (pNode->GetChildType())
298 case NODE_TYPE_SEASONS:
300 CStdString strLabel = g_localizeStrings.Get(20366);
301 pItem.reset(new CFileItem(strLabel)); // "All Seasons"
302 pItem->SetPath(BuildPath() + "-1/");
303 // set the number of watched and unwatched items accordingly
306 for (int i = 0; i < items.Size(); i++)
308 CFileItemPtr item = items[i];
309 watched += (int)item->GetProperty("watchedepisodes").asInteger();
310 unwatched += (int)item->GetProperty("unwatchedepisodes").asInteger();
312 pItem->SetProperty("totalepisodes", watched + unwatched);
313 pItem->SetProperty("numepisodes", watched + unwatched); // will be changed later to reflect watchmode setting
314 pItem->SetProperty("watchedepisodes", watched);
315 pItem->SetProperty("unwatchedepisodes", unwatched);
316 if (items.Size() && items[0]->GetVideoInfoTag())
318 *pItem->GetVideoInfoTag() = *items[0]->GetVideoInfoTag();
319 pItem->GetVideoInfoTag()->m_iSeason = -1;
321 pItem->GetVideoInfoTag()->m_strTitle = strLabel;
322 pItem->GetVideoInfoTag()->m_iEpisode = watched + unwatched;
323 pItem->GetVideoInfoTag()->m_playCount = (unwatched == 0) ? 1 : 0;
327 pItem->GetVideoInfoTag()->m_iDbId = db.GetSeasonId(pItem->GetVideoInfoTag()->m_iIdShow, -1);
330 pItem->GetVideoInfoTag()->m_type = "season";
339 pItem->m_bIsFolder = true;
340 pItem->SetSpecialSort(g_advancedSettings.m_bVideoLibraryAllItemsOnBottom ? SortSpecialOnBottom : SortSpecialOnTop);
341 pItem->SetCanQueue(false);
346 bool CDirectoryNode::CanCache() const
348 // Only cache the directorys in the root
349 //NODE_TYPE childnode=GetChildType();
350 //NODE_TYPE node=GetType();
352 // something should probably be cached
353 return true;//(childnode==NODE_TYPE_TITLE_MOVIES || childnode==NODE_TYPE_EPISODES || childnode == NODE_TYPE_SEASONS || childnode == NODE_TYPE_TITLE_TVSHOWS);