Merge branch 'single_query_playcounts'
[vuplus_xbmc] / xbmc / video / windows / GUIWindowVideoNav.cpp
index 83d8ca5..971ff01 100644 (file)
@@ -21,7 +21,6 @@
 
 #include "GUIUserMessages.h"
 #include "GUIWindowVideoNav.h"
-#include "GUIWindowVideoFiles.h"
 #include "music/windows/GUIWindowMusicNav.h"
 #include "utils/FileUtils.h"
 #include "Util.h"
@@ -76,8 +75,6 @@ using namespace std;
 CGUIWindowVideoNav::CGUIWindowVideoNav(void)
     : CGUIWindowVideoBase(WINDOW_VIDEO_NAV, "MyVideoNav.xml")
 {
-  m_vecItems->m_strPath = "?";
-  m_bDisplayEmptyDatabaseMessage = false;
   m_thumbLoader.SetObserver(this);
 }
 
@@ -105,7 +102,7 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message)
   switch (message.GetMessage())
   {
   case GUI_MSG_WINDOW_RESET:
-    m_vecItems->m_strPath = "?";
+    m_vecItems->m_strPath.clear();
     break;
   case GUI_MSG_WINDOW_DEINIT:
     if (m_thumbLoader.IsLoading())
@@ -116,12 +113,6 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message)
       /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */
       m_rootDir.AllowNonLocalSources(false);
 
-      // is this the first time the window is opened?
-      if (m_vecItems->m_strPath == "?" && message.GetStringParam().IsEmpty())
-        message.SetStringParam(g_settings.m_defaultVideoLibSource);
-
-      DisplayEmptyDatabaseMessage(false); // reset message state
-
       SetProperty("flattened", g_settings.m_bMyVideoNavFlatten);
       
       if (!CGUIWindowVideoBase::OnMessage(message))
@@ -129,12 +120,9 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message)
 
       //  base class has opened the database, do our check
       m_database.Open();
-      DisplayEmptyDatabaseMessage(!m_database.HasContent());
 
-      if (m_bDisplayEmptyDatabaseMessage)
-      {
-        // no library - make sure we focus on a known control, and default to the root.
-        SET_CONTROL_FOCUS(CONTROL_BTNTYPE, 0);
+      if (!m_database.HasContent() && m_vecItems->IsVideoDb())
+      { // no library - make sure we default to the root.
         m_vecItems->m_strPath = "";
         SetHistoryForPath("");
         Update("");
@@ -263,6 +251,8 @@ CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const
     return "RecentlyAddedMusicVideos";
   else if (strPath.Equals("special://videoplaylists/"))
     return "Playlists";
+  else if (strPath.Equals("sources://video/"))
+    return "Files";
   else
   {
     CLog::Log(LOGERROR, "  CGUIWindowVideoNav::GetQuickpathName: Unknown parameter (%s)", strPath.c_str());
@@ -281,9 +271,6 @@ void CGUIWindowVideoNav::OnItemLoaded(CFileItem* pItem)
 
 bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items)
 {
-  if (m_bDisplayEmptyDatabaseMessage)
-    return true;
-
   CFileItem directory(strDirectory, true);
 
   if (m_thumbLoader.IsLoading())
@@ -407,11 +394,83 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL
       else
         items.SetContent("");
     }
+    else
+    { // load info from the database
+      CStdString label;
+      if (items.GetLabel().IsEmpty() && m_rootDir.IsSource(items.m_strPath, g_settings.GetSourcesFromType("video"), &label)) 
+        items.SetLabel(label);
+      LoadVideoInfo(items);
+    }
   }
-
   return bResult;
 }
 
