Merge pull request #22816 from CastagnaIT/fix_tx3g
[xbmc.git] / xbmc / dialogs / GUIDialogFileBrowser.cpp
bloba9f81cbb34f0d612d82e4dc6a9ebb1e637f2cd2e
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUIDialogFileBrowser.h"
11 #include "AutoSwitch.h"
12 #include "FileItem.h"
13 #include "GUIDialogContextMenu.h"
14 #include "GUIDialogMediaSource.h"
15 #include "GUIDialogYesNo.h"
16 #include "GUIPassword.h"
17 #include "GUIUserMessages.h"
18 #include "ServiceBroker.h"
19 #include "URL.h"
20 #include "Util.h"
21 #include "filesystem/Directory.h"
22 #include "filesystem/File.h"
23 #include "filesystem/MultiPathDirectory.h"
24 #include "guilib/GUIComponent.h"
25 #include "guilib/GUIKeyboardFactory.h"
26 #include "guilib/GUIWindowManager.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "input/Key.h"
29 #include "messaging/helpers/DialogOKHelper.h"
30 #include "network/GUIDialogNetworkSetup.h"
31 #include "network/Network.h"
32 #include "profiles/ProfileManager.h"
33 #include "settings/MediaSourceSettings.h"
34 #include "settings/SettingsComponent.h"
35 #include "storage/MediaManager.h"
36 #include "utils/FileExtensionProvider.h"
37 #include "utils/StringUtils.h"
38 #include "utils/URIUtils.h"
39 #include "utils/Variant.h"
40 #include "utils/log.h"
42 using namespace KODI::MESSAGING;
43 using namespace XFILE;
45 #define CONTROL_LIST 450
46 #define CONTROL_THUMBS 451
47 #define CONTROL_HEADING_LABEL 411
48 #define CONTROL_LABEL_PATH 412
49 #define CONTROL_OK 413
50 #define CONTROL_CANCEL 414
51 #define CONTROL_NEWFOLDER 415
52 #define CONTROL_FLIP 416
54 CGUIDialogFileBrowser::CGUIDialogFileBrowser()
55 : CGUIDialog(WINDOW_DIALOG_FILE_BROWSER, "FileBrowser.xml")
57 m_Directory = new CFileItem;
58 m_vecItems = new CFileItemList;
59 m_bConfirmed = false;
60 m_Directory->m_bIsFolder = true;
61 m_browsingForFolders = 0;
62 m_browsingForImages = false;
63 m_useFileDirectories = false;
64 m_addNetworkShareEnabled = false;
65 m_singleList = false;
66 m_thumbLoader.SetObserver(this);
67 m_flipEnabled = false;
68 m_bFlip = false;
69 m_multipleSelection = false;
70 m_loadType = KEEP_IN_MEMORY;
73 CGUIDialogFileBrowser::~CGUIDialogFileBrowser()
75 delete m_Directory;
76 delete m_vecItems;
79 bool CGUIDialogFileBrowser::OnAction(const CAction &action)
81 if (action.GetID() == ACTION_PARENT_DIR)
83 GoParentFolder();
84 return true;
86 if ((action.GetID() == ACTION_CONTEXT_MENU || action.GetID() == ACTION_MOUSE_RIGHT_CLICK) && m_Directory->GetPath().empty())
88 int iItem = m_viewControl.GetSelectedItem();
89 if ((!m_addSourceType.empty() && iItem != m_vecItems->Size()-1))
90 return OnPopupMenu(iItem);
91 if (m_addNetworkShareEnabled && CServiceBroker::GetMediaManager().HasLocation(m_selectedPath))
93 // need to make sure this source is not an auto added location
94 // as users locations might have the same paths
95 CFileItemPtr pItem = (*m_vecItems)[iItem];
96 for (unsigned int i=0;i<m_shares.size();++i)
98 if (StringUtils::EqualsNoCase(m_shares[i].strName, pItem->GetLabel()) && m_shares[i].m_ignore)
99 return false;
102 return OnPopupMenu(iItem);
105 return false;
108 return CGUIDialog::OnAction(action);
111 bool CGUIDialogFileBrowser::OnBack(int actionID)
113 if (actionID == ACTION_NAV_BACK && !m_vecItems->IsVirtualDirectoryRoot())
115 GoParentFolder();
116 return true;
118 return CGUIDialog::OnBack(actionID);
121 bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message)
123 switch ( message.GetMessage() )
125 case GUI_MSG_WINDOW_DEINIT:
127 if (m_thumbLoader.IsLoading())
128 m_thumbLoader.StopThread();
129 CGUIDialog::OnMessage(message);
130 ClearFileItems();
131 m_addNetworkShareEnabled = false;
132 return true;
134 break;
136 case GUI_MSG_WINDOW_INIT:
138 m_bConfirmed = false;
139 m_bFlip = false;
140 bool bIsDir = false;
141 // this code allows two different selection modes for directories
142 // end the path with a slash to start inside the directory
143 if (URIUtils::HasSlashAtEnd(m_selectedPath))
145 bIsDir = true;
146 bool bFool;
147 int iSource = CUtil::GetMatchingSource(m_selectedPath,m_shares,bFool);
148 bFool = true;
149 if (iSource > -1 && iSource < (int)m_shares.size())
151 if (URIUtils::PathEquals(m_shares[iSource].strPath, m_selectedPath))
152 bFool = false;
155 if (bFool && !CDirectory::Exists(m_selectedPath))
156 m_selectedPath.clear();
158 else
160 if (!CFile::Exists(m_selectedPath) && !CDirectory::Exists(m_selectedPath))
161 m_selectedPath.clear();
164 // find the parent folder if we are a file browser (don't do this for folders)
165 m_Directory->SetPath(m_selectedPath);
166 if (!m_browsingForFolders && !bIsDir)
167 m_Directory->SetPath(URIUtils::GetParentPath(m_selectedPath));
168 Update(m_Directory->GetPath());
169 m_viewControl.SetSelectedItem(m_selectedPath);
170 return CGUIDialog::OnMessage(message);
172 break;
174 case GUI_MSG_CLICKED:
176 if (m_viewControl.HasControl(message.GetSenderId())) // list control
178 int iItem = m_viewControl.GetSelectedItem();
179 int iAction = message.GetParam1();
180 if (iItem < 0) break;
181 CFileItemPtr pItem = (*m_vecItems)[iItem];
182 if ((iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK) &&
183 (!m_multipleSelection || pItem->m_bIsShareOrDrive || pItem->m_bIsFolder))
185 OnClick(iItem);
186 return true;
188 else if ((iAction == ACTION_HIGHLIGHT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK || iAction == ACTION_SELECT_ITEM) &&
189 (m_multipleSelection && !pItem->m_bIsShareOrDrive && !pItem->m_bIsFolder))
191 pItem->Select(!pItem->IsSelected());
192 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), message.GetSenderId(), iItem + 1);
193 OnMessage(msg);
196 else if (message.GetSenderId() == CONTROL_OK)
198 if (m_browsingForFolders == 2)
200 int iItem = m_viewControl.GetSelectedItem();
202 std::string strPath;
203 if (iItem == 0)
204 strPath = m_selectedPath;
205 else
206 strPath = (*m_vecItems)[iItem]->GetPath();
208 std::string strTest = URIUtils::AddFileToFolder(strPath, "1");
209 CFile file;
210 if (file.OpenForWrite(strTest,true))
212 file.Close();
213 CFile::Delete(strTest);
214 m_bConfirmed = true;
215 Close();
217 else
218 HELPERS::ShowOKDialogText(CVariant{257}, CVariant{20072});
220 else
222 if (m_multipleSelection)
224 for (int iItem = 0; iItem < m_vecItems->Size(); ++iItem)
226 CFileItemPtr pItem = (*m_vecItems)[iItem];
227 if (pItem->IsSelected())
228 m_markedPath.push_back(pItem->GetPath());
231 m_bConfirmed = true;
232 Close();
234 return true;
236 else if (message.GetSenderId() == CONTROL_CANCEL)
238 Close();
239 return true;
241 else if (message.GetSenderId() == CONTROL_NEWFOLDER)
243 std::string strInput;
244 if (CGUIKeyboardFactory::ShowAndGetInput(strInput, CVariant{g_localizeStrings.Get(119)}, false))
246 std::string strPath = URIUtils::AddFileToFolder(m_vecItems->GetPath(), strInput);
247 if (CDirectory::Create(strPath))
248 Update(m_vecItems->GetPath());
249 else
250 HELPERS::ShowOKDialogText(CVariant{20069}, CVariant{20072});
253 else if (message.GetSenderId() == CONTROL_FLIP)
254 m_bFlip = !m_bFlip;
256 break;
257 case GUI_MSG_SETFOCUS:
259 if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId())
261 m_viewControl.SetFocused();
262 return true;
265 break;
266 case GUI_MSG_NOTIFY_ALL:
267 { // Message is received only if this window is active
268 if (message.GetParam1() == GUI_MSG_REMOVED_MEDIA)
270 if (m_Directory->IsVirtualDirectoryRoot() && IsActive())
272 int iItem = m_viewControl.GetSelectedItem();
273 Update(m_Directory->GetPath());
274 m_viewControl.SetSelectedItem(iItem);
276 else if (m_Directory->IsRemovable())
277 { // check that we have this removable share still
278 if (!m_rootDir.IsInSource(m_Directory->GetPath()))
279 { // don't have this share any more
280 if (IsActive()) Update("");
281 else
283 m_history.ClearPathHistory();
284 m_Directory->SetPath("");
288 return true;
290 else if (message.GetParam1()==GUI_MSG_UPDATE_SOURCES)
291 { // State of the sources changed, so update our view
292 if (m_Directory->IsVirtualDirectoryRoot() && IsActive())
294 int iItem = m_viewControl.GetSelectedItem();
295 Update(m_Directory->GetPath());
296 m_viewControl.SetSelectedItem(iItem);
298 return true;
300 else if (message.GetParam1()==GUI_MSG_UPDATE_PATH)
302 if (IsActive())
304 if((message.GetStringParam() == m_Directory->GetPath()) ||
305 (m_Directory->IsMultiPath() && XFILE::CMultiPathDirectory::HasPath(m_Directory->GetPath(), message.GetStringParam())))
307 int iItem = m_viewControl.GetSelectedItem();
308 Update(m_Directory->GetPath());
309 m_viewControl.SetSelectedItem(iItem);
314 break;
317 return CGUIDialog::OnMessage(message);
320 void CGUIDialogFileBrowser::ClearFileItems()
322 m_viewControl.Clear();
323 m_vecItems->Clear(); // will clean up everything
326 void CGUIDialogFileBrowser::OnSort()
328 if (!m_singleList)
329 m_vecItems->Sort(SortByLabel, SortOrderAscending);
332 void CGUIDialogFileBrowser::Update(const std::string &strDirectory)
334 const CURL pathToUrl(strDirectory);
336 if (m_browsingForImages && m_thumbLoader.IsLoading())
337 m_thumbLoader.StopThread();
338 // get selected item
339 int iItem = m_viewControl.GetSelectedItem();
340 std::string strSelectedItem;
341 if (iItem >= 0 && iItem < m_vecItems->Size())
343 CFileItemPtr pItem = (*m_vecItems)[iItem];
344 if (!pItem->IsParentFolder())
346 strSelectedItem = pItem->GetPath();
347 URIUtils::RemoveSlashAtEnd(strSelectedItem);
348 m_history.SetSelectedItem(strSelectedItem, m_Directory->GetPath().empty()?"empty":m_Directory->GetPath());
352 if (!m_singleList)
354 CFileItemList items;
355 std::string strParentPath;
357 if (!m_rootDir.GetDirectory(pathToUrl, items, m_useFileDirectories, false))
359 CLog::Log(LOGERROR, "CGUIDialogFileBrowser::GetDirectory({}) failed",
360 pathToUrl.GetRedacted());
362 // We assume, we can get the parent
363 // directory again
364 std::string strParentPath = m_history.GetParentPath();
365 m_history.RemoveParentPath();
366 Update(strParentPath);
367 return;
370 // check if current directory is a root share
371 if (!m_rootDir.IsSource(strDirectory))
373 if (URIUtils::GetParentPath(strDirectory, strParentPath))
375 CFileItemPtr pItem(new CFileItem(".."));
376 pItem->SetPath(strParentPath);
377 pItem->m_bIsFolder = true;
378 pItem->m_bIsShareOrDrive = false;
379 items.AddFront(pItem, 0);
382 else
384 // yes, this is the root of a share
385 // add parent path to the virtual directory
386 CFileItemPtr pItem(new CFileItem(".."));
387 pItem->SetPath("");
388 pItem->m_bIsShareOrDrive = false;
389 pItem->m_bIsFolder = true;
390 items.AddFront(pItem, 0);
391 strParentPath = "";
394 ClearFileItems();
395 m_vecItems->Copy(items);
396 m_Directory->SetPath(strDirectory);
397 m_strParentPath = strParentPath;
400 // if we're getting the root source listing
401 // make sure the path history is clean
402 if (strDirectory.empty())
403 m_history.ClearPathHistory();
405 // some evil stuff don't work with the '/' mask, e.g. shoutcast directory - make sure no files are in there
406 if (m_browsingForFolders)
408 for (int i=0;i<m_vecItems->Size();++i)
409 if (!(*m_vecItems)[i]->m_bIsFolder)
411 m_vecItems->Remove(i);
412 i--;
416 // No need to set thumbs
418 m_vecItems->FillInDefaultIcons();
420 OnSort();
422 if (m_Directory->GetPath().empty() && m_addNetworkShareEnabled &&
423 (CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE ||
424 CServiceBroker::GetSettingsComponent()->GetProfileManager()->IsMasterProfile() || g_passwordManager.bMasterUser))
425 { // we are in the virtual directory - add the "Add Network Location" item
426 CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(1032)));
427 pItem->SetPath("net://");
428 pItem->m_bIsFolder = true;
429 m_vecItems->Add(pItem);
431 if (m_Directory->GetPath().empty() && !m_addSourceType.empty())
433 CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(21359)));
434 pItem->SetPath("source://");
435 pItem->m_bIsFolder = true;
436 m_vecItems->Add(pItem);
439 m_viewControl.SetItems(*m_vecItems);
440 m_viewControl.SetCurrentView((m_browsingForImages && CAutoSwitch::ByFileCount(*m_vecItems)) ? CONTROL_THUMBS : CONTROL_LIST);
442 std::string strPath2 = m_Directory->GetPath();
443 URIUtils::RemoveSlashAtEnd(strPath2);
444 strSelectedItem = m_history.GetSelectedItem(strPath2==""?"empty":strPath2);
446 bool bSelectedFound = false;
447 for (int i = 0; i < m_vecItems->Size(); ++i)
449 CFileItemPtr pItem = (*m_vecItems)[i];
450 strPath2 = pItem->GetPath();
451 URIUtils::RemoveSlashAtEnd(strPath2);
452 if (strPath2 == strSelectedItem)
454 m_viewControl.SetSelectedItem(i);
455 bSelectedFound = true;
456 break;
460 // if we haven't found the selected item, select the first item
461 if (!bSelectedFound)
462 m_viewControl.SetSelectedItem(0);
464 m_history.AddPath(m_Directory->GetPath());
466 if (m_browsingForImages)
467 m_thumbLoader.Load(*m_vecItems);
470 void CGUIDialogFileBrowser::FrameMove()
472 int item = m_viewControl.GetSelectedItem();
473 if (item >= 0)
475 // if we are browsing for folders, and not in the root directory, then we use the parent path,
476 // else we use the current file's path
477 if (m_browsingForFolders && !m_Directory->IsVirtualDirectoryRoot())
478 m_selectedPath = m_Directory->GetPath();
479 else
480 m_selectedPath = (*m_vecItems)[item]->GetPath();
481 if (m_selectedPath == "net://")
483 SET_CONTROL_LABEL(CONTROL_LABEL_PATH, g_localizeStrings.Get(1032)); // "Add Network Location..."
485 else
487 // Update the current path label
488 CURL url(m_selectedPath);
489 std::string safePath = url.GetWithoutUserDetails();
490 SET_CONTROL_LABEL(CONTROL_LABEL_PATH, safePath);
492 if ((!m_browsingForFolders && (*m_vecItems)[item]->m_bIsFolder) || ((*m_vecItems)[item]->GetPath() == "image://Browse"))
494 CONTROL_DISABLE(CONTROL_OK);
496 else
498 CONTROL_ENABLE(CONTROL_OK);
500 if (m_browsingForFolders == 2)
502 CONTROL_ENABLE(CONTROL_NEWFOLDER);
504 else
506 CONTROL_DISABLE(CONTROL_NEWFOLDER);
508 if (m_flipEnabled)
510 CONTROL_ENABLE(CONTROL_FLIP);
512 else
514 CONTROL_DISABLE(CONTROL_FLIP);
517 CGUIDialog::FrameMove();
520 void CGUIDialogFileBrowser::OnClick(int iItem)
522 if ( iItem < 0 || iItem >= m_vecItems->Size() ) return ;
523 CFileItemPtr pItem = (*m_vecItems)[iItem];
524 std::string strPath = pItem->GetPath();
526 if (pItem->m_bIsFolder)
528 if (pItem->GetPath() == "net://")
529 { // special "Add Network Location" item
530 OnAddNetworkLocation();
531 return;
533 if (pItem->GetPath() == "source://")
534 { // special "Add Source" item
535 OnAddMediaSource();
536 return;
538 if (!m_addSourceType.empty())
540 OnEditMediaSource(pItem.get());
541 return;
543 if ( pItem->m_bIsShareOrDrive )
545 if ( !HaveDiscOrConnection( pItem->m_iDriveType ) )
546 return ;
548 Update(strPath);
550 else if (!m_browsingForFolders)
552 m_selectedPath = pItem->GetPath();
553 m_bConfirmed = true;
554 Close();
558 bool CGUIDialogFileBrowser::HaveDiscOrConnection( int iDriveType )
560 if ( iDriveType == CMediaSource::SOURCE_TYPE_DVD )
562 if (!CServiceBroker::GetMediaManager().IsDiscInDrive())
564 HELPERS::ShowOKDialogText(CVariant{218}, CVariant{219});
565 return false;
568 else if ( iDriveType == CMediaSource::SOURCE_TYPE_REMOTE )
570 //! @todo Handle not connected to a remote share
571 if ( !CServiceBroker::GetNetwork().IsConnected() )
573 HELPERS::ShowOKDialogText(CVariant{220}, CVariant{221});
574 return false;
578 return true;
581 void CGUIDialogFileBrowser::GoParentFolder()
583 std::string strPath(m_strParentPath);
584 if (strPath.size() == 2)
585 if (strPath[1] == ':')
586 URIUtils::AddSlashAtEnd(strPath);
587 Update(strPath);
590 void CGUIDialogFileBrowser::OnWindowLoaded()
592 CGUIDialog::OnWindowLoaded();
593 m_viewControl.Reset();
594 m_viewControl.SetParentWindow(GetID());
595 m_viewControl.AddView(GetControl(CONTROL_LIST));
596 m_viewControl.AddView(GetControl(CONTROL_THUMBS));
599 void CGUIDialogFileBrowser::OnWindowUnload()
601 CGUIDialog::OnWindowUnload();
602 m_viewControl.Reset();
605 bool CGUIDialogFileBrowser::ShowAndGetImage(const CFileItemList &items, const VECSOURCES &shares, const std::string &heading, std::string &result, bool* flip, int label)
607 CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
608 if (!browser)
609 return false;
610 CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
612 browser->m_browsingForImages = true;
613 browser->m_singleList = true;
614 browser->m_vecItems->Clear();
615 browser->m_vecItems->Append(items);
616 if (true)
618 CFileItemPtr item(new CFileItem("image://Browse", false));
619 item->SetLabel(g_localizeStrings.Get(20153));
620 item->SetArt("icon", "DefaultFolder.png");
621 browser->m_vecItems->Add(item);
623 browser->SetHeading(heading);
624 browser->m_flipEnabled = flip?true:false;
625 browser->Open();
626 bool confirmed(browser->IsConfirmed());
627 if (confirmed)
629 result = browser->m_selectedPath;
630 if (result == "image://Browse")
631 { // "Browse for thumb"
632 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
633 delete browser;
634 return ShowAndGetImage(shares, g_localizeStrings.Get(label), result);
638 if (flip)
639 *flip = browser->m_bFlip != 0;
641 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
642 delete browser;
644 return confirmed;
647 bool CGUIDialogFileBrowser::ShowAndGetImage(const VECSOURCES &shares, const std::string &heading, std::string &path)
649 return ShowAndGetFile(shares, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), heading, path, true); // true for use thumbs
652 bool CGUIDialogFileBrowser::ShowAndGetImageList(const VECSOURCES &shares, const std::string &heading, std::vector<std::string> &path)
654 return ShowAndGetFileList(shares, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), heading, path, true); // true for use thumbs
657 bool CGUIDialogFileBrowser::ShowAndGetDirectory(const VECSOURCES &shares, const std::string &heading, std::string &path, bool bWriteOnly)
659 // an extension mask of "/" ensures that no files are shown
660 if (bWriteOnly)
662 VECSOURCES shareWritable;
663 for (unsigned int i=0;i<shares.size();++i)
665 if (shares[i].IsWritable())
666 shareWritable.push_back(shares[i]);
669 return ShowAndGetFile(shareWritable, "/w", heading, path);
672 return ShowAndGetFile(shares, "/", heading, path);
675 bool CGUIDialogFileBrowser::ShowAndGetFile(const VECSOURCES &shares, const std::string &mask, const std::string &heading, std::string &path, bool useThumbs /* = false */, bool useFileDirectories /* = false */)
677 CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
678 if (!browser)
679 return false;
680 CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
682 browser->m_useFileDirectories = useFileDirectories;
684 browser->m_browsingForImages = useThumbs;
685 browser->SetHeading(heading);
686 browser->SetSources(shares);
687 std::string strMask = mask;
688 if (mask == "/")
689 browser->m_browsingForFolders=1;
690 else
691 if (mask == "/w")
693 browser->m_browsingForFolders=2;
694 strMask = "/";
696 else
697 browser->m_browsingForFolders = 0;
699 browser->m_rootDir.SetMask(strMask);
700 browser->m_selectedPath = path;
701 browser->m_addNetworkShareEnabled = false;
702 browser->Open();
703 bool confirmed(browser->IsConfirmed());
704 if (confirmed)
705 path = browser->m_selectedPath;
706 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
707 delete browser;
708 return confirmed;
711 // same as above, starting in a single directory
712 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 */)
714 CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
715 if (!browser)
716 return false;
717 CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
719 browser->m_useFileDirectories = useFileDirectories;
720 browser->m_browsingForImages = useThumbs;
721 browser->SetHeading(heading);
723 // add a single share for this directory
724 if (!singleList)
726 VECSOURCES shares;
727 CMediaSource share;
728 share.strPath = directory;
729 URIUtils::RemoveSlashAtEnd(share.strPath); // this is needed for the dodgy code in WINDOW_INIT
730 shares.push_back(share);
731 browser->SetSources(shares);
733 else
735 browser->m_vecItems->Clear();
736 CDirectory::GetDirectory(directory,*browser->m_vecItems, "", DIR_FLAG_DEFAULTS);
737 CFileItemPtr item(new CFileItem("file://Browse", false));
738 item->SetLabel(g_localizeStrings.Get(20153));
739 item->SetArt("icon", "DefaultFolder.png");
740 browser->m_vecItems->Add(item);
741 browser->m_singleList = true;
743 std::string strMask = mask;
744 if (mask == "/")
745 browser->m_browsingForFolders=1;
746 else
747 if (mask == "/w")
749 browser->m_browsingForFolders=2;
750 strMask = "/";
752 else
753 browser->m_browsingForFolders = 0;
755 browser->m_rootDir.SetMask(strMask);
756 browser->m_selectedPath = directory;
757 browser->m_addNetworkShareEnabled = false;
758 browser->Open();
759 bool confirmed(browser->IsConfirmed());
760 if (confirmed)
761 path = browser->m_selectedPath;
762 if (path == "file://Browse")
763 { // "Browse for thumb"
764 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
765 delete browser;
766 VECSOURCES shares;
767 CServiceBroker::GetMediaManager().GetLocalDrives(shares);
769 return ShowAndGetFile(shares, mask, heading, path, useThumbs,useFileDirectories);
771 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
772 delete browser;
773 return confirmed;
776 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 */)
778 CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
779 if (!browser)
780 return false;
781 CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
783 browser->m_useFileDirectories = useFileDirectories;
784 browser->m_multipleSelection = true;
785 browser->m_browsingForImages = useThumbs;
786 browser->SetHeading(heading);
787 browser->SetSources(shares);
788 browser->m_browsingForFolders = 0;
789 browser->m_rootDir.SetMask(mask);
790 browser->m_addNetworkShareEnabled = false;
791 browser->Open();
792 bool confirmed(browser->IsConfirmed());
793 if (confirmed)
795 if (browser->m_markedPath.size())
796 path = browser->m_markedPath;
797 else
798 path.push_back(browser->m_selectedPath);
800 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
801 delete browser;
802 return confirmed;
805 void CGUIDialogFileBrowser::SetHeading(const std::string &heading)
807 Initialize();
808 SET_CONTROL_LABEL(CONTROL_HEADING_LABEL, heading);
811 bool CGUIDialogFileBrowser::ShowAndGetSource(std::string &path, bool allowNetworkShares, VECSOURCES* additionalShare /* = NULL */, const std::string& strType /* = "" */)
813 // Technique is
814 // 1. Show Filebrowser with currently defined local, and optionally the network locations.
815 // 2. Have the "Add Network Location" option in addition.
816 // 3a. If the "Add Network Location" is pressed, then:
817 // a) Fire up the network location dialog to grab the new location
818 // b) Check the location by doing a GetDirectory() - if it fails, prompt the user
819 // to allow them to add currently disconnected network shares.
820 // c) Save this location to our xml file (network.xml)
821 // d) Return to 1.
822 // 3b. If the "Add Source" is pressed, then:
823 // a) Fire up the media source dialog to add the new location
824 // 4. Optionally allow user to browse the local and network locations for their share.
825 // 5. On OK, return.
827 // Create a new filebrowser window
828 CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser();
829 if (!browser) return false;
831 // Add it to our window manager
832 CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser);
834 VECSOURCES shares;
835 if (!strType.empty())
837 if (additionalShare)
838 shares = *additionalShare;
839 browser->m_addSourceType = strType;
841 else
843 browser->SetHeading(g_localizeStrings.Get(1023));
845 CServiceBroker::GetMediaManager().GetLocalDrives(shares);
847 // Now the additional share if appropriate
848 if (additionalShare)
850 shares.insert(shares.end(),additionalShare->begin(),additionalShare->end());
853 // Now add the network shares...
854 if (allowNetworkShares)
856 CServiceBroker::GetMediaManager().GetNetworkLocations(shares);
860 browser->SetSources(shares);
861 browser->m_rootDir.SetMask("/");
862 browser->m_rootDir.AllowNonLocalSources(false); // don't allow plug n play shares
863 browser->m_browsingForFolders = 1;
864 browser->m_addNetworkShareEnabled = allowNetworkShares;
865 browser->m_selectedPath = "";
866 browser->Open();
867 bool confirmed = browser->IsConfirmed();
868 if (confirmed)
869 path = browser->m_selectedPath;
871 CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID());
872 delete browser;
873 return confirmed;
876 void CGUIDialogFileBrowser::SetSources(const VECSOURCES &shares)
878 m_shares = shares;
879 if (!m_shares.size() && m_addSourceType.empty())
880 CServiceBroker::GetMediaManager().GetLocalDrives(m_shares);
881 m_rootDir.SetSources(m_shares);
884 void CGUIDialogFileBrowser::OnAddNetworkLocation()
886 // ok, fire up the network location dialog
887 std::string path;
888 if (CGUIDialogNetworkSetup::ShowAndGetNetworkAddress(path))
890 // verify the path by doing a GetDirectory.
891 CFileItemList items;
892 if (CDirectory::GetDirectory(path, items, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_ALLOW_PROMPT) || CGUIDialogYesNo::ShowAndGetInput(CVariant{1001}, CVariant{1002}))
893 { // add the network location to the shares list
894 CMediaSource share;
895 share.strPath = path; //setPath(path);
896 CURL url(path);
897 share.strName = url.GetWithoutUserDetails();
898 URIUtils::RemoveSlashAtEnd(share.strName);
899 m_shares.push_back(share);
900 // add to our location manager...
901 CServiceBroker::GetMediaManager().AddNetworkLocation(path);
904 m_rootDir.SetSources(m_shares);
905 Update(m_vecItems->GetPath());
908 void CGUIDialogFileBrowser::OnAddMediaSource()
910 if (CGUIDialogMediaSource::ShowAndAddMediaSource(m_addSourceType))
912 SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
913 Update("");
917 void CGUIDialogFileBrowser::OnEditMediaSource(CFileItem* pItem)
919 if (CGUIDialogMediaSource::ShowAndEditMediaSource(m_addSourceType,pItem->GetLabel()))
921 SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
922 Update("");
926 bool CGUIDialogFileBrowser::OnPopupMenu(int iItem)
928 CContextButtons choices;
929 choices.Add(1, m_addSourceType.empty() ? 20133 : 21364);
930 choices.Add(2, m_addSourceType.empty() ? 20134 : 21365);
932 int btnid = CGUIDialogContextMenu::ShowAndGetChoice(choices);
933 if (btnid == 1)
935 if (m_addNetworkShareEnabled)
937 std::string strOldPath=m_selectedPath,newPath=m_selectedPath;
938 VECSOURCES shares=m_shares;
939 if (CGUIDialogNetworkSetup::ShowAndGetNetworkAddress(newPath))
941 CServiceBroker::GetMediaManager().SetLocationPath(strOldPath, newPath);
942 CURL url(newPath);
943 for (unsigned int i=0;i<shares.size();++i)
945 if (URIUtils::CompareWithoutSlashAtEnd(shares[i].strPath, strOldPath))//getPath().Equals(strOldPath))
947 shares[i].strName = url.GetWithoutUserDetails();
948 shares[i].strPath = newPath;
949 URIUtils::RemoveSlashAtEnd(shares[i].strName);
950 break;
953 // refresh dialog content
954 SetSources(shares);
955 m_rootDir.SetMask("/");
956 m_browsingForFolders = 1;
957 m_addNetworkShareEnabled = true;
958 m_selectedPath = url.GetWithoutUserDetails();
959 Update(m_Directory->GetPath());
960 m_viewControl.SetSelectedItem(iItem);
963 else
965 CFileItemPtr item = m_vecItems->Get(iItem);
966 OnEditMediaSource(item.get());
969 if (btnid == 2)
971 if (m_addNetworkShareEnabled)
973 CServiceBroker::GetMediaManager().RemoveLocation(m_selectedPath);
975 for (unsigned int i=0;i<m_shares.size();++i)
977 if (URIUtils::CompareWithoutSlashAtEnd(m_shares[i].strPath, m_selectedPath) && !m_shares[i].m_ignore) // getPath().Equals(m_selectedPath))
979 m_shares.erase(m_shares.begin()+i);
980 break;
983 m_rootDir.SetSources(m_shares);
984 m_rootDir.SetMask("/");
986 m_browsingForFolders = 1;
987 m_addNetworkShareEnabled = true;
988 m_selectedPath = "";
990 Update(m_Directory->GetPath());
992 else
994 CMediaSourceSettings::GetInstance().DeleteSource(m_addSourceType,(*m_vecItems)[iItem]->GetLabel(),(*m_vecItems)[iItem]->GetPath());
995 SetSources(*CMediaSourceSettings::GetInstance().GetSources(m_addSourceType));
996 Update("");
1000 return true;
1003 CFileItemPtr CGUIDialogFileBrowser::GetCurrentListItem(int offset)
1005 int item = m_viewControl.GetSelectedItem();
1006 if (item < 0 || !m_vecItems->Size()) return CFileItemPtr();
1008 item = (item + offset) % m_vecItems->Size();
1009 if (item < 0) item += m_vecItems->Size();
1010 return (*m_vecItems)[item];
1013 CGUIControl *CGUIDialogFileBrowser::GetFirstFocusableControl(int id)
1015 if (m_viewControl.HasControl(id))
1016 id = m_viewControl.GetCurrentControl();
1017 return CGUIWindow::GetFirstFocusableControl(id);