summaryrefslogtreecommitdiffstats
path: root/xbmc/dialogs/GUIDialogFileBrowser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/dialogs/GUIDialogFileBrowser.cpp')
-rw-r--r--xbmc/dialogs/GUIDialogFileBrowser.cpp1020
1 files changed, 1020 insertions, 0 deletions
diff --git a/xbmc/dialogs/GUIDialogFileBrowser.cpp b/xbmc/dialogs/GUIDialogFileBrowser.cpp
new file mode 100644
index 0000000..a9f81cb
--- /dev/null
+++ b/xbmc/dialogs/GUIDialogFileBrowser.cpp
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUIDialogFileBrowser.h"
+
+#include "AutoSwitch.h"
+#include "FileItem.h"
+#include "GUIDialogContextMenu.h"
+#include "GUIDialogMediaSource.h"
+#include "GUIDialogYesNo.h"
+#include "GUIPassword.h"
+#include "GUIUserMessages.h"
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "Util.h"
+#include "filesystem/Directory.h"
+#include "filesystem/File.h"
+#include "filesystem/MultiPathDirectory.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIKeyboardFactory.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "input/Key.h"
+#include "messaging/helpers/DialogOKHelper.h"
+#include "network/GUIDialogNetworkSetup.h"
+#include "network/Network.h"
+#include "profiles/ProfileManager.h"
+#include "settings/MediaSourceSettings.h"
+#include "settings/SettingsComponent.h"
+#include "storage/MediaManager.h"
+#include "utils/FileExtensionProvider.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+using namespace KODI::MESSAGING;
+using namespace XFILE;
+
+#define CONTROL_LIST 450
+#define CONTROL_THUMBS 451
+#define CONTROL_HEADING_LABEL 411
+#define CONTROL_LABEL_PATH 412
+#define CONTROL_OK 413
+#define CONTROL_CANCEL 414
+#define CONTROL_NEWFOLDER 415
+#define CONTROL_FLIP 416
+
+CGUIDialogFileBrowser::CGUIDialogFileBrowser()
+ : CGUIDialog(WINDOW_DIALOG_FILE_BROWSER, "FileBrowser.xml")
+{
+ m_Directory = new CFileItem;
+ m_vecItems = new CFileItemList;
+ m_bConfirmed = false;
+ m_Directory->m_bIsFolder = true;
+ m_browsingForFolders = 0;
+ m_browsingForImages = false;
+ m_useFileDirectories = false;
+ m_addNetworkShareEnabled = false;
+ m_singleList = false;
+ m_thumbLoader.SetObserver(this);
+ m_flipEnabled = false;
+ m_bFlip = false;
+ m_multipleSelection = false;
+ m_loadType = KEEP_IN_MEMORY;
+}
+
+CGUIDialogFileBrowser::~CGUIDialogFileBrowser()
+{
+ delete m_Directory;
+ delete m_vecItems;
+}
+
+bool CGUIDialogFileBrowser::OnAction(const CAction &action)
+{
+ if (action.GetID() == ACTION_PARENT_DIR)
+ {
+ GoParentFolder();
+ return true;
+ }
+ if ((action.GetID() == ACTION_CONTEXT_MENU || action.GetID() == ACTION_MOUSE_RIGHT_CLICK) && m_Directory->GetPath().empty())
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+ if ((!m_addSourceType.empty() && iItem != m_vecItems->Size()-1))
+ return OnPopupMenu(iItem);
+ if (m_addNetworkShareEnabled && CServiceBroker::GetMediaManager().HasLocation(m_selectedPath))
+ {
+ // need to make sure this source is not an auto added location
+ // as users locations might have the same paths
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ for (unsigned int i=0;i<m_shares.size();++i)
+ {
+ if (StringUtils::EqualsNoCase(m_shares[i].strName, pItem->GetLabel()) && m_shares[i].m_ignore)
+ return false;
+ }
+
+ return OnPopupMenu(iItem);
+ }
+
+ return false;
+ }
+
+ return CGUIDialog::OnAction(action);
+}
+
+bool CGUIDialogFileBrowser::OnBack(int actionID)
+{
+ if (actionID == ACTION_NAV_BACK && !m_vecItems->IsVirtualDirectoryRoot())
+ {
+ GoParentFolder();
+ return true;
+ }
+ return CGUIDialog::OnBack(actionID);
+}
+
+bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message)
+{
+ switch ( message.GetMessage() )
+ {
+ case GUI_MSG_WINDOW_DEINIT:
+ {
+ if (m_thumbLoader.IsLoading())
+ m_thumbLoader.StopThread();
+ CGUIDialog::OnMessage(message);
+ ClearFileItems();
+ m_addNetworkShareEnabled = false;
+ return true;
+ }
+ break;
+
+ case GUI_MSG_WINDOW_INIT:
+ {
+ m_bConfirmed = false;
+ m_bFlip = false;
+ bool bIsDir = false;
+ // this code allows two different selection modes for directories
+ // end the path with a slash to start inside the directory
+ if (URIUtils::HasSlashAtEnd(m_selectedPath))
+ {
+ bIsDir = true;
+ bool bFool;
+ int iSource = CUtil::GetMatchingSource(m_selectedPath,m_shares,bFool);
+ bFool = true;
+ if (iSource > -1 && iSource < (int)m_shares.size())
+ {
+ if (URIUtils::PathEquals(m_shares[iSource].strPath, m_selectedPath))
+ bFool = false;
+ }
+
+ if (bFool && !CDirectory::Exists(m_selectedPath))
+ m_selectedPath.clear();
+ }
+ else
+ {
+ if (!CFile::Exists(m_selectedPath) && !CDirectory::Exists(m_selectedPath))
+ m_selectedPath.clear();
+ }
+
+ // find the parent folder if we are a file browser (don't do this for folders)
+ m_Directory->SetPath(m_selectedPath);
+ if (!m_browsingForFolders && !bIsDir)
+ m_Directory->SetPath(URIUtils::GetParentPath(m_selectedPath));
+ Update(m_Directory->GetPath());
+ m_viewControl.SetSelectedItem(m_selectedPath);
+ return CGUIDialog::OnMessage(message);
+ }
+ break;
+
+ case GUI_MSG_CLICKED:
+ {
+ if (m_viewControl.HasControl(message.GetSenderId())) // list control
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+ int iAction = message.GetParam1();
+ if (iItem < 0) break;
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ if ((iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK) &&
+ (!m_multipleSelection || pItem->m_bIsShareOrDrive || pItem->m_bIsFolder))
+ {
+ OnClick(iItem);
+ return true;
+ }
+ else if ((iAction == ACTION_HIGHLIGHT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK || iAction == ACTION_SELECT_ITEM) &&
+ (m_multipleSelection && !pItem->m_bIsShareOrDrive && !pItem->m_bIsFolder))
+ {
+ pItem->Select(!pItem->IsSelected());
+ CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), message.GetSenderId(), iItem + 1);
+ OnMessage(msg);
+ }
+ }
+ else if (message.GetSenderId() == CONTROL_OK)
+ {
+ if (m_browsingForFolders == 2)
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+
+ std::string strPath;
+ if (iItem == 0)
+ strPath = m_selectedPath;
+ else
+ strPath = (*m_vecItems)[iItem]->GetPath();
+
+ std::string strTest = URIUtils::AddFileToFolder(strPath, "1");
+ CFile file;
+ if (file.OpenForWrite(strTest,true))
+ {
+ file.Close();
+ CFile::Delete(strTest);
+ m_bConfirmed = true;
+ Close();
+ }
+ else
+ HELPERS::ShowOKDialogText(CVariant{257}, CVariant{20072});
+ }
+ else
+ {
+ if (m_multipleSelection)
+ {
+ for (int iItem = 0; iItem < m_vecItems->Size(); ++iItem)
+ {
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ if (pItem->IsSelected())
+ m_markedPath.push_back(pItem->GetPath());
+ }
+ }
+ m_bConfirmed = true;
+ Close();
+ }
+ return true;
+ }
+ else if (message.GetSenderId() == CONTROL_CANCEL)
+ {
+ Close();
+ return true;
+ }
+ else if (message.GetSenderId() == CONTROL_NEWFOLDER)
+ {
+ std::string strInput;
+ if (CGUIKeyboardFactory::ShowAndGetInput(strInput, CVariant{g_localizeStrings.Get(119)}, false))
+ {
+ std::string strPath = URIUtils::AddFileToFolder(m_vecItems->GetPath(), strInput);
+ if (CDirectory::Create(strPath))
+ Update(m_vecItems->GetPath());
+ else
+ HELPERS::ShowOKDialogText(CVariant{20069}, CVariant{20072});
+ }
+ }
+ else if (message.GetSenderId() == CONTROL_FLIP)
+ m_bFlip = !m_bFlip;
+ }
+ break;
+ case GUI_MSG_SETFOCUS:
+ {
+ if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId())
+ {
+ m_viewControl.SetFocused();
+ return true;
+ }
+ }
+ break;
+ case GUI_MSG_NOTIFY_ALL:
+ { // Message is received only if this window is active
+ if (message.GetParam1() == GUI_MSG_REMOVED_MEDIA)
+ {
+ if (m_Directory->IsVirtualDirectoryRoot() && IsActive())
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+ Update(m_Directory->GetPath());
+ m_viewControl.SetSelectedItem(iItem);
+ }
+ else if (m_Directory->IsRemovable())
+ { // check that we have this removable share still
+ if (!m_rootDir.IsInSource(m_Directory->GetPath()))
+ { // don't have this share any more
+ if (IsActive()) Update("");
+ else
+ {
+ m_history.ClearPathHistory();
+ m_Directory->SetPath("");
+ }
+ }
+ }
+ return true;
+ }
+ else if (message.GetParam1()==GUI_MSG_UPDATE_SOURCES)
+ { // State of the sources changed, so update our view
+ if (m_Directory->IsVirtualDirectoryRoot() && IsActive())
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+ Update(m_Directory->GetPath());
+ m_viewControl.SetSelectedItem(iItem);
+ }
+ return true;
+ }
+ else if (message.GetParam1()==GUI_MSG_UPDATE_PATH)
+ {
+ if (IsActive())
+ {
+ if((message.GetStringParam() == m_Directory->GetPath()) ||
+ (m_Directory->IsMultiPath() && XFILE::CMultiPathDirectory::HasPath(m_Directory->GetPath(), message.GetStringParam())))
+ {
+ int iItem = m_viewControl.GetSelectedItem();
+ Update(m_Directory->GetPath());
+ m_viewControl.SetSelectedItem(iItem);
+ }
+ }
+ }
+ }
+ break;
+
+ }
+ return CGUIDialog::OnMessage(message);
+}
+
+void CGUIDialogFileBrowser::ClearFileItems()
+{
+ m_viewControl.Clear();
+ m_vecItems->Clear(); // will clean up everything
+}
+
+void CGUIDialogFileBrowser::OnSort()
+{
+ if (!m_singleList)
+ m_vecItems->Sort(SortByLabel, SortOrderAscending);
+}
+
+void CGUIDialogFileBrowser::Update(const std::string &strDirectory)
+{
+ const CURL pathToUrl(strDirectory);
+
+ if (m_browsingForImages && m_thumbLoader.IsLoading())
+ m_thumbLoader.StopThread();
+ // get selected item
+ int iItem = m_viewControl.GetSelectedItem();
+ std::string strSelectedItem;
+ if (iItem >= 0 && iItem < m_vecItems->Size())
+ {
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ if (!pItem->IsParentFolder())
+ {
+ strSelectedItem = pItem->GetPath();
+ URIUtils::RemoveSlashAtEnd(strSelectedItem);
+ m_history.SetSelectedItem(strSelectedItem, m_Directory->GetPath().empty()?"empty":m_Directory->GetPath());
+ }
+ }
+
+ if (!m_singleList)
+ {
+ CFileItemList items;
+ std::string strParentPath;
+
+ if (!m_rootDir.GetDirectory(pathToUrl, items, m_useFileDirectories, false))
+ {
+ CLog::Log(LOGERROR, "CGUIDialogFileBrowser::GetDirectory({}) failed",
+ pathToUrl.GetRedacted());
+
+ // We assume, we can get the parent
+ // directory again
+ std::string strParentPath = m_history.GetParentPath();
+ m_history.RemoveParentPath();
+ Update(strParentPath);
+ return;
+ }
+
+ // check if current directory is a root share
+ if (!m_rootDir.IsSource(strDirectory))
+ {
+ if (URIUtils::GetParentPath(strDirectory, strParentPath))
+ {
+ CFileItemPtr pItem(new CFileItem(".."));
+ pItem->SetPath(strParentPath);
+ pItem->m_bIsFolder = true;
+ pItem->m_bIsShareOrDrive = false;
+ items.AddFront(pItem, 0);
+ }
+ }
+ else
+ {
+ // yes, this is the root of a share
+ // add parent path to the virtual directory
+ CFileItemPtr pItem(new CFileItem(".."));
+ pItem->SetPath("");
+ pItem->m_bIsShareOrDrive = false;
+ pItem->m_bIsFolder = true;
+ items.AddFront(pItem, 0);
+ strParentPath = "";
+ }
+
+ ClearFileItems();
+ m_vecItems->Copy(items);
+ m_Directory->SetPath(strDirectory);
+ m_strParentPath = strParentPath;
+ }
+
+ // if we're getting the root source listing
+ // make sure the path history is clean
+ if (strDirectory.empty())
+ m_history.ClearPathHistory();
+
+ // some evil stuff don't work with the '/' mask, e.g. shoutcast directory - make sure no files are in there
+ if (m_browsingForFolders)
+ {
+ for (int i=0;i<m_vecItems->Size();++i)
+ if (!(*m_vecItems)[i]->m_bIsFolder)
+ {
+ m_vecItems->Remove(i);
+ i--;
+ }
+ }
+
+ // No need to set thumbs
+
+ m_vecItems->FillInDefaultIcons();
+
+ OnSort();
+
+ if (m_Directory->GetPath().empty() && m_addNetworkShareEnabled &&
+ (CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE ||
+ CServiceBroker::GetSettingsComponent()->GetProfileManager()->IsMasterProfile() || g_passwordManager.bMasterUser))
+ { // we are in the virtual directory - add the "Add Network Location" item
+ CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(1032)));
+ pItem->SetPath("net://");
+ pItem->m_bIsFolder = true;
+ m_vecItems->Add(pItem);
+ }
+ if (m_Directory->GetPath().empty() && !m_addSourceType.empty())
+ {
+ CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(21359)));
+ pItem->SetPath("source://");
+ pItem->m_bIsFolder = true;
+ m_vecItems->Add(pItem);
+ }
+
+ m_viewControl.SetItems(*m_vecItems);
+ m_viewControl.SetCurrentView((m_browsingForImages && CAutoSwitch::ByFileCount(*m_vecItems)) ? CONTROL_THUMBS : CONTROL_LIST);
+
+ std::string strPath2 = m_Directory->GetPath();
+ URIUtils::RemoveSlashAtEnd(strPath2);
+ strSelectedItem = m_history.GetSelectedItem(strPath2==""?"empty":strPath2);
+
+ bool bSelectedFound = false;
+ for (int i = 0; i < m_vecItems->Size(); ++i)
+ {
+ CFileItemPtr pItem = (*m_vecItems)[i];
+ strPath2 = pItem->GetPath();
+ URIUtils::RemoveSlashAtEnd(strPath2);
+ if (strPath2 == strSelectedItem)
+ {
+ m_viewControl.SetSelectedItem(i);
+ bSelectedFound = true;
+ break;
+ }
+ }
+
+ // if we haven't found the selected item, select the first item
+ if (!bSelectedFound)
+ m_viewControl.SetSelectedItem(0);
+
+ m_history.AddPath(m_Directory->GetPath());
+
+ if (m_browsingForImages)
+ m_thumbLoader.Load(*m_vecItems);
+}
+
+void CGUIDialogFileBrowser::FrameMove()
+{
+ int item = m_viewControl.GetSelectedItem();
+ if (item >= 0)
+ {
+ // if we are browsing for folders, and not in the root directory, then we use the parent path,
+ // else we use the current file's path
+ if (m_browsingForFolders && !m_Directory->IsVirtualDirectoryRoot())
+ m_selectedPath = m_Directory->GetPath();
+ else
+ m_selectedPath = (*m_vecItems)[item]->GetPath();
+ if (m_selectedPath == "net://")
+ {
+ SET_CONTROL_LABEL(CONTROL_LABEL_PATH, g_localizeStrings.Get(1032)); // "Add Network Location..."
+ }
+ else
+ {
+ // Update the current path label
+ CURL url(m_selectedPath);
+ std::string safePath = url.GetWithoutUserDetails();
+ SET_CONTROL_LABEL(CONTROL_LABEL_PATH, safePath);
+ }
+ if ((!m_browsingForFolders && (*m_vecItems)[item]->m_bIsFolder) || ((*m_vecItems)[item]->GetPath() == "image://Browse"))
+ {
+ CONTROL_DISABLE(CONTROL_OK);
+ }
+ else
+ {
+ CONTROL_ENABLE(CONTROL_OK);
+ }
+ if (m_browsingForFolders == 2)
+ {
+ CONTROL_ENABLE(CONTROL_NEWFOLDER);
+ }
+ else
+ {
+ CONTROL_DISABLE(CONTROL_NEWFOLDER);
+ }
+ if (m_flipEnabled)
+ {
+ CONTROL_ENABLE(CONTROL_FLIP);
+ }
+ else
+ {
+ CONTROL_DISABLE(CONTROL_FLIP);
+ }
+ }
+ CGUIDialog::FrameMove();
+}
+
+void CGUIDialogFileBrowser::OnClick(int iItem)
+{
+ if ( iItem < 0 || iItem >= m_vecItems->Size() ) return ;
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ std::string strPath = pItem->GetPath();
+
+ if (pItem->m_bIsFolder)
+ {
+ if (pItem->GetPath() == "net://")
+ { // special "Add Network Location" item
+ OnAddNetworkLocation();
+ return;
+ }
+ if (pItem->GetPath() == "source://")
+ { // special "Add Source" item
+ OnAddMediaSource();
+ return;
+ }
+ if (!m_addSourceType.empty())
+ {
+ OnEditMediaSource(pItem.get());
+ return;
+ }
+ if ( pItem->m_bIsShareOrDrive )
+ {
+ if ( !HaveDiscOrConnection( pItem->m_iDriveType ) )
+ return ;
+ }
+ Update(strPath);
+ }
+ else if (!m_browsingForFolders)
+ {
+ m_selectedPath = pItem->GetPath();
+ m_bConfirmed = true;
+ Close();
+ }
+}
+
+bool CGUIDialogFileBrowser::HaveDiscOrConnection( int iDriveType )
+{
+ if ( iDriveType == CMediaSource::SOURCE_TYPE_DVD )
+ {
+ if (!CServiceBroker::GetMediaManager().IsDiscInDrive())
+ {
+ HELPERS::ShowOKDialogText(CVariant{218}, CVariant{219});
+ return false;
+ }
+ }
+ else if ( iDriveType == CMediaSource::SOURCE_TYPE_REMOTE )
+ {
+ //! @todo Handle not connected to a remote share
+ if ( !CServiceBroker::GetNetwork().IsConnected() )
+ {
+ HELPERS::ShowOKDialogText(CVariant{220}, CVariant{221});
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void CGUIDialogFileBrowser::GoParentFolder()
+{
+ std::string strPath(m_strParentPath);
+ if (strPath.size() == 2)
+ if (strPath[1] == ':')
+ URIUtils::AddSlashAtEnd(strPath);
+ Update(strPath);
+}
+
+void CGUIDialogFileBrowser::OnWindowLoaded()
+{
+ CGUIDialog::OnWindowLoaded();
+ m_viewControl.Reset();
+ m_viewControl.SetParentWindow(GetID());
+ m_viewControl.AddView(GetControl(CONTROL_LIST));
+ m_viewControl.AddView(GetControl(CONTROL_THUMBS));
+}
+
+void CGUIDialogFileBrowser::OnWindowUnload()
+{
+ CGUIDialog::OnWindowUnload();
+ m_viewControl.Reset();
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetImage(const CFileItemList &items, const VECSOURCES &shares, const std::string &heading, std::string &result, bool* flip, int label)
+{
+ CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
+ if (!browser)
+ return false;
+ CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
+
+ browser->m_browsingForImages = true;
+ browser->m_singleList = true;
+ browser->m_vecItems->Clear();
+ browser->m_vecItems->Append(items);
+ if (true)
+ {
+ CFileItemPtr item(new CFileItem("image://Browse", false));
+ item->SetLabel(g_localizeStrings.Get(20153));
+ item->SetArt("icon", "DefaultFolder.png");
+ browser->m_vecItems->Add(item);
+ }
+ browser->SetHeading(heading);
+ browser->m_flipEnabled = flip?true:false;
+ browser->Open();
+ bool confirmed(browser->IsConfirmed());
+ if (confirmed)
+ {
+ result = browser->m_selectedPath;
+ if (result == "image://Browse")
+ { // "Browse for thumb"
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ return ShowAndGetImage(shares, g_localizeStrings.Get(label), result);
+ }
+ }
+
+ if (flip)
+ *flip = browser->m_bFlip != 0;
+
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+
+ return confirmed;
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetImage(const VECSOURCES &shares, const std::string &heading, std::string &path)
+{
+ return ShowAndGetFile(shares, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), heading, path, true); // true for use thumbs
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetImageList(const VECSOURCES &shares, const std::string &heading, std::vector<std::string> &path)
+{
+ return ShowAndGetFileList(shares, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), heading, path, true); // true for use thumbs
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetDirectory(const VECSOURCES &shares, const std::string &heading, std::string &path, bool bWriteOnly)
+{
+ // an extension mask of "/" ensures that no files are shown
+ if (bWriteOnly)
+ {
+ VECSOURCES shareWritable;
+ for (unsigned int i=0;i<shares.size();++i)
+ {
+ if (shares[i].IsWritable())
+ shareWritable.push_back(shares[i]);
+ }
+
+ return ShowAndGetFile(shareWritable, "/w", heading, path);
+ }
+
+ return ShowAndGetFile(shares, "/", heading, path);
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetFile(const VECSOURCES &shares, const std::string &mask, const std::string &heading, std::string &path, bool useThumbs /* = false */, bool useFileDirectories /* = false */)
+{
+ CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
+ if (!browser)
+ return false;
+ CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
+
+ browser->m_useFileDirectories = useFileDirectories;
+
+ browser->m_browsingForImages = useThumbs;
+ browser->SetHeading(heading);
+ browser->SetSources(shares);
+ std::string strMask = mask;
+ if (mask == "/")
+ browser->m_browsingForFolders=1;
+ else
+ if (mask == "/w")
+ {
+ browser->m_browsingForFolders=2;
+ strMask = "/";
+ }
+ else
+ browser->m_browsingForFolders = 0;
+
+ browser->m_rootDir.SetMask(strMask);
+ browser->m_selectedPath = path;
+ browser->m_addNetworkShareEnabled = false;
+ browser->Open();
+ bool confirmed(browser->IsConfirmed());
+ if (confirmed)
+ path = browser->m_selectedPath;
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ return confirmed;
+}
+
+// same as above, starting in a single directory
+bool CGUIDialogFileBrowser::ShowAndGetFile(const std::string &directory, const std::string &mask, const std::string &heading, std::string &path, bool useThumbs /* = false */, bool useFileDirectories /* = false */, bool singleList /* = false */)
+{
+ CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
+ if (!browser)
+ return false;
+ CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
+
+ browser->m_useFileDirectories = useFileDirectories;
+ browser->m_browsingForImages = useThumbs;
+ browser->SetHeading(heading);
+
+ // add a single share for this directory
+ if (!singleList)
+ {
+ VECSOURCES shares;
+ CMediaSource share;
+ share.strPath = directory;
+ URIUtils::RemoveSlashAtEnd(share.strPath); // this is needed for the dodgy code in WINDOW_INIT
+ shares.push_back(share);
+ browser->SetSources(shares);
+ }
+ else
+ {
+ browser->m_vecItems->Clear();
+ CDirectory::GetDirectory(directory,*browser->m_vecItems, "", DIR_FLAG_DEFAULTS);
+ CFileItemPtr item(new CFileItem("file://Browse", false));
+ item->SetLabel(g_localizeStrings.Get(20153));
+ item->SetArt("icon", "DefaultFolder.png");
+ browser->m_vecItems->Add(item);
+ browser->m_singleList = true;
+ }
+ std::string strMask = mask;
+ if (mask == "/")
+ browser->m_browsingForFolders=1;
+ else
+ if (mask == "/w")
+ {
+ browser->m_browsingForFolders=2;
+ strMask = "/";
+ }
+ else
+ browser->m_browsingForFolders = 0;
+
+ browser->m_rootDir.SetMask(strMask);
+ browser->m_selectedPath = directory;
+ browser->m_addNetworkShareEnabled = false;
+ browser->Open();
+ bool confirmed(browser->IsConfirmed());
+ if (confirmed)
+ path = browser->m_selectedPath;
+ if (path == "file://Browse")
+ { // "Browse for thumb"
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ VECSOURCES shares;
+ CServiceBroker::GetMediaManager().GetLocalDrives(shares);
+
+ return ShowAndGetFile(shares, mask, heading, path, useThumbs,useFileDirectories);
+ }
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ return confirmed;
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetFileList(const VECSOURCES &shares, const std::string &mask, const std::string &heading, std::vector<std::string> &path, bool useThumbs /* = false */, bool useFileDirectories /* = false */)
+{
+ CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
+ if (!browser)
+ return false;
+ CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
+
+ browser->m_useFileDirectories = useFileDirectories;
+ browser->m_multipleSelection = true;
+ browser->m_browsingForImages = useThumbs;
+ browser->SetHeading(heading);
+ browser->SetSources(shares);
+ browser->m_browsingForFolders = 0;
+ browser->m_rootDir.SetMask(mask);
+ browser->m_addNetworkShareEnabled = false;
+ browser->Open();
+ bool confirmed(browser->IsConfirmed());
+ if (confirmed)
+ {
+ if (browser->m_markedPath.size())
+ path = browser->m_markedPath;
+ else
+ path.push_back(browser->m_selectedPath);
+ }
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ return confirmed;
+}
+
+void CGUIDialogFileBrowser::SetHeading(const std::string &heading)
+{
+ Initialize();
+ SET_CONTROL_LABEL(CONTROL_HEADING_LABEL, heading);
+}
+
+bool CGUIDialogFileBrowser::ShowAndGetSource(std::string &path, bool allowNetworkShares, VECSOURCES* additionalShare /* = NULL */, const std::string& strType /* = "" */)
+{
+ // Technique is
+ // 1. Show Filebrowser with currently defined local, and optionally the network locations.
+ // 2. Have the "Add Network Location" option in addition.
+ // 3a. If the "Add Network Location" is pressed, then:
+ // a) Fire up the network location dialog to grab the new location
+ // b) Check the location by doing a GetDirectory() - if it fails, prompt the user
+ // to allow them to add currently disconnected network shares.
+ // c) Save this location to our xml file (network.xml)
+ // d) Return to 1.
+ // 3b. If the "Add Source" is pressed, then:
+ // a) Fire up the media source dialog to add the new location
+ // 4. Optionally allow user to browse the local and network locations for their share.
+ // 5. On OK, return.
+
+ // Create a new filebrowser window
+ CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
+ if (!browser) return false;
+
+ // Add it to our window manager
+ CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
+
+ VECSOURCES shares;
+ if (!strType.empty())
+ {
+ if (additionalShare)
+ shares = *additionalShare;
+ browser->m_addSourceType = strType;
+ }
+ else
+ {
+ browser->SetHeading(g_localizeStrings.Get(1023));
+
+ CServiceBroker::GetMediaManager().GetLocalDrives(shares);
+
+ // Now the additional share if appropriate
+ if (additionalShare)
+ {
+ shares.insert(shares.end(),additionalShare->begin(),additionalShare->end());
+ }
+
+ // Now add the network shares...
+ if (allowNetworkShares)
+ {
+ CServiceBroker::GetMediaManager().GetNetworkLocations(shares);
+ }
+ }
+
+ browser->SetSources(shares);
+ browser->m_rootDir.SetMask("/");
+ browser->m_rootDir.AllowNonLocalSources(false); // don't allow plug n play shares
+ browser->m_browsingForFolders = 1;
+ browser->m_addNetworkShareEnabled = allowNetworkShares;
+ browser->m_selectedPath = "";
+ browser->Open();
+ bool confirmed = browser->IsConfirmed();
+ if (confirmed)
+ path = browser->m_selectedPath;
+
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
+ delete browser;
+ return confirmed;
+}
+
+void CGUIDialogFileBrowser::SetSources(const VECSOURCES &shares)
+{
+ m_shares = shares;
+ if (!m_shares.size() && m_addSourceType.empty())
+ CServiceBroker::GetMediaManager().GetLocalDrives(m_shares);
+ m_rootDir.SetSources(m_shares);
+}
+
+void CGUIDialogFileBrowser::OnAddNetworkLocation()
+{
+ // ok, fire up the network location dialog
+ std::string path;
+ if (CGUIDialogNetworkSetup::ShowAndGetNetworkAddress(path))
+ {
+ // verify the path by doing a GetDirectory.
+ CFileItemList items;
+ if (CDirectory::GetDirectory(path, items, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_ALLOW_PROMPT) || CGUIDialogYesNo::ShowAndGetInput(CVariant{1001}, CVariant{1002}))
+ { // add the network location to the shares list
+ CMediaSource share;
+ share.strPath = path; //setPath(path);
+ CURL url(path);
+ share.strName = url.GetWithoutUserDetails();
+ URIUtils::RemoveSlashAtEnd(share.strName);
+ m_shares.push_back(share);
+ // add to our location manager...
+ CServiceBroker::GetMediaManager().AddNetworkLocation(path);
+ }
+ }
+ m_rootDir.SetSources(m_shares);
+ Update(m_vecItems->GetPath());
+}
+
+void CGUIDialogFileBrowser::OnAddMediaSource()
+{
+ if (CGUIDialogMediaSource::ShowAndAddMediaSource(m_addSourceType))
+ {
+ SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
+ Update("");
+ }
+}
+
+void CGUIDialogFileBrowser::OnEditMediaSource(CFileItem* pItem)
+{
+ if (CGUIDialogMediaSource::ShowAndEditMediaSource(m_addSourceType,pItem->GetLabel()))
+ {
+ SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
+ Update("");
+ }
+}
+
+bool CGUIDialogFileBrowser::OnPopupMenu(int iItem)
+{
+ CContextButtons choices;
+ choices.Add(1, m_addSourceType.empty() ? 20133 : 21364);
+ choices.Add(2, m_addSourceType.empty() ? 20134 : 21365);
+
+ int btnid = CGUIDialogContextMenu::ShowAndGetChoice(choices);
+ if (btnid == 1)
+ {
+ if (m_addNetworkShareEnabled)
+ {
+ std::string strOldPath=m_selectedPath,newPath=m_selectedPath;
+ VECSOURCES shares=m_shares;
+ if (CGUIDialogNetworkSetup::ShowAndGetNetworkAddress(newPath))
+ {
+ CServiceBroker::GetMediaManager().SetLocationPath(strOldPath, newPath);
+ CURL url(newPath);
+ for (unsigned int i=0;i<shares.size();++i)
+ {
+ if (URIUtils::CompareWithoutSlashAtEnd(shares[i].strPath, strOldPath))//getPath().Equals(strOldPath))
+ {
+ shares[i].strName = url.GetWithoutUserDetails();
+ shares[i].strPath = newPath;
+ URIUtils::RemoveSlashAtEnd(shares[i].strName);
+ break;
+ }
+ }
+ // refresh dialog content
+ SetSources(shares);
+ m_rootDir.SetMask("/");
+ m_browsingForFolders = 1;
+ m_addNetworkShareEnabled = true;
+ m_selectedPath = url.GetWithoutUserDetails();
+ Update(m_Directory->GetPath());
+ m_viewControl.SetSelectedItem(iItem);
+ }
+ }
+ else
+ {
+ CFileItemPtr item = m_vecItems->Get(iItem);
+ OnEditMediaSource(item.get());
+ }
+ }
+ if (btnid == 2)
+ {
+ if (m_addNetworkShareEnabled)
+ {
+ CServiceBroker::GetMediaManager().RemoveLocation(m_selectedPath);
+
+ for (unsigned int i=0;i<m_shares.size();++i)
+ {
+ if (URIUtils::CompareWithoutSlashAtEnd(m_shares[i].strPath, m_selectedPath) && !m_shares[i].m_ignore) // getPath().Equals(m_selectedPath))
+ {
+ m_shares.erase(m_shares.begin()+i);
+ break;
+ }
+ }
+ m_rootDir.SetSources(m_shares);
+ m_rootDir.SetMask("/");
+
+ m_browsingForFolders = 1;
+ m_addNetworkShareEnabled = true;
+ m_selectedPath = "";
+
+ Update(m_Directory->GetPath());
+ }
+ else
+ {
+ CMediaSourceSettings::GetInstance().DeleteSource(m_addSourceType,(*m_vecItems)[iItem]->GetLabel(),(*m_vecItems)[iItem]->GetPath());
+ SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
+ Update("");
+ }
+ }
+
+ return true;
+}
+
+CFileItemPtr CGUIDialogFileBrowser::GetCurrentListItem(int offset)
+{
+ int item = m_viewControl.GetSelectedItem();
+ if (item < 0 || !m_vecItems->Size()) return CFileItemPtr();
+
+ item = (item + offset) % m_vecItems->Size();
+ if (item < 0) item += m_vecItems->Size();
+ return (*m_vecItems)[item];
+}
+
+CGUIControl *CGUIDialogFileBrowser::GetFirstFocusableControl(int id)
+{
+ if (m_viewControl.HasControl(id))
+ id = m_viewControl.GetCurrentControl();
+ return CGUIWindow::GetFirstFocusableControl(id);
+}
+
+