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 "pictures/Picture.h"
53 #include "TextureCache.h"
55 using namespace XFILE;
56 using namespace VIDEODATABASEDIRECTORY;
59 #define CONTROL_BTNVIEWASICONS 2
60 #define CONTROL_BTNSORTBY 3
61 #define CONTROL_BTNSORTASC 4
62 #define CONTROL_BTNTYPE 5
63 #define CONTROL_BTNSEARCH 8
64 #define CONTROL_LABELFILES 12
66 #define CONTROL_BTN_FILTER 19
67 #define CONTROL_BTNSHOWMODE 10
68 #define CONTROL_BTNSHOWALL 14
69 #define CONTROL_UNLOCK 11
71 #define CONTROL_FILTER 15
72 #define CONTROL_BTNPARTYMODE 16
73 #define CONTROL_BTNFLATTEN 17
74 #define CONTROL_LABELEMPTY 18
76 CGUIWindowVideoNav::CGUIWindowVideoNav(void)
77 : CGUIWindowVideoBase(WINDOW_VIDEO_NAV, "MyVideoNav.xml")
79 m_thumbLoader.SetObserver(this);
82 CGUIWindowVideoNav::~CGUIWindowVideoNav(void)
86 bool CGUIWindowVideoNav::OnAction(const CAction &action)
88 if (action.GetID() == ACTION_TOGGLE_WATCHED)
90 CFileItemPtr pItem = m_vecItems->Get(m_viewControl.GetSelectedItem());
91 if (pItem->IsParentFolder())
93 if (pItem && pItem->GetVideoInfoTag()->m_playCount == 0)
94 return OnContextButton(m_viewControl.GetSelectedItem(),CONTEXT_BUTTON_MARK_WATCHED);
95 if (pItem && pItem->GetVideoInfoTag()->m_playCount > 0)
96 return OnContextButton(m_viewControl.GetSelectedItem(),CONTEXT_BUTTON_MARK_UNWATCHED);
98 return CGUIWindowVideoBase::OnAction(action);
101 bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message)
103 switch (message.GetMessage())
105 case GUI_MSG_WINDOW_RESET:
106 m_vecItems->SetPath("");
108 case GUI_MSG_WINDOW_DEINIT:
109 if (m_thumbLoader.IsLoading())
110 m_thumbLoader.StopThread();
112 case GUI_MSG_WINDOW_INIT:
114 /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */
115 m_rootDir.AllowNonLocalSources(false);
117 SetProperty("flattened", g_settings.m_bMyVideoNavFlatten);
119 if (!CGUIWindowVideoBase::OnMessage(message))
122 // base class has opened the database, do our check
125 if (!m_database.HasContent() && m_vecItems->IsVideoDb())
126 { // no library - make sure we default to the root.
127 m_vecItems->SetPath("");
128 SetHistoryForPath("");
137 case GUI_MSG_CLICKED:
139 int iControl = message.GetSenderId();
140 if (iControl == CONTROL_BTNPARTYMODE)
142 if (g_partyModeManager.IsEnabled())
143 g_partyModeManager.Disable();
146 if (!g_partyModeManager.Enable(PARTYMODECONTEXT_VIDEO))
148 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE,false);
152 // Playlist directory is the root of the playlist window
153 if (m_guiState.get()) m_guiState->SetPlaylistDirectory("playlistvideo://");
160 if (iControl == CONTROL_BTNSEARCH)
164 else if (iControl == CONTROL_BTNSHOWMODE)
166 g_settings.CycleWatchMode(m_vecItems->GetContent());
169 // TODO: Can we perhaps filter this directly? Probably not for some of the more complicated views,
170 // but for those perhaps we can just display them all, and only filter when we get a list
172 Update(m_vecItems->GetPath());
175 else if (iControl == CONTROL_BTNFLATTEN)
177 g_settings.m_bMyVideoNavFlatten = !g_settings.m_bMyVideoNavFlatten;
179 SetProperty("flattened", g_settings.m_bMyVideoNavFlatten);
180 CUtil::DeleteVideoDatabaseDirectoryCache();
185 else if (iControl == CONTROL_BTNSHOWALL)
187 if (g_settings.GetWatchMode(m_vecItems->GetContent()) == VIDEO_SHOW_ALL)
188 g_settings.SetWatchMode(m_vecItems->GetContent(), VIDEO_SHOW_UNWATCHED);
190 g_settings.SetWatchMode(m_vecItems->GetContent(), VIDEO_SHOW_ALL);
192 // TODO: Can we perhaps filter this directly? Probably not for some of the more complicated views,
193 // but for those perhaps we can just display them all, and only filter when we get a list
195 Update(m_vecItems->GetPath());
200 // update the display
201 case GUI_MSG_SCAN_FINISHED:
202 case GUI_MSG_REFRESH_THUMBS:
204 Update(m_vecItems->GetPath());
208 return CGUIWindowVideoBase::OnMessage(message);
211 CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const
213 if (strPath.Equals("videodb://1/1/"))
214 return "MovieGenres";
215 else if (strPath.Equals("videodb://1/2/"))
216 return "MovieTitles";
217 else if (strPath.Equals("videodb://1/3/"))
219 else if (strPath.Equals("videodb://1/4/"))
220 return "MovieActors";
221 else if (strPath.Equals("videodb://1/5/"))
222 return "MovieDirectors";
223 else if (strPath.Equals("videodb://1/"))
225 else if (strPath.Equals("videodb://2/1/"))
226 return "TvShowGenres";
227 else if (strPath.Equals("videodb://2/2/"))
228 return "TvShowTitles";
229 else if (strPath.Equals("videodb://2/3/"))
230 return "TvShowYears";
231 else if (strPath.Equals("videodb://2/4/"))
232 return "TvShowActors";
233 else if (strPath.Equals("videodb://2/"))
235 else if (strPath.Equals("videodb://3/1/"))
236 return "MusicVideoGenres";
237 else if (strPath.Equals("videodb://3/2/"))
238 return "MusicVideoTitles";
239 else if (strPath.Equals("videodb://3/3/"))
240 return "MusicVideoYears";
241 else if (strPath.Equals("videodb://3/4/"))
242 return "MusicVideoArtists";
243 else if (strPath.Equals("videodb://3/5/"))
244 return "MusicVideoDirectors";
245 else if (strPath.Equals("videodb://3/"))
246 return "MusicVideos";
247 else if (strPath.Equals("videodb://4/"))
248 return "RecentlyAddedMovies";
249 else if (strPath.Equals("videodb://5/"))
250 return "RecentlyAddedEpisodes";
251 else if (strPath.Equals("videodb://6/"))
252 return "RecentlyAddedMusicVideos";
253 else if (strPath.Equals("special://videoplaylists/"))
255 else if (strPath.Equals("sources://video/"))
259 CLog::Log(LOGERROR, " CGUIWindowVideoNav::GetQuickpathName: Unknown parameter (%s)", strPath.c_str());
264 void CGUIWindowVideoNav::OnItemLoaded(CFileItem* pItem)
266 /* even though the background loader is running multiple threads and we could,
267 be acting on someone else's flag, we don't care who invalidates the cache
268 only that it is done. We also don't care if it is done multiple times due
269 to a race between multiple threads here at the same time */
270 CUtil::DeleteVideoDatabaseDirectoryCache();
273 bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items)
275 CFileItem directory(strDirectory, true);
277 if (m_thumbLoader.IsLoading())
278 m_thumbLoader.StopThread();
280 m_rootDir.SetCacheDirectory(DIR_CACHE_ONCE);
281 items.ClearProperties();
283 bool bResult = CGUIWindowVideoBase::GetDirectory(strDirectory, items);
286 if (items.IsVideoDb())
288 XFILE::CVideoDatabaseDirectory dir;
290 dir.GetQueryParams(items.GetPath(),params);
291 VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
293 items.SetThumbnailImage("");
294 if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES ||
295 node == NODE_TYPE_SEASONS ||
296 node == NODE_TYPE_RECENTLY_ADDED_EPISODES)
298 CLog::Log(LOGDEBUG, "WindowVideoNav::GetDirectory");
299 // grab the show thumb
301 m_database.GetFilePathById(params.GetTvShowId(),path,VIDEODB_CONTENT_TVSHOWS);
302 CFileItem showItem(path, true);
303 showItem.SetVideoThumb();
304 items.SetProperty("tvshowthumb", showItem.GetThumbnailImage());
306 CVideoInfoTag details;
307 m_database.GetTvShowInfo(showItem.GetPath(), details, params.GetTvShowId());
308 items.SetProperty("fanart_color1", details.m_fanart.GetColor(0));
309 items.SetProperty("fanart_color2", details.m_fanart.GetColor(1));
310 items.SetProperty("fanart_color3", details.m_fanart.GetColor(2));
311 if (showItem.CacheLocalFanart())
312 items.SetProperty("fanart_image", showItem.GetCachedFanart());
314 // save the show description (showplot)
315 items.SetProperty("showplot", details.m_strPlot);
317 // set the season thumb
319 if (params.GetSeason() == 0)
320 strLabel = g_localizeStrings.Get(20381);
322 strLabel.Format(g_localizeStrings.Get(20358), params.GetSeason());
324 CFileItem item(strLabel);
325 item.SetPath(URIUtils::GetParentPath(items.GetPath()));
326 item.m_bIsFolder = true;
327 item.SetCachedSeasonThumb();
328 if (item.HasThumbnail())
329 items.SetProperty("seasonthumb",item.GetThumbnailImage());
331 // the container folder thumb is the parent (i.e. season or show)
332 if (node == NODE_TYPE_EPISODES || node == NODE_TYPE_RECENTLY_ADDED_EPISODES)
334 items.SetContent("episodes");
335 // grab the season thumb as the folder thumb
338 if (params.GetSeason() == -1 && items.Size() > 0)
340 CQueryParams params2;
341 dir.GetQueryParams(items[0]->GetPath(),params2);
342 strLabel.Format(g_localizeStrings.Get(20358), params2.GetSeason());
343 strPath = URIUtils::GetParentPath(items.GetPath());
347 if (params.GetSeason() == 0)
348 strLabel = g_localizeStrings.Get(20381);
350 strLabel.Format(g_localizeStrings.Get(20358), params.GetSeason());
351 strPath = items.GetPath();
354 CFileItem item(strPath, true);
355 item.SetLabel(strLabel);
356 item.GetVideoInfoTag()->m_strPath = showItem.GetPath();
357 item.SetCachedSeasonThumb();
359 items.SetThumbnailImage(item.GetThumbnailImage());
360 items.SetProperty("seasonthumb",item.GetThumbnailImage());
364 items.SetContent("seasons");
365 items.SetThumbnailImage(showItem.GetThumbnailImage());
368 else if (node == NODE_TYPE_TITLE_MOVIES ||
369 node == NODE_TYPE_RECENTLY_ADDED_MOVIES)
370 items.SetContent("movies");
371 else if (node == NODE_TYPE_TITLE_TVSHOWS)
372 items.SetContent("tvshows");
373 else if (node == NODE_TYPE_TITLE_MUSICVIDEOS ||
374 node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
375 items.SetContent("musicvideos");
376 else if (node == NODE_TYPE_GENRE)
377 items.SetContent("genres");
378 else if (node == NODE_TYPE_COUNTRY)
379 items.SetContent("countries");
380 else if (node == NODE_TYPE_ACTOR)
382 if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS)
383 items.SetContent("artists");
385 items.SetContent("actors");
387 else if (node == NODE_TYPE_DIRECTOR)
388 items.SetContent("directors");
389 else if (node == NODE_TYPE_STUDIO)
390 items.SetContent("studios");
391 else if (node == NODE_TYPE_YEAR)
392 items.SetContent("years");
393 else if (node == NODE_TYPE_MUSICVIDEOS_ALBUM)
394 items.SetContent("albums");
396 items.SetContent("");
399 { // load info from the database
401 if (items.GetLabel().IsEmpty() && m_rootDir.IsSource(items.GetPath(), g_settings.GetSourcesFromType("video"), &label))
402 items.SetLabel(label);
403 LoadVideoInfo(items);
409 void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items)
411 // TODO: this could possibly be threaded as per the music info loading,
412 // we could also cache the info
413 if (!items.GetContent().IsEmpty())
414 return; // don't load for listings that have content set
416 CStdString content = m_database.GetContentForPath(items.GetPath());
417 items.SetContent(content.IsEmpty() ? "files" : content);
419 bool fileMetaData = (g_guiSettings.GetBool("myvideos.filemetadata") &&
420 !content.IsEmpty() &&
421 m_stackingAvailable);
423 CFileItemList dbItems;
424 /* NOTE: In the future when GetItemsForPath returns all items regardless of whether they're "in the library"
425 we won't need the fetchedPlayCounts code, and can "simply" do this directly on absense of content. */
426 bool fetchedPlayCounts = false;
427 if (!content.IsEmpty())
429 m_database.GetItemsForPath(content, items.GetPath(), dbItems);
430 dbItems.SetFastLookup(true);
433 for (int i = 0; i < items.Size(); i++)
435 CFileItemPtr pItem = items[i];
437 if (!content.IsEmpty())
438 match = dbItems.Get(pItem->GetPath());
441 CStdString label (pItem->GetLabel ());
442 CStdString label2(pItem->GetLabel2());
443 pItem->UpdateInfo(*match);
447 if (match->m_bIsFolder)
448 pItem->SetPath(match->GetVideoInfoTag()->m_strPath);
450 pItem->SetPath(match->GetVideoInfoTag()->m_strFileNameAndPath);
451 // if we switch from a file to a folder item it means we really shouldn't be sorting files and
452 // folders separately
453 if (pItem->m_bIsFolder != match->m_bIsFolder)
455 items.SetSortIgnoreFolders(true);
456 pItem->m_bIsFolder = match->m_bIsFolder;
461 if (CFile::Exists(match->GetCachedFanart()))
462 pItem->SetProperty("fanart_image", match->GetCachedFanart());
464 pItem->SetLabel (label);
465 pItem->SetLabel2(label2);
470 /* NOTE: Currently we GetPlayCounts on our items regardless of whether content is set
471 as if content is set, GetItemsForPaths doesn't return anything not in the content tables.
472 This code can be removed once the content tables are always filled */
473 if (!pItem->m_bIsFolder && !fetchedPlayCounts)
475 m_database.GetPlayCounts(items.GetPath(), items);
476 fetchedPlayCounts = true;
479 // set the watched overlay
480 if (pItem->HasVideoInfoTag())
481 pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pItem->GetVideoInfoTag()->m_playCount > 0);
483 // Since the item is not in our db, as an alternative clean its name
485 pItem->CleanString();
490 void CGUIWindowVideoNav::UpdateButtons()
492 CGUIWindowVideoBase::UpdateButtons();
494 // Update object count
495 int iItems = m_vecItems->Size();
498 // check for parent dir and "all" items
499 // should always be the first two items
500 for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++)
502 CFileItemPtr pItem = m_vecItems->Get(i);
503 if (pItem->IsParentFolder()) iItems--;
504 if (pItem->GetPath().Left(4).Equals("/-1/")) iItems--;
507 if (m_vecItems->Size() > 2 &&
508 m_vecItems->Get(m_vecItems->Size()-1)->GetPath().Left(4).Equals("/-1/"))
512 items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str());
513 SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
515 // set the filter label
519 if (m_vecItems->GetPath().Equals("special://videoplaylists/"))
520 strLabel = g_localizeStrings.Get(136);
522 else if (m_vecItems->IsPlayList())
524 // get playlist name from path
526 URIUtils::Split(m_vecItems->GetPath(), strDummy, strLabel);
528 else if (m_vecItems->GetPath().Equals("sources://video/"))
529 strLabel = g_localizeStrings.Get(744);
530 // everything else is from a videodb:// path
531 else if (m_vecItems->IsVideoDb())
533 CVideoDatabaseDirectory dir;
534 dir.GetLabel(m_vecItems->GetPath(), strLabel);
537 strLabel = URIUtils::GetFileName(m_vecItems->GetPath());
539 SET_CONTROL_LABEL(CONTROL_FILTER, strLabel);
541 int watchMode = g_settings.GetWatchMode(m_vecItems->GetContent());
542 SET_CONTROL_LABEL(CONTROL_BTNSHOWMODE, g_localizeStrings.Get(16100 + watchMode));
544 SET_CONTROL_SELECTED(GetID(), CONTROL_BTNSHOWALL, watchMode != VIDEO_SHOW_ALL);
546 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
548 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNFLATTEN, g_settings.m_bMyVideoNavFlatten);
551 /// \brief Search for names, genres, artists, directors, and plots with search string \e strSearch in the
552 /// \brief video databases and return the found \e items
553 /// \param strSearch The search string
554 /// \param items Items Found
555 void CGUIWindowVideoNav::DoSearch(const CStdString& strSearch, CFileItemList& items)
557 CFileItemList tempItems;
558 CStdString strGenre = g_localizeStrings.Get(515); // Genre
559 CStdString strActor = g_localizeStrings.Get(20337); // Actor
560 CStdString strDirector = g_localizeStrings.Get(20339); // Director
561 CStdString strMovie = g_localizeStrings.Get(20338); // Movie
564 m_database.GetMoviesByName(strSearch, tempItems);
565 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20338) + "] ", items);
567 m_database.GetEpisodesByName(strSearch, tempItems);
568 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20359) + "] ", items);
570 m_database.GetTvShowsByName(strSearch, tempItems);
571 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20364) + "] ", items);
573 m_database.GetMusicVideosByName(strSearch, tempItems);
574 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20391) + "] ", items);
576 m_database.GetMusicVideosByAlbum(strSearch, tempItems);
577 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(558) + "] ", items);
579 // get matching genres
580 m_database.GetMovieGenresByName(strSearch, tempItems);
581 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20342) + "] ", items);
583 m_database.GetTvShowGenresByName(strSearch, tempItems);
584 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20343) + "] ", items);
586 m_database.GetMusicVideoGenresByName(strSearch, tempItems);
587 AppendAndClearSearchItems(tempItems, "[" + strGenre + " - " + g_localizeStrings.Get(20389) + "] ", items);
590 m_database.GetMovieActorsByName(strSearch, tempItems);
591 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20342) + "] ", items);
593 m_database.GetTvShowsActorsByName(strSearch, tempItems);
594 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20343) + "] ", items);
596 m_database.GetMusicVideoArtistsByName(strSearch, tempItems);
597 AppendAndClearSearchItems(tempItems, "[" + strActor + " - " + g_localizeStrings.Get(20389) + "] ", items);
600 m_database.GetMovieDirectorsByName(strSearch, tempItems);
601 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20342) + "] ", items);
603 m_database.GetTvShowsDirectorsByName(strSearch, tempItems);
604 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20343) + "] ", items);
606 m_database.GetMusicVideoDirectorsByName(strSearch, tempItems);
607 AppendAndClearSearchItems(tempItems, "[" + strDirector + " - " + g_localizeStrings.Get(20389) + "] ", items);
610 m_database.GetEpisodesByPlot(strSearch, tempItems);
611 AppendAndClearSearchItems(tempItems, "[" + g_localizeStrings.Get(20365) + "] ", items);
613 m_database.GetMoviesByPlot(strSearch, tempItems);
614 AppendAndClearSearchItems(tempItems, "[" + strMovie + " " + g_localizeStrings.Get(207) + "] ", items);
617 void CGUIWindowVideoNav::PlayItem(int iItem)
619 // unlike additemtoplaylist, we need to check the items here
620 // before calling it since the current playlist will be stopped
623 // root is not allowed
624 if (m_vecItems->IsVirtualDirectoryRoot())
627 CGUIWindowVideoBase::PlayItem(iItem);
630 void CGUIWindowVideoNav::OnInfo(CFileItem* pItem, ADDON::ScraperPtr& scraper)
632 m_database.Open(); // since we can be called from the music library without being inited
633 if (pItem->IsVideoDb())
634 scraper = m_database.GetScraperForPath(pItem->GetVideoInfoTag()->m_strPath);
637 CStdString strPath,strFile;
638 URIUtils::Split(pItem->GetPath(),strPath,strFile);
639 scraper = m_database.GetScraperForPath(strPath);
642 CGUIWindowVideoBase::OnInfo(pItem,scraper);
645 bool CGUIWindowVideoNav::CanDelete(const CStdString& strPath)
648 CVideoDatabaseDirectory::GetQueryParams(strPath,params);
650 if (params.GetMovieId() != -1 ||
651 params.GetEpisodeId() != -1 ||
652 params.GetMVideoId() != -1 ||
653 (params.GetTvShowId() != -1 && params.GetSeason() == -1
654 && !CVideoDatabaseDirectory::IsAllItem(strPath)))
660 void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
662 if (m_vecItems->IsParentFolder())
665 if (!m_vecItems->IsVideoDb() && !pItem->IsVideoDb())
667 if (!pItem->GetPath().Equals("newsmartplaylist://video") &&
668 !pItem->GetPath().Equals("special://videoplaylists/") &&
669 !pItem->GetPath().Equals("sources://video/"))
670 CGUIWindowVideoBase::OnDeleteItem(pItem);
672 else if (pItem->GetPath().Left(14).Equals("videodb://1/7/") &&
673 pItem->GetPath().size() > 14 && pItem->m_bIsFolder)
675 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
676 pDialog->SetLine(0, g_localizeStrings.Get(432));
678 strLabel.Format(g_localizeStrings.Get(433),pItem->GetLabel());
679 pDialog->SetLine(1, strLabel);
680 pDialog->SetLine(2, "");;
682 if (pDialog->IsConfirmed())
685 CDirectory::GetDirectory(pItem->GetPath(),items,"",false,false,DIR_CACHE_ONCE,true,true);
686 for (int i=0;i<items.Size();++i)
687 OnDeleteItem(items[i]);
689 CVideoDatabaseDirectory dir;
691 dir.GetQueryParams(pItem->GetPath(),params);
692 m_database.DeleteSet(params.GetSetId());
695 else if (m_vecItems->GetPath().Equals(CUtil::VideoPlaylistsLocation()) ||
696 m_vecItems->GetPath().Equals("special://videoplaylists/"))
698 pItem->m_bIsFolder = false;
699 CFileUtils::DeleteItem(pItem);
703 if (!DeleteItem(pItem.get()))
706 CStdString strDeletePath;
707 if (pItem->m_bIsFolder)
708 strDeletePath=pItem->GetVideoInfoTag()->m_strPath;
710 strDeletePath=pItem->GetVideoInfoTag()->m_strFileNameAndPath;
712 if (URIUtils::GetFileName(strDeletePath).Equals("VIDEO_TS.IFO"))
714 URIUtils::GetDirectory(strDeletePath.Mid(0),strDeletePath);
715 if (strDeletePath.Right(9).Equals("VIDEO_TS/"))
717 URIUtils::RemoveSlashAtEnd(strDeletePath);
718 URIUtils::GetDirectory(strDeletePath.Mid(0),strDeletePath);
721 if (URIUtils::HasSlashAtEnd(strDeletePath))
722 pItem->m_bIsFolder=true;
724 if (g_guiSettings.GetBool("filelists.allowfiledeletion") &&
725 CUtil::SupportsFileOperations(strDeletePath))
727 pItem->SetPath(strDeletePath);
728 CGUIWindowVideoBase::OnDeleteItem(pItem);
732 CUtil::DeleteVideoDatabaseDirectoryCache();
735 bool CGUIWindowVideoNav::DeleteItem(CFileItem* pItem, bool bUnavailable /* = false */)
737 if (!pItem->HasVideoInfoTag() || !CanDelete(pItem->GetPath()))
740 VIDEODB_CONTENT_TYPE iType=VIDEODB_CONTENT_MOVIES;
741 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_strShowTitle.IsEmpty())
742 iType = VIDEODB_CONTENT_TVSHOWS;
743 if (pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iSeason > -1 && !pItem->m_bIsFolder)
744 iType = VIDEODB_CONTENT_EPISODES;
745 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_strArtist.IsEmpty())
746 iType = VIDEODB_CONTENT_MUSICVIDEOS;
748 // dont allow update while scanning
749 CGUIDialogVideoScan* pDialogScan = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
750 if (pDialogScan && pDialogScan->IsScanning())
752 CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0);
757 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
760 if (iType == VIDEODB_CONTENT_MOVIES)
761 pDialog->SetHeading(432);
762 if (iType == VIDEODB_CONTENT_EPISODES)
763 pDialog->SetHeading(20362);
764 if (iType == VIDEODB_CONTENT_TVSHOWS)
765 pDialog->SetHeading(20363);
766 if (iType == VIDEODB_CONTENT_MUSICVIDEOS)
767 pDialog->SetHeading(20392);
771 pDialog->SetLine(0, g_localizeStrings.Get(662));
772 pDialog->SetLine(1, g_localizeStrings.Get(663));
773 pDialog->SetLine(2, "");;
779 strLine.Format(g_localizeStrings.Get(433),pItem->GetLabel());
780 pDialog->SetLine(0, strLine);
781 pDialog->SetLine(1, "");
782 pDialog->SetLine(2, "");;
786 if (!pDialog->IsConfirmed())
790 CVideoDatabase database;
793 database.GetFilePathById(pItem->GetVideoInfoTag()->m_iDbId, path, iType);
796 if (iType == VIDEODB_CONTENT_MOVIES)
797 database.DeleteMovie(path);
798 if (iType == VIDEODB_CONTENT_EPISODES)
799 database.DeleteEpisode(path, pItem->GetVideoInfoTag()->m_iDbId);
800 if (iType == VIDEODB_CONTENT_TVSHOWS)
801 database.DeleteTvShow(path);
802 if (iType == VIDEODB_CONTENT_MUSICVIDEOS)
803 database.DeleteMusicVideo(path);
805 if (iType == VIDEODB_CONTENT_TVSHOWS)
806 database.SetPathHash(path,"");
809 CStdString strDirectory;
810 URIUtils::GetDirectory(path,strDirectory);
811 database.SetPathHash(strDirectory,"");
817 void CGUIWindowVideoNav::OnPrepareFileItems(CFileItemList &items)
819 CGUIWindowVideoBase::OnPrepareFileItems(items);
823 CVideoDatabaseDirectory dir;
824 dir.GetQueryParams(items.GetPath(),params);
825 if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS)
826 CGUIWindowMusicNav::SetupFanart(items);
828 NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
830 // now filter as necessary
831 bool filterWatched=false;
832 if (node == NODE_TYPE_EPISODES
833 || node == NODE_TYPE_SEASONS
834 || node == NODE_TYPE_TITLE_MOVIES
835 || node == NODE_TYPE_TITLE_TVSHOWS
836 || node == NODE_TYPE_TITLE_MUSICVIDEOS
837 || node == NODE_TYPE_RECENTLY_ADDED_EPISODES
838 || node == NODE_TYPE_RECENTLY_ADDED_MOVIES
839 || node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
840 filterWatched = true;
841 if (!items.IsVideoDb())
842 filterWatched = true;
843 if (items.IsSmartPlayList() && items.GetContent() == "tvshows")
844 node = NODE_TYPE_TITLE_TVSHOWS; // so that the check below works
846 int watchMode = g_settings.GetWatchMode(m_vecItems->GetContent());
848 for (int i = 0; i < items.Size(); i++)
850 CFileItemPtr item = items.Get(i);
851 if(item->HasVideoInfoTag() && (node == NODE_TYPE_TITLE_TVSHOWS || node == NODE_TYPE_SEASONS))
853 if (watchMode == VIDEO_SHOW_UNWATCHED)
854 item->GetVideoInfoTag()->m_iEpisode = (int)item->GetProperty("unwatchedepisodes").asInteger();
855 if (watchMode == VIDEO_SHOW_WATCHED)
856 item->GetVideoInfoTag()->m_iEpisode = (int)item->GetProperty("watchedepisodes").asInteger();
857 item->SetProperty("numepisodes", item->GetVideoInfoTag()->m_iEpisode);
862 if((watchMode==VIDEO_SHOW_WATCHED && item->GetVideoInfoTag()->m_playCount== 0)
863 || (watchMode==VIDEO_SHOW_UNWATCHED && item->GetVideoInfoTag()->m_playCount > 0))
872 void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &buttons)
875 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
876 item = m_vecItems->Get(itemNumber);
878 CGUIWindowVideoBase::GetContextButtons(itemNumber, buttons);
880 if (item && item->GetProperty("pluginreplacecontextitems").asBoolean())
883 CVideoDatabaseDirectory dir;
884 NODE_TYPE node = dir.GetDirectoryChildType(m_vecItems->GetPath());
888 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
889 if (pScanDlg && pScanDlg->IsScanning())
890 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
892 buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
894 else if (m_vecItems->GetPath().Equals("sources://video/"))
896 // get the usual shares
897 CGUIDialogContextMenu::GetContextButtons("video", item, buttons);
898 // add scan button somewhere here
899 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
900 if (pScanDlg && pScanDlg->IsScanning())
901 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); // Stop Scanning
902 if (!item->IsDVD() && item->GetPath() != "add" &&
903 (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser))
905 CVideoDatabase database;
907 ADDON::ScraperPtr info = database.GetScraperForPath(item->GetPath());
909 if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
911 if (!item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
913 if (info && info->Content() != CONTENT_NONE)
914 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
916 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
920 if (info && (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning())))
921 buttons.Add(CONTEXT_BUTTON_SCAN, 13349);
926 // are we in the playlists location?
927 bool inPlaylists = m_vecItems->GetPath().Equals(CUtil::VideoPlaylistsLocation()) ||
928 m_vecItems->GetPath().Equals("special://videoplaylists/");
930 if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_strArtist.IsEmpty())
932 CMusicDatabase database;
934 if (database.GetArtistByName(item->GetVideoInfoTag()->m_strArtist) > -1)
935 buttons.Add(CONTEXT_BUTTON_GO_TO_ARTIST, 20396);
937 if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_strAlbum.size() > 0)
939 CMusicDatabase database;
941 if (database.GetAlbumByName(item->GetVideoInfoTag()->m_strAlbum) > -1)
942 buttons.Add(CONTEXT_BUTTON_GO_TO_ALBUM, 20397);
944 if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_strAlbum.size() > 0 &&
945 item->GetVideoInfoTag()->m_strArtist.size() > 0 &&
946 item->GetVideoInfoTag()->m_strTitle.size() > 0)
948 CMusicDatabase database;
950 if (database.GetSongByArtistAndAlbumAndTitle(item->GetVideoInfoTag()->m_strArtist,
951 item->GetVideoInfoTag()->m_strAlbum,
952 item->GetVideoInfoTag()->m_strTitle) > -1)
954 buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 20398);
957 if (!item->IsParentFolder())
959 ADDON::ScraperPtr info;
960 VIDEO::SScanSettings settings;
961 GetScraperForItem(item.get(), info, settings);
963 if (info && info->Content() == CONTENT_TVSHOWS)
964 buttons.Add(CONTEXT_BUTTON_INFO, item->m_bIsFolder ? 20351 : 20352);
965 else if (info && info->Content() == CONTENT_MUSICVIDEOS)
966 buttons.Add(CONTEXT_BUTTON_INFO,20393);
967 else if (info && info->Content() == CONTENT_MOVIES)
968 buttons.Add(CONTEXT_BUTTON_INFO, 13346);
970 // can we update the database?
971 if (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser)
973 if (node == NODE_TYPE_TITLE_TVSHOWS)
975 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
976 if (pScanDlg && pScanDlg->IsScanning())
977 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
979 buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349);
981 if (!item->IsPlugin() && !item->IsScript() && !item->IsLiveTV() && !item->IsAddonsPath() &&
982 item->GetPath() != "sources://video/" && item->GetPath() != "special://videoplaylists/")
984 if (item->m_bIsFolder)
986 // Have both options for folders since we don't know whether all childs are watched/unwatched
987 buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
988 buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); //Mark as Watched
992 if (item->GetOverlayImage().Equals("OverlayWatched.png"))
993 buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
995 buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103); //Mark as Watched
998 if ((node == NODE_TYPE_TITLE_TVSHOWS) ||
999 (item->IsVideoDb() && item->HasVideoInfoTag() && !item->m_bIsFolder))
1001 buttons.Add(CONTEXT_BUTTON_EDIT, 16105); //Edit Title
1003 if (m_database.HasContent(VIDEODB_CONTENT_TVSHOWS) && item->HasVideoInfoTag() &&
1004 !item->m_bIsFolder && item->GetVideoInfoTag()->m_iEpisode == -1 &&
1005 item->GetVideoInfoTag()->m_strArtist.IsEmpty() && item->GetVideoInfoTag()->m_iDbId >= 0) // movie entry
1007 if (m_database.IsLinkedToTvshow(item->GetVideoInfoTag()->m_iDbId))
1008 buttons.Add(CONTEXT_BUTTON_UNLINK_MOVIE,20385);
1009 buttons.Add(CONTEXT_BUTTON_LINK_MOVIE,20384);
1012 if (node == NODE_TYPE_SEASONS && item->m_bIsFolder)
1013 buttons.Add(CONTEXT_BUTTON_SET_SEASON_THUMB, 20371);
1015 if (item->GetPath().Left(14).Equals("videodb://1/7/") && item->GetPath().size() > 14 && item->m_bIsFolder) // sets
1017 buttons.Add(CONTEXT_BUTTON_EDIT, 16105);
1018 buttons.Add(CONTEXT_BUTTON_SET_MOVIESET_THUMB, 20435);
1019 buttons.Add(CONTEXT_BUTTON_SET_MOVIESET_FANART, 20456);
1020 buttons.Add(CONTEXT_BUTTON_DELETE, 646);
1023 if (node == NODE_TYPE_ACTOR && !dir.IsAllItem(item->GetPath()) && item->m_bIsFolder)
1025 if (m_vecItems->GetPath().Left(11).Equals("videodb://3")) // mvids
1026 buttons.Add(CONTEXT_BUTTON_SET_ARTIST_THUMB, 13359);
1028 buttons.Add(CONTEXT_BUTTON_SET_ACTOR_THUMB, 20403);
1030 if (item->IsVideoDb() && item->HasVideoInfoTag() &&
1031 (!item->m_bIsFolder || node == NODE_TYPE_TITLE_TVSHOWS))
1033 if (info && info->Content() == CONTENT_TVSHOWS)
1035 if(item->GetVideoInfoTag()->m_iBookmarkId != -1 &&
1036 item->GetVideoInfoTag()->m_iBookmarkId != 0)
1038 buttons.Add(CONTEXT_BUTTON_UNLINK_BOOKMARK, 20405);
1041 buttons.Add(CONTEXT_BUTTON_DELETE, 646);
1044 // this should ideally be non-contextual (though we need some context for non-tv show node I guess)
1045 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1046 if (pScanDlg && pScanDlg->IsScanning())
1048 if (node != NODE_TYPE_TITLE_TVSHOWS)
1049 buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
1052 buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
1055 if (!m_vecItems->IsVideoDb() && !m_vecItems->IsVirtualDirectoryRoot())
1056 { // non-video db items, file operations are allowed
1057 if ((g_guiSettings.GetBool("filelists.allowfiledeletion") &&
1058 CUtil::SupportsFileOperations(item->GetPath())) ||
1059 (inPlaylists && !URIUtils::GetFileName(item->GetPath()).Equals("PartyMode-Video.xsp")
1060 && (item->IsPlayList() || item->IsSmartPlayList())))
1062 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
1063 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
1065 // add "Set/Change content" to folders
1066 if (item->m_bIsFolder && !item->IsPlayList() && !item->IsSmartPlayList() && !item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
1068 CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1069 if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
1071 if (info && info->Content() != CONTENT_NONE)
1072 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
1074 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
1078 if (item->IsPlugin() || item->IsScript() || m_vecItems->IsPlugin())
1079 buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
1082 CGUIWindowVideoBase::GetNonContextButtons(itemNumber, buttons);
1085 bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
1088 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
1089 item = m_vecItems->Get(itemNumber);
1090 if (CGUIDialogContextMenu::OnContextButton("video", item, button))
1092 //TODO should we search DB for entries from plugins?
1093 if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin()
1094 && !item->IsLiveTV() &&!item->IsRSS())
1096 OnUnAssignContent(item->GetPath(),20375,20340,20341);
1098 Update(m_vecItems->GetPath());
1103 case CONTEXT_BUTTON_EDIT:
1104 UpdateVideoTitle(item.get());
1105 CUtil::DeleteVideoDatabaseDirectoryCache();
1106 Update(m_vecItems->GetPath());
1109 case CONTEXT_BUTTON_SET_SEASON_THUMB:
1110 case CONTEXT_BUTTON_SET_ACTOR_THUMB:
1111 case CONTEXT_BUTTON_SET_ARTIST_THUMB:
1112 case CONTEXT_BUTTON_SET_MOVIESET_THUMB:
1114 // Grab the thumbnails from the web
1116 CFileItemList items;
1117 URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath,"imdbthumbs",strPath);
1118 CFileItemPtr cacheItem(new CFileItem(strPath,true));
1119 CFileUtils::DeleteItem(cacheItem,true);
1120 XFILE::CDirectory::Create(strPath);
1121 CFileItemPtr noneitem(new CFileItem("thumb://None", false));
1122 CStdString cachedThumb = m_vecItems->Get(itemNumber)->GetCachedSeasonThumb();
1123 if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB)
1124 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedActorThumb();
1125 if (button == CONTEXT_BUTTON_SET_ARTIST_THUMB)
1126 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedArtistThumb();
1127 if (button == CONTEXT_BUTTON_SET_MOVIESET_THUMB)
1128 cachedThumb = m_vecItems->Get(itemNumber)->GetCachedVideoThumb();
1129 if (CFile::Exists(cachedThumb))
1131 CFileItemPtr item(new CFileItem("thumb://Current", false));
1132 item->SetThumbnailImage(cachedThumb);
1133 item->SetLabel(g_localizeStrings.Get(20016));
1136 noneitem->SetIconImage("DefaultFolder.png");
1137 noneitem->SetLabel(g_localizeStrings.Get(20018));
1139 vector<CStdString> thumbs;
1140 if (button != CONTEXT_BUTTON_SET_ARTIST_THUMB)
1143 if (button == CONTEXT_BUTTON_SET_SEASON_THUMB)
1144 m_database.GetTvShowInfo("",tag,m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iDbId);
1146 tag = *m_vecItems->Get(itemNumber)->GetVideoInfoTag();
1147 if (button == CONTEXT_BUTTON_SET_SEASON_THUMB)
1148 tag.m_strPictureURL.GetThumbURLs(thumbs, m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iSeason);
1150 tag.m_strPictureURL.GetThumbURLs(thumbs);
1152 for (unsigned int i = 0; i < thumbs.size(); i++)
1154 CStdString strItemPath;
1155 strItemPath.Format("thumb://Remote%i",i);
1156 CFileItemPtr item(new CFileItem(strItemPath, false));
1157 item->SetThumbnailImage(thumbs[i]);
1158 item->SetIconImage("DefaultPicture.png");
1159 item->SetLabel(g_localizeStrings.Get(20015));
1162 // TODO: Do we need to clear the cached image?
1163 // CTextureCache::Get().ClearCachedImage(thumbs[i]);
1168 if (button == CONTEXT_BUTTON_SET_ARTIST_THUMB)
1170 CStdString picturePath;
1172 CStdString strPath = m_vecItems->Get(itemNumber)->GetPath();
1173 URIUtils::RemoveSlashAtEnd(strPath);
1175 int nPos=strPath.ReverseFind("/");
1178 // try to guess where the user should start
1179 // browsing for the artist thumb
1180 CMusicDatabase database;
1182 long idArtist=database.GetArtistByName(m_vecItems->Get(itemNumber)->GetLabel());
1183 database.GetArtistPath(idArtist, picturePath);
1186 CStdString strThumb;
1187 URIUtils::AddFileToFolder(picturePath,"folder.jpg",strThumb);
1188 if (XFILE::CFile::Exists(strThumb))
1190 CFileItemPtr pItem(new CFileItem(strThumb,false));
1191 pItem->SetLabel(g_localizeStrings.Get(20017));
1192 pItem->SetThumbnailImage(strThumb);
1197 noneitem->SetIconImage("DefaultArtist.png");
1200 if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB)
1202 CStdString picturePath;
1203 CStdString strThumb;
1204 URIUtils::AddFileToFolder(picturePath,"folder.jpg",strThumb);
1205 if (XFILE::CFile::Exists(strThumb))
1207 CFileItemPtr pItem(new CFileItem(strThumb,false));
1208 pItem->SetLabel(g_localizeStrings.Get(20017));
1209 pItem->SetThumbnailImage(strThumb);
1214 noneitem->SetIconImage("DefaultActor.png");
1217 if (button == CONTEXT_BUTTON_SET_MOVIESET_THUMB)
1218 noneitem->SetIconImage("DefaultVideo.png");
1221 items.Add(noneitem);
1223 VECSOURCES sources=g_settings.m_videoSources;
1224 g_mediaManager.GetLocalDrives(sources);
1226 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources,
1227 g_localizeStrings.Get(20019), result))
1229 return false; // user cancelled
1232 if (result == "thumb://Current")
1233 return false; // user chose the one they have
1235 // delete the thumbnail if that's what the user wants, else overwrite with the
1237 CTextureCache::Get().ClearCachedImage(cachedThumb, true);
1238 if (result.Left(14) == "thumb://Remote")
1240 int number = atoi(result.Mid(14));
1241 CFile::Cache(thumbs[number], cachedThumb);
1243 if (result == "thumb://None")
1244 CTextureCache::Get().ClearCachedImage(cachedThumb, true);
1246 CFile::Cache(result,cachedThumb);
1248 CUtil::DeleteVideoDatabaseDirectoryCache();
1249 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
1250 g_windowManager.SendMessage(msg);
1251 Update(m_vecItems->GetPath());
1255 case CONTEXT_BUTTON_SET_MOVIESET_FANART:
1257 CFileItemList items;
1258 CStdString cachedFanart(item->GetCachedFanart());
1260 if (CFile::Exists(cachedFanart))
1262 CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false));
1263 itemCurrent->SetThumbnailImage(cachedFanart);
1264 itemCurrent->SetLabel(g_localizeStrings.Get(20440));
1265 items.Add(itemCurrent);
1268 CStdString localFanart(item->GetLocalFanart());
1269 if (!localFanart.IsEmpty())
1271 CFileItemPtr itemLocal(new CFileItem("fanart://Local",false));
1272 itemLocal->SetThumbnailImage(localFanart);
1273 itemLocal->SetLabel(g_localizeStrings.Get(20438));
1274 CTextureCache::Get().ClearCachedImage(localFanart);
1275 items.Add(itemLocal);
1279 CFileItemPtr itemNone(new CFileItem("fanart://None", false));
1280 itemNone->SetIconImage("DefaultVideo.png");
1281 itemNone->SetLabel(g_localizeStrings.Get(20439));
1282 items.Add(itemNone);
1286 VECSOURCES sources(g_settings.m_videoSources);
1287 g_mediaManager.GetLocalDrives(sources);
1289 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || result.Equals("fanart://Current"))
1292 CTextureCache::Get().ClearCachedImage(cachedFanart, true);
1294 if (result.Equals("fanart://Local"))
1295 result = localFanart;
1297 if (CFile::Exists(result))
1300 CPicture::ConvertFile(result, cachedFanart,0,1920,-1,100,true);
1302 CPicture::CacheFanart(result, cachedFanart);
1305 // clear view cache and reload images
1306 CUtil::DeleteVideoDatabaseDirectoryCache();
1308 if (CFile::Exists(cachedFanart))
1309 item->SetProperty("fanart_image", cachedFanart);
1311 item->ClearProperty("fanart_image");
1313 Update(m_vecItems->GetPath());
1316 case CONTEXT_BUTTON_UPDATE_LIBRARY:
1321 case CONTEXT_BUTTON_UNLINK_MOVIE:
1323 OnLinkMovieToTvShow(itemNumber, true);
1324 Update(m_vecItems->GetPath());
1327 case CONTEXT_BUTTON_LINK_MOVIE:
1329 OnLinkMovieToTvShow(itemNumber, false);
1332 case CONTEXT_BUTTON_GO_TO_ARTIST:
1335 CMusicDatabase database;
1337 strPath.Format("musicdb://2/%ld/",database.GetArtistByName(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strArtist));
1338 g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath);
1341 case CONTEXT_BUTTON_GO_TO_ALBUM:
1344 CMusicDatabase database;
1346 strPath.Format("musicdb://3/%ld/",database.GetAlbumByName(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum));
1347 g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV,strPath);
1350 case CONTEXT_BUTTON_PLAY_OTHER:
1352 CMusicDatabase database;
1355 if (database.GetSongById(database.GetSongByArtistAndAlbumAndTitle(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strArtist,m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum,
1356 m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strTitle),
1359 g_application.getApplicationMessenger().PlayFile(song);
1364 case CONTEXT_BUTTON_UNLINK_BOOKMARK:
1367 m_database.DeleteBookMarkForEpisode(*m_vecItems->Get(itemNumber)->GetVideoInfoTag());
1369 CUtil::DeleteVideoDatabaseDirectoryCache();
1370 Update(m_vecItems->GetPath());
1378 return CGUIWindowVideoBase::OnContextButton(itemNumber, button);
1381 void CGUIWindowVideoNav::OnLinkMovieToTvShow(int itemnumber, bool bRemove)
1387 if (!m_database.GetLinksToTvShow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,ids))
1389 for (unsigned int i=0;i<ids.size();++i)
1392 m_database.GetTvShowInfo("",tag,ids[i]);
1393 CFileItemPtr show(new CFileItem(tag));
1399 m_database.GetTvShowsNav("videodb://2/2",list);
1401 // remove already linked shows
1403 if (!m_database.GetLinksToTvShow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,ids))
1405 for (int i=0;i<list.Size();)
1408 for (j=0;j<ids.size();++j)
1410 if (list[i]->GetVideoInfoTag()->m_iDbId == ids[j])
1413 if (j == ids.size())
1419 int iSelectedLabel = 0;
1420 if (list.Size() > 1)
1422 list.Sort(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SORT_ORDER_ASC);
1423 CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
1425 pDialog->SetItems(&list);
1426 pDialog->SetHeading(20356);
1428 iSelectedLabel = pDialog->GetSelectedLabel();
1430 if (iSelectedLabel > -1)
1432 m_database.LinkMovieToTvshow(m_vecItems->Get(itemnumber)->GetVideoInfoTag()->m_iDbId,
1433 list[iSelectedLabel]->GetVideoInfoTag()->m_iDbId, bRemove);
1434 CUtil::DeleteVideoDatabaseDirectoryCache();
1438 bool CGUIWindowVideoNav::OnClick(int iItem)
1440 CFileItemPtr item = m_vecItems->Get(iItem);
1441 if (!item->m_bIsFolder && item->IsVideoDb() && !item->Exists())
1443 if (!DeleteItem(item.get(), true))
1447 m_vecItems->RemoveDiscCache(GetID());
1448 Update(m_vecItems->GetPath());
1449 m_viewControl.SetSelectedItem(iItem);
1453 return CGUIWindowVideoBase::OnClick(iItem);
1456 CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir)
1458 if (dir.Equals("MovieGenres"))
1459 return "videodb://1/1/";
1460 else if (dir.Equals("MovieTitles"))
1461 return "videodb://1/2/";
1462 else if (dir.Equals("MovieYears"))
1463 return "videodb://1/3/";
1464 else if (dir.Equals("MovieActors"))
1465 return "videodb://1/4/";
1466 else if (dir.Equals("MovieDirectors"))
1467 return "videodb://1/5/";
1468 else if (dir.Equals("MovieStudios"))
1469 return "videodb://1/6/";
1470 else if (dir.Equals("MovieSets"))
1471 return "videodb://1/7/";
1472 else if (dir.Equals("MovieCountries"))
1473 return "videodb://1/8/";
1474 else if (dir.Equals("Movies"))
1475 return "videodb://1/";
1476 else if (dir.Equals("TvShowGenres"))
1477 return "videodb://2/1/";
1478 else if (dir.Equals("TvShowTitles"))
1479 return "videodb://2/2/";
1480 else if (dir.Equals("TvShowYears"))
1481 return "videodb://2/3/";
1482 else if (dir.Equals("TvShowActors"))
1483 return "videodb://2/4/";
1484 else if (dir.Equals("TvShowStudios"))
1485 return "videodb://2/5/";
1486 else if (dir.Equals("TvShows"))
1487 return "videodb://2/";
1488 else if (dir.Equals("MusicVideoGenres"))
1489 return "videodb://3/1/";
1490 else if (dir.Equals("MusicVideoTitles"))
1491 return "videodb://3/2/";
1492 else if (dir.Equals("MusicVideoYears"))
1493 return "videodb://3/3/";
1494 else if (dir.Equals("MusicVideoArtists"))
1495 return "videodb://3/4/";
1496 else if (dir.Equals("MusicVideoDirectors"))
1497 return "videodb://3/5/";
1498 else if (dir.Equals("MusicVideoStudios"))
1499 return "videodb://3/6/";
1500 else if (dir.Equals("MusicVideos"))
1501 return "videodb://3/";
1502 else if (dir.Equals("RecentlyAddedMovies"))
1503 return "videodb://4/";
1504 else if (dir.Equals("RecentlyAddedEpisodes"))
1505 return "videodb://5/";
1506 else if (dir.Equals("RecentlyAddedMusicVideos"))
1507 return "videodb://6/";
1508 else if (dir.Equals("Files"))
1509 return "sources://video/";
1510 return CGUIWindowVideoBase::GetStartFolder(dir);