/* * 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;iGetLabel()) && 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;iSize();++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 &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;iGetWindowManager().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 &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;iGetPath()); 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;iGetPath()); } 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); }