adds a directory provider class
authorJonathan Marshall <jmarshall@xbmc.org>
Sun, 13 Oct 2013 08:28:51 +0000 (10:28 +0200)
committerJonathan Marshall <jmarshall@xbmc.org>
Mon, 11 Nov 2013 22:49:21 +0000 (11:49 +1300)
XBMC.xcodeproj/project.pbxproj
project/VS2010Express/XBMC.vcxproj
project/VS2010Express/XBMC.vcxproj.filters
xbmc/listproviders/DirectoryProvider.cpp [new file with mode: 0644]
xbmc/listproviders/DirectoryProvider.h [new file with mode: 0644]
xbmc/listproviders/IListProvider.cpp
xbmc/listproviders/Makefile

index 890f016..15f14ed 100644 (file)
                7C89674613C03B22003631FE /* InfoBool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89674313C03B22003631FE /* InfoBool.cpp */; };
                7C8A14571154CB2600E5FCFA /* TextureCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A14541154CB2600E5FCFA /* TextureCache.cpp */; };
                7C8A187D115B2A8200E5FCFA /* TextureDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A187A115B2A8200E5FCFA /* TextureDatabase.cpp */; };
+               7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
+               7C8FC6EF1829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
+               7C8FC6F01829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
                7C920CF9181669FF00DA1477 /* TextureOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C920CF7181669FF00DA1477 /* TextureOperations.cpp */; };
                7C920CFA181669FF00DA1477 /* TextureOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C920CF7181669FF00DA1477 /* TextureOperations.cpp */; };
                7C920CFB181669FF00DA1477 /* TextureOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C920CF7181669FF00DA1477 /* TextureOperations.cpp */; };
                7C8A14551154CB2600E5FCFA /* TextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCache.h; sourceTree = "<group>"; };
                7C8A187A115B2A8200E5FCFA /* TextureDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureDatabase.cpp; sourceTree = "<group>"; };
                7C8A187B115B2A8200E5FCFA /* TextureDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureDatabase.h; sourceTree = "<group>"; };
+               7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DirectoryProvider.cpp; path = xbmc/listproviders/DirectoryProvider.cpp; sourceTree = SOURCE_ROOT; };
+               7C8FC6ED1829A4580045153D /* DirectoryProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DirectoryProvider.h; path = xbmc/listproviders/DirectoryProvider.h; sourceTree = SOURCE_ROOT; };
                7C920CF7181669FF00DA1477 /* TextureOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureOperations.cpp; sourceTree = "<group>"; };
                7C920CF8181669FF00DA1477 /* TextureOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureOperations.h; sourceTree = "<group>"; };
                7C99B6A2133D342100FC2B16 /* CircularCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CircularCache.cpp; sourceTree = "<group>"; };
                7C430161175C41FE009B82E5 /* listproviders */ = {
                        isa = PBXGroup;
                        children = (
+                               7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */,
+                               7C8FC6ED1829A4580045153D /* DirectoryProvider.h */,
                                7C7BCDBF17727951004842FB /* IListProvider.cpp */,
                                7C7BCDC417727951004842FB /* IListProvider.h */,
                                7C7BCDC317727951004842FB /* StaticProvider.cpp */,
                                7C26126C182068660086E04D /* SettingsOperations.cpp in Sources */,
                                7C7BCDC517727951004842FB /* IListProvider.cpp in Sources */,
                                7C7BCDC717727951004842FB /* StaticProvider.cpp in Sources */,
+                               7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                7C26126E182068660086E04D /* SettingsOperations.cpp in Sources */,
                                7C7BCDCB17727951004842FB /* IListProvider.cpp in Sources */,
                                7C7BCDCD17727952004842FB /* StaticProvider.cpp in Sources */,
+                               7C8FC6F01829A4580045153D /* DirectoryProvider.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                7C26126D182068660086E04D /* SettingsOperations.cpp in Sources */,
                                7C7BCDC817727951004842FB /* IListProvider.cpp in Sources */,
                                7C7BCDCA17727951004842FB /* StaticProvider.cpp in Sources */,
+                               7C8FC6EF1829A4580045153D /* DirectoryProvider.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index e33d61f..6f6d7b1 100644 (file)
     <ClCompile Include="..\..\xbmc\interfaces\python\XBPython.cpp" />
     <ClCompile Include="..\..\xbmc\LangInfo.cpp" />
     <ClCompile Include="..\..\xbmc\listproviders\IListProvider.cpp" />
+    <ClCompile Include="..\..\xbmc\listproviders\DirectoryProvider.cpp" />
     <ClCompile Include="..\..\xbmc\listproviders\StaticProvider.cpp" />
     <ClCompile Include="..\..\xbmc\MediaSource.cpp" />
     <ClCompile Include="..\..\xbmc\music\Album.cpp" />
     <ClInclude Include="..\..\xbmc\IProgressCallback.h" />
     <ClInclude Include="..\..\xbmc\LangInfo.h" />
     <ClInclude Include="..\..\xbmc\listproviders\IListProvider.h" />
+    <ClInclude Include="..\..\xbmc\listproviders\DirectoryProvider.h" />
     <ClInclude Include="..\..\xbmc\listproviders\StaticProvider.h" />
     <ClInclude Include="..\..\xbmc\MediaSource.h" />
     <ClInclude Include="..\..\xbmc\music\Album.h" />
index 6cb6e4d..65b0c0f 100644 (file)
     <ClCompile Include="..\..\xbmc\listproviders\IListProvider.cpp">
       <Filter>listproviders</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\xbmc\listproviders\DirectoryProvider.cpp">
+      <Filter>listproviders</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\xbmc\listproviders\StaticProvider.cpp">
       <Filter>listproviders</Filter>
     </ClCompile>
     <ClInclude Include="..\..\xbmc\listproviders\IListProvider.h">
       <Filter>listproviders</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\xbmc\listproviders\DirectoryProvider.h">
+      <Filter>listproviders</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\xbmc\listproviders\StaticProvider.h">
       <Filter>listproviders</Filter>
     </ClInclude>
diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp
new file mode 100644 (file)
index 0000000..ea51b9e
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://www.xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "DirectoryProvider.h"
+#include "filesystem/Directory.h"
+#include "filesystem/FavouritesDirectory.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/JobManager.h"
+#include "utils/StringUtils.h"
+#include "utils/TimeUtils.h"
+#include "utils/XMLUtils.h"
+#include "threads/SingleLock.h"
+#include "ApplicationMessenger.h"
+#include "FileItem.h"
+
+using namespace std;
+using namespace XFILE;
+
+class CDirectoryJob : public CJob
+{
+public:
+  CDirectoryJob(const std::string &url, int parentID) : m_url(url), m_parentID(parentID) { };
+  virtual ~CDirectoryJob() {};
+
+  virtual const char* GetType() const { return "directory"; };
+  virtual bool operator==(const CJob *job) const
+  {
+    if (strcmp(job->GetType(),GetType()) == 0)
+    {
+      const CDirectoryJob* dirJob = dynamic_cast<const CDirectoryJob*>(job);
+      if (dirJob && dirJob->m_url == m_url)
+        return true;
+    }
+    return false;
+  }
+
+  virtual bool DoWork()
+  {
+    CFileItemList items;
+    if (CDirectory::GetDirectory(m_url, items, ""))
+    {
+      // convert to CGUIStaticItem's and set visibility and targets
+      m_items.reserve(items.Size());
+      for (int i = 0; i < items.Size(); i++)
+      {
+        CGUIStaticItemPtr item(new CGUIStaticItem(*items[i]));
+        if (item->HasProperty("node.visible"))
+          item->SetVisibleCondition(item->GetProperty("node.visible").asString(), m_parentID);
+        m_items.push_back(item);
+      }
+      m_target = items.GetProperty("node.target").asString();
+    }
+    return true;    
+  }
+
+  const std::vector<CGUIStaticItemPtr> &GetItems() const { return m_items; }
+  const std::string &GetTarget() const { return m_target; }
+private:
+  std::string m_url;
+  std::string m_target;
+  int m_parentID;
+  std::vector<CGUIStaticItemPtr> m_items;
+};
+
+CDirectoryProvider::CDirectoryProvider(const TiXmlElement *element, int parentID)
+ : IListProvider(parentID),
+   m_updateTime(0),
+   m_invalid(false),
+   m_jobID(0)
+{
+  assert(element);
+
+  if (!element->NoChildren())
+  {
+    const char *target = element->Attribute("target");
+    if (target)
+      m_target.SetLabel(target, "", parentID);
+    m_url.SetLabel(element->FirstChild()->ValueStr(), "", parentID);
+  }
+}
+
+CDirectoryProvider::~CDirectoryProvider()
+{
+  Reset();
+}
+
+bool CDirectoryProvider::Update(bool refresh)
+{
+  bool changed = refresh;
+  {
+    CSingleLock lock(m_section);
+    changed |= m_invalid;
+    m_invalid = false;
+  }
+
+  // update the URL and fire off a new job if needed
+  CStdString value(m_url.GetLabel(m_parentID, false));
+  if (value != m_currentUrl)
+  {
+    m_currentUrl = value;
+
+    // fire job
+    CSingleLock lock(m_section);
+    if (m_jobID)
+      CJobManager::GetInstance().CancelJob(m_jobID);
+    m_jobID = CJobManager::GetInstance().AddJob(new CDirectoryJob(m_currentUrl, m_parentID), this);
+  }
+
+  for (vector<CGUIStaticItemPtr>::iterator i = m_items.begin(); i != m_items.end(); ++i)
+    changed |= (*i)->UpdateVisibility(m_parentID);
+  return changed; // TODO: Also returned changed if properties are changed (if so, need to update scroll to letter).
+}
+
+void CDirectoryProvider::Fetch(vector<CGUIListItemPtr> &items) const
+{
+  CSingleLock lock(m_section);
+  items.clear();
+  for (vector<CGUIStaticItemPtr>::const_iterator i = m_items.begin(); i != m_items.end(); ++i)
+  {
+    if ((*i)->IsVisible())
+      items.push_back(*i);
+  }
+}
+
+void CDirectoryProvider::Reset()
+{
+  // cancel any pending jobs
+  CSingleLock lock(m_section);
+  if (m_jobID)
+    CJobManager::GetInstance().CancelJob(m_jobID);
+  m_jobID = 0;
+  m_items.clear();
+  m_currentTarget.clear();
+  m_currentUrl.clear();
+  m_invalid = false;
+}
+
+void CDirectoryProvider::OnJobComplete(unsigned int jobID, bool success, CJob *job)
+{
+  CSingleLock lock(m_section);
+  if (success)
+  {
+    m_items = ((CDirectoryJob*)job)->GetItems();
+    m_currentTarget = ((CDirectoryJob*)job)->GetTarget();
+    m_invalid = true;
+  }
+  m_jobID = 0;
+}
+
+bool CDirectoryProvider::OnClick(const CGUIListItemPtr &item)
+{
+  CFileItem fileItem(*boost::static_pointer_cast<CFileItem>(item));
+  string target = fileItem.GetProperty("node.target").asString();
+  if (target.empty())
+    target = m_currentTarget;
+  if (target.empty())
+    target = m_target.GetLabel(m_parentID, false);
+  if (fileItem.HasProperty("node.target_url"))
+    fileItem.SetPath(fileItem.GetProperty("node.target_url").asString());
+  // grab the execute string
+  string execute = CFavouritesDirectory::GetExecutePath(fileItem, target);
+  if (!execute.empty())
+  {
+    CGUIMessage message(GUI_MSG_EXECUTE, 0, 0);
+    message.SetStringParam(execute);
+    g_windowManager.SendMessage(message);
+    return true;
+  }
+  return false;
+}
diff --git a/xbmc/listproviders/DirectoryProvider.h b/xbmc/listproviders/DirectoryProvider.h
new file mode 100644 (file)
index 0000000..f398130
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://www.xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <string>
+#include "IListProvider.h"
+#include "guilib/GUIStaticItem.h"
+#include "utils/Job.h"
+#include "threads/CriticalSection.h"
+
+class TiXmlElement;
+
+class CDirectoryProvider : public IListProvider, public IJobCallback
+{
+public:
+  CDirectoryProvider(const TiXmlElement *element, int parentID);
+  virtual ~CDirectoryProvider();
+
+  virtual bool Update(bool refresh);
+  virtual void Fetch(std::vector<CGUIListItemPtr> &items) const;
+  virtual void Reset();
+  virtual bool OnClick(const CGUIListItemPtr &item);
+
+  // callback from directory job
+  virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job);
+private:
+  unsigned int     m_updateTime;
+  bool             m_invalid;
+  unsigned int     m_jobID;
+  CGUIInfoLabel    m_url;
+  CGUIInfoLabel    m_target;
+  std::string      m_currentUrl;
+  std::string      m_currentTarget;   ///< \brief node.target property on the list as a whole
+  std::vector<CGUIStaticItemPtr> m_items;
+  CCriticalSection m_section;
+};
index 5b890be..16a11a9 100644 (file)
@@ -21,6 +21,7 @@
 #include "IListProvider.h"
 #include "utils/XBMCTinyXML.h"
 #include "StaticProvider.h"
+#include "DirectoryProvider.h"
 
 IListProvider *IListProvider::Create(const TiXmlNode *node, int parentID)
 {
@@ -30,6 +31,9 @@ IListProvider *IListProvider::Create(const TiXmlNode *node, int parentID)
     const TiXmlElement *item = root->FirstChildElement("item");
     if (item)
       return new CStaticListProvider(root, parentID);
+
+    if (!root->NoChildren())
+      return new CDirectoryProvider(root, parentID);
   }
   return NULL;
 }
index 81b5f64..f0f66a2 100644 (file)
@@ -1,4 +1,5 @@
-SRCS  = IListProvider.cpp
+SRCS  = DirectoryProvider.cpp
+SRCS += IListProvider.cpp
 SRCS += StaticProvider.cpp
      
 LIB=listproviders.a