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 "GUIUserMessages.h"
23 #include "GUIWindowVideoNav.h"
24 #include "music/windows/GUIWindowMusicNav.h"
25 #include "utils/FileUtils.h"
27 #include "utils/RegExp.h"
28 #include "PlayListPlayer.h"
29 #include "GUIPassword.h"
30 #include "dialogs/GUIDialogFileBrowser.h"
31 #include "filesystem/VideoDatabaseDirectory.h"
32 #include "playlists/PlayListFactory.h"
33 #include "video/dialogs/GUIDialogVideoScan.h"
34 #include "dialogs/GUIDialogOK.h"
35 #include "addons/AddonManager.h"
36 #include "PartyModeManager.h"
37 #include "music/MusicDatabase.h"
38 #include "guilib/GUIWindowManager.h"
39 #include "dialogs/GUIDialogYesNo.h"
40 #include "dialogs/GUIDialogSelect.h"
41 #include "filesystem/Directory.h"
42 #include "filesystem/File.h"
44 #include "Application.h"
45 #include "settings/Settings.h"
46 #include "settings/AdvancedSettings.h"
47 #include "settings/GUISettings.h"
48 #include "guilib/LocalizeStrings.h"
49 #include "storage/MediaManager.h"
50 #include "utils/log.h"
51 #include "utils/URIUtils.h"
52 #include "TextureCache.h"
54 using namespace XFILE;
55 using namespace VIDEODATABASEDIRECTORY;
58 #define CONTROL_BTNVIEWASICONS 2
59 #define CONTROL_BTNSORTBY 3
60 #define CONTROL_BTNSORTASC 4
61 #define CONTROL_BTNTYPE 5
62 #define CONTROL_BTNSEARCH 8
63 #define CONTROL_LABELFILES 12
65 #define CONTROL_BTN_FILTER 19
66 #define CONTROL_BTNSHOWMODE 10
67 #define CONTROL_BTNSHOWALL 14
68 #define CONTROL_UNLOCK 11
70 #define CONTROL_FILTER 15
71 #define CONTROL_BTNPARTYMODE 16
72 #define CONTROL_BTNFLATTEN 17
73 #define CONTROL_LABELEMPTY 18
75 CGUIWindowVideoNav::CGUIWindowVideoNav(void)
76 : CGUIWindowVideoBase(WINDOW_VIDEO_NAV, "MyVideoNav.xml")
78 m_thumbLoader.SetObserver(this);
81 CGUIWindowVideoNav::~CGUIWindowVideoNav(void)
85 bool CGUIWindowVideoNav::OnAction(const CAction &action)
87 if (action.GetID() == ACTION_TOGGLE_WATCHED)
89 CFileItemPtr pItem = m_vecItems->Get(m_viewControl.GetSelectedItem());
90 if (pItem->IsParentFolder())
92 if (pItem && pItem->GetVideoInfoTag()->m_playCount == 0)
93 return OnContextButton(m_viewControl.GetSelectedItem(),CONTEXT_BUTTON_MARK_WATCHED);
94 if (pItem && pItem->GetVideoInfoTag()->m_playCount > 0)
95 return OnContextButton(m_viewControl.GetSelectedItem(),CONTEXT_BUTTON_MARK_UNWATCHED);
97 return CGUIWindowVideoBase::OnAction(action);
100 bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message)
102 switch (message.GetMessage())
104 case GUI_MSG_WINDOW_RESET:
105 m_vecItems->m_strPath.clear();
107 case GUI_MSG_WINDOW_DEINIT:
108 if (m_thumbLoader.IsLoading())
109 m_thumbLoader.StopThread();
111 case GUI_MSG_WINDOW_INIT:
113 /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */
114 m_rootDir.AllowNonLocalSources(false);
116 SetProperty("flattened", g_settings.m_bMyVideoNavFlatten);
118 if (!CGUIWindowVideoBase::OnMessage(message))
121 // base class has opened the database, do our check
124 if (!m_database.HasContent() && m_vecItems->IsVideoDb())
125 { // no library - make sure we default to the root.
126 m_vecItems->m_strPath = "";
127 SetHistoryForPath("");
136 case GUI_MSG_CLICKED:
138 int iControl = message.GetSenderId();
139 if (iControl == CONTROL_BTNPARTYMODE)
141 if (g_partyModeManager.IsEnabled())
142 g_partyModeManager.Disable();
145 if (!g_partyModeManager.Enable(PARTYMODECONTEXT_VIDEO))
147 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE,false);
151 // Playlist directory is the root of the playlist window
152 if (m_guiState.get()) m_guiState->SetPlaylistDirectory("playlistvideo://");
159 if (iControl == CONTROL_BTNSEARCH)
163 else if (iControl == CONTROL_BTNSHOWMODE)
165 g_settings.CycleWatchMode(m_vecItems->GetContent());
168 // TODO: Can we perhaps filter this directly? Probably not for some of the more complicated views,
169 // but for those perhaps we can just display them all, and only filter when we get a list
171 Update(m_vecItems->m_strPath);
174 else if (iControl == CONTROL_BTNFLATTEN)
176 g_settings.m_bMyVideoNavFlatten = !g_settings.m_bMyVideoNavFlatten;
178 SetProperty("flattened", g_settings.m_bMyVideoNavFlatten);
179 CUtil::DeleteVideoDatabaseDirectoryCache();
184 else if (iControl == CONTROL_BTNSHOWALL)
186 if (g_settings.GetWatchMode(m_vecItems->GetContent()) == VIDEO_SHOW_ALL)
187 g_settings.SetWatchMode(m_vecItems->GetContent(), VIDEO_SHOW_UNWATCHED);
189 g_settings.SetWatchMode(m_vecItems->GetContent(), VIDEO_SHOW_ALL);
191 // TODO: Can we perhaps filter this directly? Probably not for some of the more complicated views,
192 // but for those perhaps we can just display them all, and only filter when we get a list
194 Update(m_vecItems->m_strPath);
199 // update the display
200 case GUI_MSG_SCAN_FINISHED:
201 case GUI_MSG_REFRESH_THUMBS:
203 Update(m_vecItems->m_strPath);
207 return CGUIWindowVideoBase::OnMessage(message);
210 CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const
212 if (strPath.Equals("videodb://1/1/"))
213 return "MovieGenres";
214 else if (strPath.Equals("videodb://1/2/"))
215 return "MovieTitles";
216 else if (strPath.Equals("videodb://1/3/"))
218 else if (strPath.Equals("videodb://1/4/"))
219 return "MovieActors";
220 else if (strPath.Equals("videodb://1/5/"))
221 return "MovieDirectors";
222 else if (strPath.Equals("videodb://1/"))
224 else if (strPath.Equals("videodb://2/1/"))
225 return "TvShowGenres";
226 else if (strPath.Equals("videodb://2/2/"))
227 return "TvShowTitles";
228 else if (strPath.Equals("videodb://2/3/"))
229 return "TvShowYears";
230 else if (strPath.Equals("videodb://2/4/"))
231 return "TvShowActors";
232 else if (strPath.Equals("videodb://2/"))
234 else if (strPath.Equals("videodb://3/1/"))
235 return "MusicVideoGenres";
236 else if (strPath.Equals("videodb://3/2/"))
237 return "MusicVideoTitles";
238 else if (strPath.Equals("videodb://3/3/"))
239 return "MusicVideoYears";
240 else if (strPath.Equals("videodb://3/4/"))
241 return "MusicVideoArtists";
242 else if (strPath.Equals("videodb://3/5/"))
243 return "MusicVideoDirectors";
244 else if (strPath.Equals("videodb://3/"))
245 return "MusicVideos";
246 else if (strPath.Equals("videodb://4/"))
247 return "RecentlyAddedMovies";
248 else if (strPath.Equals("videodb://5/"))
249 return "RecentlyAddedEpisodes";
250 else if (strPath.Equals("videodb://6/"))
251 return "RecentlyAddedMusicVideos";
252 else if (strPath.Equals("special://videoplaylists/"))
254 else if (strPath.Equals("sources://video/"))
258 CLog::Log(LOGERROR, " CGUIWindowVideoNav::GetQuickpathName: Unknown parameter (%s)", strPath.c_str());
263 void CGUIWindowVideoNav::OnItemLoaded(CFileItem* pItem)
265 /* even though the background loader is running multiple threads and we could,
266 be acting on someone else's flag, we don't care who invalidates the cache
267 only that it is done. We also don't care if it is done multiple times due
268 to a race between multiple threads here at the same time */
269 CUtil::DeleteVideoDatabaseDirectoryCache();
272 bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items)
274 CFileItem directory(strDirectory, true);
276 if (m_thumbLoader.IsLoading())
277 m_thumbLoader.StopThread();
279 m_rootDir.SetCacheDirectory(DIR_CACHE_NEVER);
280 items.ClearProperties();
282 bool bResult = CGUIWindowVideoBase::GetDirectory(strDirectory, items);
285 if (items.IsVideoDb())
287 XFILE::CVideoDatabaseDirectory dir;
289 dir.GetQueryParams(items.m_strPath,params);
290 VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.m_strPath);
292 items.SetThumbnailImage("");
293 if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES ||
294 node == NODE_TYPE_SEASONS ||
295 node == NODE_TYPE_RECENTLY_ADDED_EPISODES)
297 CLog::Log(LOGDEBUG, "WindowVideoNav::GetDirectory");
298 // grab the show thumb
300 m_database.GetFilePathById(params.GetTvShowId(),showItem.m_strPath,VIDEODB_CONTENT_TVSHOWS);
301 showItem.SetVideoThumb();
302 items.SetProperty("tvshowthumb", showItem.GetThumbnailImage());
304 CVideoInfoTag details;
305 m_database.GetTvShowInfo(showItem.m_strPath, details, params.GetTvShowId());
306 items.SetProperty("fanart_color1", details.m_fanart.GetColor(0));
307 items.SetProperty("fanart_color2", details.m_fanart.GetColor(1));
308 items.SetProperty("fanart_color3", details.m_fanart.GetColor(2));
309 if (showItem.CacheLocalFanart())
310 items.SetProperty("fanart_image", showItem.GetCachedFanart());
312 // save the show description (showplot)
313 items.SetProperty("showplot", details.m_strPlot);
315 // set the season thumb
317 if (params.GetSeason() == 0)
318 strLabel = g_localizeStrings.Get(20381);
320 strLabel.Format(g_localizeStrings.Get(20358), params.GetSeason());
322 CFileItem item(strLabel);
323 URIUtils::GetParentPath(items.m_strPath,item.m_strPath);
324 item.m_bIsFolder = true;
325 item.SetCachedSeasonThumb();
326 if (item.HasThumbnail())
327 items.SetProperty("seasonthumb",item.GetThumbnailImage());
329 // the container folder thumb is the parent (i.e. season or show)
330 if (node == NODE_TYPE_EPISODES || node == NODE_TYPE_RECENTLY_ADDED_EPISODES)
332 items.SetContent("episodes");
333 // grab the season thumb as the folder thumb
336 if (params.GetSeason() == -1 && items.Size() > 0)
338 CQueryParams params2;
339 dir.GetQueryParams(items[0]->m_strPath,params2);
340 strLabel.Format(g_localizeStrings.Get(20358), params2.GetSeason());
341 URIUtils::GetParentPath(items.m_strPath,strPath);
345 if (params.GetSeason() == 0)
346 strLabel = g_localizeStrings.Get(20381);
348 strLabel.Format(g_localizeStrings.Get(20358), params.GetSeason());
349 strPath = items.m_strPath;
352 CFileItem item(strLabel);
353 item.m_strPath = strPath;
354 item.m_bIsFolder = true;
355 item.GetVideoInfoTag()->m_strPath = showItem.m_strPath;
356 item.SetCachedSeasonThumb();
358 items.SetThumbnailImage(item.GetThumbnailImage());
359 items.SetProperty("seasonthumb",item.GetThumbnailImage());
363 items.SetContent("seasons");
364 items.SetThumbnailImage(showItem.GetThumbnailImage());
367 else if (node == NODE_TYPE_TITLE_MOVIES ||
368 node == NODE_TYPE_RECENTLY_ADDED_MOVIES)
369 items.SetContent("movies");
370 else if (node == NODE_TYPE_TITLE_TVSHOWS)
371 items.SetContent("tvshows");
372 else if (node == NODE_TYPE_TITLE_MUSICVIDEOS ||
373 node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
374 items.SetContent("musicvideos");
375 else if (node == NODE_TYPE_GENRE)
376 items.SetContent("genres");
377 else if (node == NODE_TYPE_COUNTRY)
378 items.SetContent("countries");
379 else if (node == NODE_TYPE_ACTOR)
381 if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS)
382 items.SetContent("artists");
384 items.SetContent("actors");
386 else if (node == NODE_TYPE_DIRECTOR)
387 items.SetContent("directors");
388 else if (node == NODE_TYPE_STUDIO)
389 items.SetContent("studios");
390 else if (node == NODE_TYPE_YEAR)
391 items.SetContent("years");
392 else if (node == NODE_TYPE_MUSICVIDEOS_ALBUM)
393 items.SetContent("albums");
395 items.SetContent("");
398 { // load info from the database
400 if (items.GetLabel().IsEmpty() && m_rootDir.IsSource(items.m_strPath, g_settings.GetSourcesFromType("video"), &label))
401 items.SetLabel(label);
402 LoadVideoInfo(items);
408 void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items)
410 // TODO: this could possibly be threaded as per the music info loading,
411 // we could also cache the info
412 if (!items.GetContent().IsEmpty())
413 return; // don't load for listings that have content set
415 CStdString content = m_database.GetContentForPath(items.m_strPath);
416 items.SetContent(content.IsEmpty() ? "files" : content);
418 bool clean = (g_guiSettings.GetBool("myvideos.cleanstrings") &&
419 !items.IsVirtualDirectoryRoot() &&
420 m_stackingAvailable);
422 CFileItemList dbItems;
423 if (content.IsEmpty())
424 m_database.GetPlayCounts(items);
427 m_database.GetItemsForPath(content, items.m_strPath, dbItems);
428 dbItems.SetFastLookup(true);
430 for (int i = 0; i < items.Size(); i++)
432 CFileItemPtr pItem = items[i];
434 if (!content.IsEmpty())
435 match = dbItems.Get(pItem->m_strPath);
438 CStdString label (pItem->GetLabel ());
439 CStdString label2(pItem->GetLabel2());
440 pItem->UpdateInfo(*match);
442 if(g_settings.m_videoStacking && m_stackingAvailable)
444 if (match->m_bIsFolder)
445 pItem->m_strPath = match->GetVideoInfoTag()->m_strPath;
447 pItem->m_strPath = match->GetVideoInfoTag()->m_strFileNameAndPath;
448 // if we switch from a file to a folder item it means we really shouldn't be sorting files and
449 // folders separately
450 if (pItem->m_bIsFolder != match->m_bIsFolder)
451 items.SetSortIgnoreFolders(true);
452 pItem->m_bIsFolder = match->m_bIsFolder;
456 if (CFile::Exists(match->GetCachedFanart()))
457 pItem->SetProperty("fanart_image", match->GetCachedFanart());
458 pItem->SetLabel (label);
459 pItem->SetLabel2(label);
463 { // set the watched overlay (note: items in a folder with content set that aren't in the db
464 // won't get picked up here - in the future all items will be returned)
465 // and clean the label
466 if (pItem->HasVideoInfoTag())
467 pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pItem->GetVideoInfoTag()->m_playCount > 0);
469 pItem->CleanString();
474 void CGUIWindowVideoNav::UpdateButtons()
476 CGUIWindowVideoBase::UpdateButtons();
478 // Update object count
479 int iItems = m_vecItems->Size();
482 // check for parent dir and "all" items
483 // should always be the first two items
484 for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++)
486 CFileItemPtr pItem = m_vecItems->Get(i);
487 if (pItem->IsParentFolder()) iItems--;
488 if (pItem->m_strPath.Left(4).Equals("/-1/")) iItems--;
491 if (m_vecItems->Size() > 2 &&
492 m_vecItems->Get(m_vecItems->Size()-1)->m_strPath.Left(4).Equals("/-1/"))
496 items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str());
497 SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
499 // set the filter label
503 if (m_vecItems->m_strPath.Equals("special://videoplaylists/"))
504 strLabel = g_localizeStrings.Get(136);
506 else if (m_vecItems->IsPlayList())
508 // get playlist name from path
510 URIUtils::Split(m_vecItems->m_strPath, strDummy, strLabel);
512 else if (m_vecItems->m_strPath.Equals("sources://video/"))
513 strLabel = g_localizeStrings.Get(744);
514 // everything else is from a videodb:// path
515 else if (m_vecItems->IsVideoDb())
517 CVideoDatabaseDirectory dir;
518 dir.GetLabel(m_vecItems->m_strPath, strLabel);
521 strLabel = URIUtils::GetFileName(m_vecItems->m_strPath);
523 SET_CONTROL_LABEL(CONTROL_FILTER, strLabel);
525 int watchMode = g_settings.GetWatchMode(m_vecItems->GetContent());
526 SET_CONTROL_LABEL(CONTROL_BTNSHOWMODE, g_localizeStrings.Get(16100 + watchMode));
528 SET_CONTROL_SELECTED(GetID(), CONTROL_BTNSHOWALL, watchMode != VIDEO_SHOW_ALL);
530 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
532 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNFLATTEN, g_settings.m_bMyVideoNavFlatten);
535 /// \brief Search for names, genres, artists, directors, and plots with search string \e strSearch in the
536 /// \brief video databases and return the found \e items
537 /// \param strSearch The search string
538 /// \param items Items Found
539 void CGUIWindowVideoNav::DoSearch(const CStdString& strSearch, CFileItemList& items)
541 CFileItemList tempItems;
542 CStdString strGenre = g_localizeStrings.Get(515); // Genre
543 CStdString strActor = g_localizeStrings.Get(20337); // Actor
544 CStdString strDirector = g_localizeStrings.Get(20339); // Director
545 CStdString strMovie = g_localizeStrings.Get(20338); // Movie
548 m_database.GetMoviesByName(strSearch, tempItems);
549 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20338) + "] ", items);
551 m_database.GetEpisodesByName(strSearch, tempItems);
552 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20359) + "] ", items);
554 m_database.GetTvShowsByName(strSearch, tempItems);
555 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20364) + "] ", items);
557 m_database.GetMusicVideosByName(strSearch, tempItems);
558 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20391) + "] ", items);
560 m_database.GetMusicVideosByAlbum(strSearch, tempItems);
561 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(558) + "] ", items);
563 // get matching genres
564 m_database.GetMovieGenresByName(strSearch, tempItems);
565 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20342) + "] ", items);
567 m_database.GetTvShowGenresByName(strSearch, tempItems);
568 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20343) + "] ", items);
570 m_database.GetMusicVideoGenresByName(strSearch, tempItems);
571 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20389) + "] ", items);
574 m_database.GetMovieActorsByName(strSearch, tempItems);
575 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20342) + "] ", items);
577 m_database.GetTvShowsActorsByName(strSearch, tempItems);
578 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20343) + "] ", items);
580 m_database.GetMusicVideoArtistsByName(strSearch, tempItems);
581 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20389) + "] ", items);
584 m_database.GetMovieDirectorsByName(strSearch, tempItems);
585 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20342) + "] ", items);
587 m_database.GetTvShowsDirectorsByName(strSearch, tempItems);
588 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20343) + "] ", items);
590 m_database.GetMusicVideoDirectorsByName(strSearch, tempItems);
591 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20389) + "] ", items);
594 m_database.GetEpisodesByPlot(strSearch, tempItems);
595 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20365) + "] ", items);
597 m_database.GetMoviesByPlot(strSearch, tempItems);
598 AppendAndClearSearchItems(tempItems, "[" + strMovie + " " + g_localizeStrings.Get(207) + "] ", items);
601 void CGUIWindowVideoNav::PlayItem(int iItem)
603 // unlike additemtoplaylist, we need to check the items here
604 // before calling it since the current playlist will be stopped
607 // root is not allowed
608 if (m_vecItems->IsVirtualDirectoryRoot())
611 CGUIWindowVideoBase::PlayItem(iItem);
614 void CGUIWindowVideoNav::OnInfo(CFileItem* pItem, ADDON::ScraperPtr& scraper)
616 m_database.Open(); // since we can be called from the music library without being inited
617 if (pItem->IsVideoDb())
618 scraper = m_database.GetScraperForPath(pItem->GetVideoInfoTag()->m_strPath);
621 CStdString strPath,strFile;
622 URIUtils::Split(pItem->m_strPath,strPath,strFile);
623 scraper = m_database.GetScraperForPath(strPath);
626 CGUIWindowVideoBase::OnInfo(pItem,scraper);
629 bool CGUIWindowVideoNav::CanDelete(const CStdString& strPath)
632 CVideoDatabaseDirectory::GetQueryParams(strPath,params);
634 if (params.GetMovieId() != -1 ||
635 params.GetEpisodeId() != -1 ||
636 params.GetMVideoId() != -1 ||
637 (params.GetTvShowId() != -1 && params.GetSeason() == -1
638 && !CVideoDatabaseDirectory::IsAllItem(strPath)))
644 void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
646 if (m_vecItems->IsParentFolder())
649 if (!m_vecItems->IsVideoDb())
651 if (!pItem->m_strPath.Equals("newsmartplaylist://video") &&
652 !pItem->m_strPath.Equals("special://videoplaylists/") &&
653 !pItem->m_strPath.Equals("sources://video/"))
654 CGUIWindowVideoBase::OnDeleteItem(pItem);
656 else if (pItem->m_strPath.Left(14).Equals("videodb://1/7/") &&
657 pItem->m_strPath.size() > 14 && pItem->m_bIsFolder)
659 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
660 pDialog->SetLine(0, g_localizeStrings.Get(432));
662 strLabel.Format(g_localizeStrings.Get(433),pItem->GetLabel());
663 pDialog->SetLine(1, strLabel);
664 pDialog->SetLine(2, "");;
666 if (pDialog->IsConfirmed())
669 CDirectory::GetDirectory(pItem->m_strPath,items,"",false,false,DIR_CACHE_ONCE,true,true);
670 for (int i=0;i<items.Size();++i)
671 OnDeleteItem(items[i]);
673 CVideoDatabaseDirectory dir;
675 dir.GetQueryParams(pItem->m_strPath,params);
676 m_database.DeleteSet(params.GetSetId());
681 if (!DeleteItem(pItem.get()))
684 CStdString strDeletePath;
685 if (pItem->m_bIsFolder)
686 strDeletePath=pItem->GetVideoInfoTag()->m_strPath;
688 strDeletePath=pItem->GetVideoInfoTag()->m_strFileNameAndPath;
690 if (URIUtils::GetFileName(strDeletePath).Equals("VIDEO_TS.IFO"))
692 URIUtils::GetDirectory(strDeletePath.Mid(0),strDeletePath);
693 if (strDeletePath.Right(9).Equals("VIDEO_TS/"))
695 URIUtils::RemoveSlashAtEnd(strDeletePath);
696 URIUtils::GetDirectory(strDeletePath.Mid(0),strDeletePath);
699 if (URIUtils::HasSlashAtEnd(strDeletePath))
700 pItem->m_bIsFolder=true;
702 if (g_guiSettings.GetBool("filelists.allowfiledeletion") &&
703 CUtil::SupportsFileOperations(strDeletePath))
705 pItem->m_strPath = strDeletePath;
706 CGUIWindowVideoBase::OnDeleteItem(pItem);
710 CUtil::DeleteVideoDatabaseDirectoryCache();
713 bool CGUIWindowVideoNav::DeleteItem(CFileItem* pItem, bool bUnavailable /* = false */)
715 if (!pItem->HasVideoInfoTag() || !CanDelete(pItem->m_strPath))
718 VIDEODB_CONTENT_TYPE iType=VIDEODB_CONTENT_MOVIES;
719 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_strShowTitle.IsEmpty())
720 iType = VIDEODB_CONTENT_TVSHOWS;
721 if (pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iSeason > -1 && !pItem->m_bIsFolder)
722 iType = VIDEODB_CONTENT_EPISODES;
723 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_strArtist.IsEmpty())
724 iType = VIDEODB_CONTENT_MUSICVIDEOS;
726 // dont allow update while scanning
727 CGUIDialogVideoScan* pDialogScan = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
728 if (pDialogScan && pDialogScan->IsScanning())
730 CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0);
735 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
738 if (iType == VIDEODB_CONTENT_MOVIES)
739 pDialog->SetHeading(432);
740 if (iType == VIDEODB_CONTENT_EPISODES)
741 pDialog->SetHeading(20362);
742 if (iType == VIDEODB_CONTENT_TVSHOWS)
743 pDialog->SetHeading(20363);
744 if (iType == VIDEODB_CONTENT_MUSICVIDEOS)
745 pDialog->SetHeading(20392);
749 pDialog->SetLine(0, g_localizeStrings.Get(662));
750 pDialog->SetLine(1, g_localizeStrings.Get(663));
751 pDialog->SetLine(2, "");;
757 strLine.Format(g_localizeStrings.Get(433),pItem->GetLabel());
758 pDialog->SetLine(0, strLine);
759 pDialog->SetLine(1, "");
760 pDialog->SetLine(2, "");;
764 if (!pDialog->IsConfirmed())
768 CVideoDatabase database;
771 database.GetFilePathById(pItem->GetVideoInfoTag()->m_iDbId, path, iType);
774 if (iType == VIDEODB_CONTENT_MOVIES)
775 database.DeleteMovie(path);
776 if (iType == VIDEODB_CONTENT_EPISODES)
777 database.DeleteEpisode(path, pItem->GetVideoInfoTag()->m_iDbId);
778 if (iType == VIDEODB_CONTENT_TVSHOWS)
779 database.DeleteTvShow(path);
780 if (iType == VIDEODB_CONTENT_MUSICVIDEOS)
781 database.DeleteMusicVideo(path);
783 if (iType == VIDEODB_CONTENT_TVSHOWS)
784 database.SetPathHash(path,"");
787 CStdString strDirectory;
788 URIUtils::GetDirectory(path,strDirectory);
789 database.SetPathHash(strDirectory,"");
795 void CGUIWindowVideoNav::OnPrepareFileItems(CFileItemList &items)
797 CGUIWindowVideoBase::OnPrepareFileItems(items);
801 CVideoDatabaseDirectory dir;
802 dir.GetQueryParams(items.m_strPath,params);
803 if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS)
804 CGUIWindowMusicNav::SetupFanart(items);
806 NODE_TYPE node = dir.GetDirectoryChildType(items.m_strPath);
808 // now filter as necessary
809 bool filterWatched=false;
810 if (node == NODE_TYPE_EPISODES
811 || node == NODE_TYPE_SEASONS
812 || node == NODE_TYPE_TITLE_MOVIES
813 || node == NODE_TYPE_TITLE_TVSHOWS
814 || node == NODE_TYPE_TITLE_MUSICVIDEOS
815 || node == NODE_TYPE_RECENTLY_ADDED_EPISODES
816 || node == NODE_TYPE_RECENTLY_ADDED_MOVIES
817 || node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
818 filterWatched = true;
819 if (!items.IsVideoDb())
820 filterWatched = true;
821 if (items.IsSmartPlayList() && items.GetContent() == "tvshows")
822 node = NODE_TYPE_TITLE_TVSHOWS; // so that the check below works
824 int watchMode = g_settings.GetWatchMode(m_vecItems->GetContent());
826 for (int i = 0; i < items.Size(); i++)
828 CFileItemPtr item = items.Get(i);
829 if(item->HasVideoInfoTag() && (node == NODE_TYPE_TITLE_TVSHOWS || node == NODE_TYPE_SEASONS))
831 if (watchMode == VIDEO_SHOW_UNWATCHED)
832 item->GetVideoInfoTag()->m_iEpisode = item->GetPropertyInt("unwatchedepisodes");
833 if (watchMode == VIDEO_SHOW_WATCHED)
834 item->GetVideoInfoTag()->m_iEpisode = item->GetPropertyInt("watchedepisodes");
835 item->SetProperty("numepisodes", item->GetVideoInfoTag()->m_iEpisode);
840 if((watchMode==VIDEO_SHOW_WATCHED && item->GetVideoInfoTag()->m_playCount== 0)
841 || (watchMode==VIDEO_SHOW_UNWATCHED && item->GetVideoInfoTag()->m_playCount > 0))
850 void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &buttons)
853 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
854 item = m_vecItems->Get(itemNumber);
856 CGUIWindowVideoBase::GetContextButtons(itemNumber, buttons);
858 if (item && item->GetPropertyBOOL("pluginreplacecontextitems"))
861 CVideoDatabaseDirectory dir;
862 NODE_TYPE node = dir.GetDirectoryChildType(m_vecItems->m_strPath);
866 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
867 if (pScanDlg && pScanDlg->IsScanning())
868 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
870 buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
872 else if (m_vecItems->m_strPath.Equals("sources://video/"))
874 // get the usual shares
875 CGUIDialogContextMenu::GetContextButtons("video", item, buttons);
876 // add scan button somewhere here
877 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
878 if (pScanDlg && pScanDlg->IsScanning())
879 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); // Stop Scanning
880 if (!item->IsDVD() && item->m_strPath != "add" &&
881 (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser))
883 CVideoDatabase database;
885 ADDON::ScraperPtr info = database.GetScraperForPath(item->m_strPath);
887 if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
889 if (!item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
891 if (info && info->Content() != CONTENT_NONE)
892 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
894 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
898 if (info && (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning())))
899 buttons.Add(CONTEXT_BUTTON_SCAN, 13349);
904 ADDON::ScraperPtr info;
905 VIDEO::SScanSettings settings;
906 GetScraperForItem(item.get(), info, settings);
908 if (info && info->Content() == CONTENT_TVSHOWS)
909 buttons.Add(CONTEXT_BUTTON_INFO, item->m_bIsFolder ? 20351 : 20352);
910 else if (info && info->Content() == CONTENT_MUSICVIDEOS)
911 buttons.Add(CONTEXT_BUTTON_INFO,20393);
912 else if (!item->m_bIsFolder && !item->m_strPath.Left(19).Equals("newsmartplaylist://"))
913 buttons.Add(CONTEXT_BUTTON_INFO, 13346);
915 if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_strArtist.IsEmpty())
917 CMusicDatabase database;
919 if (database.GetArtistByName(item->GetVideoInfoTag()->m_strArtist) > -1)
920 buttons.Add(CONTEXT_BUTTON_GO_TO_ARTIST, 20396);
922 if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_strAlbum.size() > 0)
924 CMusicDatabase database;
926 if (database.GetAlbumByName(item->GetVideoInfoTag()->m_strAlbum) > -1)
927 buttons.Add(CONTEXT_BUTTON_GO_TO_ALBUM, 20397);
929 if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_strAlbum.size() > 0 &&
930 item->GetVideoInfoTag()->m_strArtist.size() > 0 &&
931 item->GetVideoInfoTag()->m_strTitle.size() > 0)
933 CMusicDatabase database;
935 if (database.GetSongByArtistAndAlbumAndTitle(item->GetVideoInfoTag()->m_strArtist,
936 item->GetVideoInfoTag()->m_strAlbum,
937 item->GetVideoInfoTag()->m_strTitle) > -1)
939 buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 20398);
942 if (!item->IsParentFolder())
944 // can we update the database?
945 if (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser)
947 if (node == NODE_TYPE_TITLE_TVSHOWS)
949 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
950 if (pScanDlg && pScanDlg->IsScanning())
951 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
953 buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349);
955 if (!item->IsPlugin() && !item->IsLiveTV() && !item->IsAddonsPath() &&
956 item->m_strPath != "sources://video/" && item->m_strPath != "special://videoplaylists/")
958 if (item->m_bIsFolder)
960 // Have both options for folders since we don't know whether all childs are watched/unwatched
961 buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
962 buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); //Mark as Watched
966 if (item->GetOverlayImage().Equals("OverlayWatched.png"))
967 buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
969 buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); //Mark as Watched
972 if ((node == NODE_TYPE_TITLE_TVSHOWS) ||
973 (item->IsVideoDb() && item->HasVideoInfoTag() && !item->m_bIsFolder))
975 buttons.Add(CONTEXT_BUTTON_EDIT, 16105); //Edit Title
977 if (m_database.HasContent(VIDEODB_CONTENT_TVSHOWS) && item->HasVideoInfoTag() &&
978 !item->m_bIsFolder && item->GetVideoInfoTag()->m_iEpisode == -1 &&
979 item->GetVideoInfoTag()->m_strArtist.IsEmpty() && item->GetVideoInfoTag()->m_iDbId >= 0) // movie entry
981 if (m_database.IsLinkedToTvshow(item->GetVideoInfoTag()->m_iDbId))
982 buttons.Add(CONTEXT_BUTTON_UNLINK_MOVIE,20385);
983 buttons.Add(CONTEXT_BUTTON_LINK_MOVIE,20384);
986 if (node == NODE_TYPE_SEASONS && item->m_bIsFolder)
987 buttons.Add(CONTEXT_BUTTON_SET_SEASON_THUMB, 20371);
989 if (item->m_strPath.Left(14).Equals("videodb://1/7/") && item->m_strPath.size() > 14 && item->m_bIsFolder) // sets
991 buttons.Add(CONTEXT_BUTTON_EDIT, 16105);
992 buttons.Add(CONTEXT_BUTTON_SET_MOVIESET_THUMB, 20435);
993 buttons.Add(CONTEXT_BUTTON_DELETE, 646);
996 if (node == NODE_TYPE_ACTOR && !dir.IsAllItem(item->m_strPath) && item->m_bIsFolder)
998 if (m_vecItems->m_strPath.Left(11).Equals("videodb://3")) // mvids
999 buttons.Add(CONTEXT_BUTTON_SET_ARTIST_THUMB, 13359);
1001 buttons.Add(CONTEXT_BUTTON_SET_ACTOR_THUMB, 20403);
1003 if (item->IsVideoDb() && item->HasVideoInfoTag() &&
1004 (!item->m_bIsFolder || node == NODE_TYPE_TITLE_TVSHOWS))
1006 if (info && info->Content() == CONTENT_TVSHOWS)
1008 if(item->GetVideoInfoTag()->m_iBookmarkId != -1 &&
1009 item->GetVideoInfoTag()->m_iBookmarkId != 0)
1011 buttons.Add(CONTEXT_BUTTON_UNLINK_BOOKMARK, 20405);
1014 buttons.Add(CONTEXT_BUTTON_DELETE, 646);
1017 // this should ideally be non-contextual (though we need some context for non-tv show node I guess)
1018 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1019 if (pScanDlg && pScanDlg->IsScanning())
1021 if (node != NODE_TYPE_TITLE_TVSHOWS)
1022 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
1025 buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
1028 if (!m_vecItems->IsVideoDb() && !m_vecItems->IsVirtualDirectoryRoot())
1029 { // non-video db items, file operations are allowed
1030 if (g_guiSettings.GetBool("filelists.allowfiledeletion") &&
1031 CUtil::SupportsFileOperations(item->m_strPath))
1033 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
1034 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
1036 // add "Set/Change content" to folders
1037 if (item->m_bIsFolder && !item->IsPlayList() && !item->IsSmartPlayList() && !item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
1039 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1040 if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
1042 if (info && info->Content() != CONTENT_NONE)
1043 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
1045 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
1049 if (item->IsPlugin() || item->m_strPath.Left(9).Equals("script://") || m_vecItems->IsPlugin())
1050 buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
1053 CGUIWindowVideoBase::GetNonContextButtons(itemNumber, buttons);
1056 bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
1059 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
1060 item = m_vecItems->Get(itemNumber);
1061 if (CGUIDialogContextMenu::OnContextButton("video", item, button))
1063 //TODO should we search DB for entries from plugins?
1064 if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin()
1065 && !item->IsLiveTV() &&!item->IsRSS())
1067 OnUnAssignContent(item->m_strPath,20375,20340,20341);
1069 Update(m_vecItems->m_strPath);
1074 case CONTEXT_BUTTON_EDIT:
1075 UpdateVideoTitle(item.get());
1076 CUtil::DeleteVideoDatabaseDirectoryCache();
1077 Update(m_vecItems->m_strPath);
1080 case CONTEXT_BUTTON_SET_SEASON_THUMB:
1081 case CONTEXT_BUTTON_SET_ACTOR_THUMB:
1082 case CONTEXT_BUTTON_SET_ARTIST_THUMB:
1083 case CONTEXT_BUTTON_SET_MOVIESET_THUMB:
1085 // Grab the thumbnails from the web
1087 CFileItemList items;
1088 URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath,"imdbthumbs",strPath);
1089 CFileItemPtr cacheItem(new CFileItem(strPath,true));
1090 CFileUtils::DeleteItem(cacheItem,true);
1091 XFILE::CDirectory::Create(strPath);
1092 CFileItemPtr noneitem(new CFileItem("thumb://None", false));
1093 CStdString cachedThumb = m_vecItems->Get(itemNumber)->GetCachedSeasonThumb();
1094 if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB)
1095 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedActorThumb();
1096 if (button == CONTEXT_BUTTON_SET_ARTIST_THUMB)
1097 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedArtistThumb();
1098 if (button == CONTEXT_BUTTON_SET_MOVIESET_THUMB)
1099 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedVideoThumb();
1100 if (CFile::Exists(cachedThumb))
1102 CFileItemPtr item(new CFileItem("thumb://Current", false));
1103 item->SetThumbnailImage(cachedThumb);
1104 item->SetLabel(g_localizeStrings.Get(20016));
1107 noneitem->SetIconImage("DefaultFolder.png");
1108 noneitem->SetLabel(g_localizeStrings.Get(20018));
1110 vector<CStdString> thumbs;
1111 if (button != CONTEXT_BUTTON_SET_ARTIST_THUMB)
1114 if (button == CONTEXT_BUTTON_SET_SEASON_THUMB)
1115 m_database.GetTvShowInfo("",tag,m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iDbId);
1117 tag = *m_vecItems->Get(itemNumber)->GetVideoInfoTag();
1118 if (button == CONTEXT_BUTTON_SET_SEASON_THUMB)
1119 tag.m_strPictureURL.GetThumbURLs(thumbs, m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iSeason);
1121 tag.m_strPictureURL.GetThumbURLs(thumbs);
1123 for (unsigned int i = 0; i < thumbs.size(); i++)
1125 CStdString strItemPath;
1126 strItemPath.Format("thumb://Remote%i",i);
1127 CFileItemPtr item(new CFileItem(strItemPath, false));
1128 item->SetThumbnailImage(thumbs[i]);
1129 item->SetIconImage("DefaultPicture.png");
1130 item->SetLabel(g_localizeStrings.Get(20015));
1133 // TODO: Do we need to clear the cached image?
1134 // CTextureCache::Get().ClearCachedImage(thumbs[i]);
1139 if (button == CONTEXT_BUTTON_SET_ARTIST_THUMB)
1141 CStdString picturePath;
1143 CStdString strPath = m_vecItems->Get(itemNumber)->m_strPath;
1144 URIUtils::RemoveSlashAtEnd(strPath);
1146 int nPos=strPath.ReverseFind("/");
1149 // try to guess where the user should start
1150 // browsing for the artist thumb
1151 CMusicDatabase database;
1153 long idArtist=database.GetArtistByName(m_vecItems->Get(itemNumber)->GetLabel());
1154 database.GetArtistPath(idArtist, picturePath);
1157 CStdString strThumb;
1158 URIUtils::AddFileToFolder(picturePath,"folder.jpg",strThumb);
1159 if (XFILE::CFile::Exists(strThumb))
1161 CFileItemPtr pItem(new CFileItem(strThumb,false));
1162 pItem->SetLabel(g_localizeStrings.Get(20017));
1163 pItem->SetThumbnailImage(strThumb);
1168 noneitem->SetIconImage("DefaultArtist.png");
1171 if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB)
1173 CStdString picturePath;
1174 CStdString strThumb;
1175 URIUtils::AddFileToFolder(picturePath,"folder.jpg",strThumb);
1176 if (XFILE::CFile::Exists(strThumb))
1178 CFileItemPtr pItem(new CFileItem(strThumb,false));
1179 pItem->SetLabel(g_localizeStrings.Get(20017));
1180 pItem->SetThumbnailImage(strThumb);
1185 noneitem->SetIconImage("DefaultActor.png");
1188 if (button == CONTEXT_BUTTON_SET_MOVIESET_THUMB)
1189 noneitem->SetIconImage("DefaultVideo.png");
1192 items.Add(noneitem);
1194 VECSOURCES sources=g_settings.m_videoSources;
1195 g_mediaManager.GetLocalDrives(sources);
1197 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources,
1198 g_localizeStrings.Get(20019), result))
1200 return false; // user cancelled
1203 if (result == "thumb://Current")
1204 return false; // user chose the one they have
1206 // delete the thumbnail if that's what the user wants, else overwrite with the
1208 CTextureCache::Get().ClearCachedImage(cachedThumb, true);
1209 if (result.Left(14) == "thumb://Remote")
1211 int number = atoi(result.Mid(14));
1212 CFile::Cache(thumbs[number], cachedThumb);
1214 if (result == "thumb://None")
1215 CTextureCache::Get().ClearCachedImage(cachedThumb, true);
1217 CFile::Cache(result,cachedThumb);
1219 CUtil::DeleteVideoDatabaseDirectoryCache();
1220 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
1221 g_windowManager.SendMessage(msg);
1222 Update(m_vecItems->m_strPath);
1226 case CONTEXT_BUTTON_UPDATE_LIBRARY:
1231 case CONTEXT_BUTTON_UNLINK_MOVIE:
1233 OnLinkMovieToTvShow(itemNumber, true);
1234 Update(m_vecItems->m_strPath);
1237 case CONTEXT_BUTTON_LINK_MOVIE:
1239 OnLinkMovieToTvShow(itemNumber, false);
1242 case CONTEXT_BUTTON_GO_TO_ARTIST:
1245 CMusicDatabase database;
1247 strPath.Format("musicdb://2/%ld/",database.GetArtistByName(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strArtist));
1248 g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath);
1251 case CONTEXT_BUTTON_GO_TO_ALBUM:
1254 CMusicDatabase database;
1256 strPath.Format("musicdb://3/%ld/",database.GetAlbumByName(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum));
1257 g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath);
1260 case CONTEXT_BUTTON_PLAY_OTHER:
1262 CMusicDatabase database;
1265 if (database.GetSongById(database.GetSongByArtistAndAlbumAndTitle(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strArtist,m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum,
1266 m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strTitle),
1269 g_application.getApplicationMessenger().PlayFile(song);
1274 case CONTEXT_BUTTON_UNLINK_BOOKMARK:
1277 m_database.DeleteBookMarkForEpisode(*m_vecItems->Get(itemNumber)->GetVideoInfoTag());
1279 CUtil::DeleteVideoDatabaseDirectoryCache();
1280 Update(m_vecItems->m_strPath);
1288 return CGUIWindowVideoBase::OnContextButton(itemNumber, button);
1291 void CGUIWindowVideoNav::OnLinkMovieToTvShow(int itemnumber, bool bRemove)
1297 if (!m_database.GetLinksToTvShow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,ids))
1299 for (unsigned int i=0;i<ids.size();++i)
1302 m_database.GetTvShowInfo("",tag,ids[i]);
1303 CFileItemPtr show(new CFileItem(tag));
1309 m_database.GetTvShowsNav("videodb://2/2",list);
1311 // remove already linked shows
1313 if (!m_database.GetLinksToTvShow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,ids))
1315 for (int i=0;i<list.Size();)
1318 for (j=0;j<ids.size();++j)
1320 if (list[i]->GetVideoInfoTag()->m_iDbId == ids[j])
1323 if (j == ids.size())
1329 int iSelectedLabel = 0;
1330 if (list.Size() > 1)
1332 list.Sort(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SORT_ORDER_ASC);
1333 CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
1335 pDialog->SetItems(&list);
1336 pDialog->SetHeading(20356);
1338 iSelectedLabel = pDialog->GetSelectedLabel();
1340 if (iSelectedLabel > -1)
1342 m_database.LinkMovieToTvshow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,
1343 list[iSelectedLabel]->GetVideoInfoTag()->m_iDbId, bRemove);
1344 CUtil::DeleteVideoDatabaseDirectoryCache();
1348 bool CGUIWindowVideoNav::OnClick(int iItem)
1350 CFileItemPtr item = m_vecItems->Get(iItem);
1351 if (!item->m_bIsFolder && item->IsVideoDb() && !item->Exists())
1353 if (!DeleteItem(item.get(), true))
1357 m_vecItems->RemoveDiscCache(GetID());
1358 Update(m_vecItems->m_strPath);
1359 m_viewControl.SetSelectedItem(iItem);
1363 return CGUIWindowVideoBase::OnClick(iItem);
1366 CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir)
1368 if (dir.Equals("MovieGenres"))
1369 return "videodb://1/1/";
1370 else if (dir.Equals("MovieTitles"))
1371 return "videodb://1/2/";
1372 else if (dir.Equals("MovieYears"))
1373 return "videodb://1/3/";
1374 else if (dir.Equals("MovieActors"))
1375 return "videodb://1/4/";
1376 else if (dir.Equals("MovieDirectors"))
1377 return "videodb://1/5/";
1378 else if (dir.Equals("MovieStudios"))
1379 return "videodb://1/6/";
1380 else if (dir.Equals("MovieSets"))
1381 return "videodb://1/7/";
1382 else if (dir.Equals("MovieCountries"))
1383 return "videodb://1/8/";
1384 else if (dir.Equals("Movies"))
1385 return "videodb://1/";
1386 else if (dir.Equals("TvShowGenres"))
1387 return "videodb://2/1/";
1388 else if (dir.Equals("TvShowTitles"))
1389 return "videodb://2/2/";
1390 else if (dir.Equals("TvShowYears"))
1391 return "videodb://2/3/";
1392 else if (dir.Equals("TvShowActors"))
1393 return "videodb://2/4/";
1394 else if (dir.Equals("TvShowStudios"))
1395 return "videodb://2/5/";
1396 else if (dir.Equals("TvShows"))
1397 return "videodb://2/";
1398 else if (dir.Equals("MusicVideoGenres"))
1399 return "videodb://3/1/";
1400 else if (dir.Equals("MusicVideoTitles"))
1401 return "videodb://3/2/";
1402 else if (dir.Equals("MusicVideoYears"))
1403 return "videodb://3/3/";
1404 else if (dir.Equals("MusicVideoArtists"))
1405 return "videodb://3/4/";
1406 else if (dir.Equals("MusicVideoDirectors"))
1407 return "videodb://3/5/";
1408 else if (dir.Equals("MusicVideoStudios"))
1409 return "videodb://3/6/";
1410 else if (dir.Equals("MusicVideos"))
1411 return "videodb://3/";
1412 else if (dir.Equals("RecentlyAddedMovies"))
1413 return "videodb://4/";
1414 else if (dir.Equals("RecentlyAddedEpisodes"))
1415 return "videodb://5/";
1416 else if (dir.Equals("RecentlyAddedMusicVideos"))
1417 return "videodb://6/";
1418 else if (dir.Equals("Files"))
1419 return "sources://video/";
1420 return CGUIWindowVideoBase::GetStartFolder(dir);