+void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items)
+{
+  // TODO: this could possibly be threaded as per the music info loading,
+  //       we could also cache the info
+  if (!items.GetContent().IsEmpty())
+    return; // don't load for listings that have content set
+
+  CStdString content = m_database.GetContentForPath(items.m_strPath);
+  items.SetContent(content.IsEmpty() ? "files" : content);
+
+  bool clean = (g_guiSettings.GetBool("myvideos.cleanstrings") &&
+                !items.IsVirtualDirectoryRoot() &&
+                m_stackingAvailable);
+
+  CFileItemList dbItems;
+  if (content.IsEmpty())
+    m_database.GetPlayCounts(items);
+  else
+  {
+    m_database.GetItemsForPath(content, items.m_strPath, dbItems);
+    dbItems.SetFastLookup(true);
+  }
+  for (int i = 0; i < items.Size(); i++)
+  {
+    CFileItemPtr pItem = items[i];
+    CFileItemPtr match;
+    if (!content.IsEmpty())
+      match = dbItems.Get(pItem->m_strPath);
+    if (match)
+    {
+      CStdString label (pItem->GetLabel ());
+      CStdString label2(pItem->GetLabel2());
+      pItem->UpdateInfo(*match);
+
+      if(g_settings.m_videoStacking && m_stackingAvailable)
+      {
+        if (match->m_bIsFolder)
+          pItem->m_strPath = match->GetVideoInfoTag()->m_strPath;
+        else
+          pItem->m_strPath = match->GetVideoInfoTag()->m_strFileNameAndPath;
+        // if we switch from a file to a folder item it means we really shouldn't be sorting files and
+        // folders separately
+        if (pItem->m_bIsFolder != match->m_bIsFolder)
+          items.SetSortIgnoreFolders(true);
+        pItem->m_bIsFolder = match->m_bIsFolder;
+      }
+      else
+      {
+        if (CFile::Exists(match->GetCachedFanart()))
+          pItem->SetProperty("fanart_image", match->GetCachedFanart());
+        pItem->SetLabel (label);
+        pItem->SetLabel2(label);
+      }
+    }
+    else
+    { // set the watched overlay (note: items in a folder with content set that aren't in the db
+      //                                won't get picked up here - in the future all items will be returned)
+      // and clean the label
+      if (pItem->HasVideoInfoTag())
+        pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pItem->GetVideoInfoTag()->m_playCount > 0);
+      if (clean)
+        pItem->CleanString();
+    }
+  }
+}
+
 void CGUIWindowVideoNav::UpdateButtons()
 {
   CGUIWindowVideoBase::UpdateButtons();
@@ -450,12 +509,16 @@ void CGUIWindowVideoNav::UpdateButtons()
     CStdString strDummy;
     URIUtils::Split(m_vecItems->m_strPath, strDummy, strLabel);
   }
+  else if (m_vecItems->m_strPath.Equals("sources://video/"))
+    strLabel = g_localizeStrings.Get(744);
   // everything else is from a videodb:// path
-  else
+  else if (m_vecItems->IsVideoDb())
   {
     CVideoDatabaseDirectory dir;
     dir.GetLabel(m_vecItems->m_strPath, strLabel);
   }
+  else
+    strLabel = URIUtils::GetFileName(m_vecItems->m_strPath);
 
   SET_CONTROL_LABEL(CONTROL_FILTER, strLabel);
 
@@ -548,20 +611,6 @@ void CGUIWindowVideoNav::PlayItem(int iItem)
   CGUIWindowVideoBase::PlayItem(iItem);
 }
 
-void CGUIWindowVideoNav::DisplayEmptyDatabaseMessage(bool bDisplay)
-{
-  m_bDisplayEmptyDatabaseMessage = bDisplay;
-}
-
-void CGUIWindowVideoNav::FrameMove()
-{
-  if (m_bDisplayEmptyDatabaseMessage)
-    SET_CONTROL_LABEL(CONTROL_LABELEMPTY,g_localizeStrings.Get(745)+'\n'+g_localizeStrings.Get(746));
-  else
-    SET_CONTROL_LABEL(CONTROL_LABELEMPTY,"");
-  CGUIWindowVideoBase::FrameMove();
-}
-
 void CGUIWindowVideoNav::OnInfo(CFileItem* pItem, ADDON::ScraperPtr& scraper)
 {
   m_database.Open(); // since we can be called from the music library without being inited
@@ -597,9 +646,11 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
   if (m_vecItems->IsParentFolder())
     return;
 
-  if (m_vecItems->m_strPath.Equals("special://videoplaylists/"))
+  if (!m_vecItems->IsVideoDb())
   {
-    if (!pItem->m_strPath.Equals("newsmartplaylist://video"))
+    if (!pItem->m_strPath.Equals("newsmartplaylist://video") &&
+        !pItem->m_strPath.Equals("special://videoplaylists/") &&
+        !pItem->m_strPath.Equals("sources://video/"))
       CGUIWindowVideoBase::OnDeleteItem(pItem);
   }
   else if (pItem->m_strPath.Left(14).Equals("videodb://1/7/") &&
@@ -657,7 +708,6 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
   }
 
   CUtil::DeleteVideoDatabaseDirectoryCache();
-  DisplayEmptyDatabaseMessage(!m_database.HasContent());
 }
 
 bool CGUIWindowVideoNav::DeleteItem(CFileItem* pItem, bool bUnavailable /* = false */)
@@ -766,14 +816,10 @@ void CGUIWindowVideoNav::OnPrepareFileItems(CFileItemList &items)
   ||  node == NODE_TYPE_RECENTLY_ADDED_MOVIES
   ||  node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
     filterWatched = true;
-  if (items.IsPlugin())
-    filterWatched = true;
-  if (items.IsSmartPlayList())
-  {
-    if (items.GetContent() == "tvshows")
-      node = NODE_TYPE_TITLE_TVSHOWS; // so that the check below works
+  if (!items.IsVideoDb())
     filterWatched = true;
-  }
+  if (items.IsSmartPlayList() && items.GetContent() == "tvshows")
+    node = NODE_TYPE_TITLE_TVSHOWS; // so that the check below works
 
   int watchMode = g_settings.GetWatchMode(m_vecItems->GetContent());
 
@@ -823,6 +869,36 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
     else
       buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
   }
+  else if (m_vecItems->m_strPath.Equals("sources://video/"))
+  {
+    // get the usual shares
+    CGUIDialogContextMenu::GetContextButtons("video", item, buttons);
+    // add scan button somewhere here
+    CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
+    if (pScanDlg && pScanDlg->IsScanning())
+      buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);  // Stop Scanning
+    if (!item->IsDVD() && item->m_strPath != "add" &&
+        (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser))
+    {
+      CVideoDatabase database;
+      database.Open();
+      ADDON::ScraperPtr info = database.GetScraperForPath(item->m_strPath);
+
+      if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
+      {
+        if (!item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
+        {
+          if (info && info->Content() != CONTENT_NONE)
+            buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
+          else
+            buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
+        }
+      }
+
+      if (info && (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning())))
+        buttons.Add(CONTEXT_BUTTON_SCAN, 13349);
+    }
+  }
   else
   {
     ADDON::ScraperPtr info;
@@ -876,19 +952,31 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
           else
             buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349);
         }
-        if ((info && info->Content() == CONTENT_TVSHOWS && item->m_bIsFolder) ||
-            (item->IsVideoDb() && item->HasVideoInfoTag() && !item->m_bIsFolder))
+        if (!item->IsPlugin() && !item->IsLiveTV() && !item->IsAddonsPath() &&
+             item->m_strPath != "sources://video/" && item->m_strPath != "special://videoplaylists/")
         {
-          if (item->m_bIsFolder || item->GetVideoInfoTag()->m_playCount > 0)
+          if (item->m_bIsFolder)
+          {
+            // Have both options for folders since we don't know whether all childs are watched/unwatched
             buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
-          if (item->m_bIsFolder || item->GetVideoInfoTag()->m_playCount == 0)
             buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103);   //Mark as Watched
-          if (node != NODE_TYPE_SEASONS)
-            buttons.Add(CONTEXT_BUTTON_EDIT, 16105); //Edit Title
+          }
+          else
+          {
+            if (item->GetOverlayImage().Equals("OverlayWatched.png"))
+              buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
+            else
+              buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103);   //Mark as Watched
+          }
+        }
+        if ((node == NODE_TYPE_TITLE_TVSHOWS) ||
+            (item->IsVideoDb() && item->HasVideoInfoTag() && !item->m_bIsFolder))
+        {
+          buttons.Add(CONTEXT_BUTTON_EDIT, 16105); //Edit Title
         }
         if (m_database.HasContent(VIDEODB_CONTENT_TVSHOWS) && item->HasVideoInfoTag() &&
            !item->m_bIsFolder && item->GetVideoInfoTag()->m_iEpisode == -1 &&
-            item->GetVideoInfoTag()->m_strArtist.IsEmpty()) // movie entry
+            item->GetVideoInfoTag()->m_strArtist.IsEmpty() && item->GetVideoInfoTag()->m_iDbId >= 0) // movie entry
         {
           if (m_database.IsLinkedToTvshow(item->GetVideoInfoTag()->m_iDbId))
             buttons.Add(CONTEXT_BUTTON_UNLINK_MOVIE,20385);
@@ -937,39 +1025,26 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
           buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653);
       }
 
-      //Set default and/or clear default
-      NODE_TYPE nodetype = CVideoDatabaseDirectory::GetDirectoryType(item->m_strPath);
-      if (!item->IsParentFolder() && !m_vecItems->m_strPath.Equals("special://videoplaylists/") &&
-        (nodetype == NODE_TYPE_ROOT             ||
-         nodetype == NODE_TYPE_OVERVIEW         ||
-         nodetype == NODE_TYPE_TVSHOWS_OVERVIEW ||
-         nodetype == NODE_TYPE_MOVIES_OVERVIEW  ||
-         nodetype == NODE_TYPE_MUSICVIDEOS_OVERVIEW))
-      {
-        if (!item->m_strPath.Equals(g_settings.m_defaultVideoLibSource))
-          buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default
-        if (strcmp(g_settings.m_defaultVideoLibSource, ""))
-          buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default
-      }
-
-      if ((CVideoDatabaseDirectory::GetDirectoryChildType(item->m_strPath) == NODE_TYPE_TITLE_MOVIES ||
-           CVideoDatabaseDirectory::GetDirectoryChildType(item->m_strPath) == NODE_TYPE_TITLE_MUSICVIDEOS ||
-           item->m_strPath.Equals("videodb://1/") ||
-           item->m_strPath.Equals("videodb://4/") ||
-           item->m_strPath.Equals("videodb://6/")) &&
-           nodetype != NODE_TYPE_RECENTLY_ADDED_MOVIES)
-      {
-        buttons.Add(CONTEXT_BUTTON_MARK_WATCHED, 16103);   //Mark as Watched
-        buttons.Add(CONTEXT_BUTTON_MARK_UNWATCHED, 16104); //Mark as UnWatched
-      }
-
-      if (m_vecItems->m_strPath.Equals("special://videoplaylists/"))
-      { // video playlists, file operations are allowed
-        if (!item->IsReadOnly())
+      if (!m_vecItems->IsVideoDb() && !m_vecItems->IsVirtualDirectoryRoot())
+      { // non-video db items, file operations are allowed
+        if (g_guiSettings.GetBool("filelists.allowfiledeletion") &&
+            CUtil::SupportsFileOperations(item->m_strPath))
         {
           buttons.Add(CONTEXT_BUTTON_DELETE, 117);
           buttons.Add(CONTEXT_BUTTON_RENAME, 118);
         }
+        // add "Set/Change content" to folders
+        if (item->m_bIsFolder && !item->IsPlayList() && !item->IsSmartPlayList() && !item->IsLiveTV() && !item->IsPlugin() && !item->IsAddonsPath())
+        {
+          CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
+          if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
+          {
+            if (info && info->Content() != CONTENT_NONE)
+              buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442);
+            else
+              buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
+          }
+        }
       }
       if (item->IsPlugin() || item->m_strPath.Left(9).Equals("script://") || m_vecItems->IsPlugin())
         buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
@@ -983,18 +1058,19 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
   CFileItemPtr item;
   if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
     item = m_vecItems->Get(itemNumber);
-  switch (button)
+  if (CGUIDialogContextMenu::OnContextButton("video", item, button))
   {
-  case CONTEXT_BUTTON_SET_DEFAULT:
-    g_settings.m_defaultVideoLibSource = GetQuickpathName(item->m_strPath);
-    g_settings.Save();
-    return true;
-
-  case CONTEXT_BUTTON_CLEAR_DEFAULT:
-    g_settings.m_defaultVideoLibSource.Empty();
-    g_settings.Save();
+    //TODO should we search DB for entries from plugins?
+    if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin()
+        && !item->IsLiveTV() &&!item->IsRSS())
+    {
+      OnUnAssignContent(item->m_strPath,20375,20340,20341);
+    }
+    Update(m_vecItems->m_strPath);
     return true;
-
+  }
+  switch (button)
+  {
   case CONTEXT_BUTTON_EDIT:
     UpdateVideoTitle(item.get());
     CUtil::DeleteVideoDatabaseDirectoryCache();
@@ -1339,5 +1415,7 @@ CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir)
     return "videodb://5/";
   else if (dir.Equals("RecentlyAddedMusicVideos"))
     return "videodb://6/";
+  else if (dir.Equals("Files"))
+    return "sources://video/";
   return CGUIWindowVideoBase::GetStartFolder(dir);
 }