[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / pictures / GUIWindowPictures.cpp
blobebc8fe9f2af64be7283f11dc02ef95fdf6732369
1 /*
2 * Copyright (C) 2005-2020 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 "GUIWindowPictures.h"
11 #include "Autorun.h"
12 #include "FileItem.h"
13 #include "GUIDialogPictureInfo.h"
14 #include "GUIPassword.h"
15 #include "GUIWindowSlideShow.h"
16 #include "PictureInfoLoader.h"
17 #include "ServiceBroker.h"
18 #include "URL.h"
19 #include "Util.h"
20 #include "addons/gui/GUIDialogAddonInfo.h"
21 #include "application/Application.h"
22 #include "application/ApplicationComponents.h"
23 #include "application/ApplicationPlayer.h"
24 #include "dialogs/GUIDialogMediaSource.h"
25 #include "dialogs/GUIDialogProgress.h"
26 #include "guilib/GUIComponent.h"
27 #include "guilib/GUIWindowManager.h"
28 #include "input/actions/ActionIDs.h"
29 #include "interfaces/AnnouncementManager.h"
30 #include "media/MediaLockState.h"
31 #include "messaging/helpers/DialogOKHelper.h"
32 #include "playlists/PlayList.h"
33 #include "playlists/PlayListFactory.h"
34 #include "settings/MediaSourceSettings.h"
35 #include "settings/Settings.h"
36 #include "settings/SettingsComponent.h"
37 #include "utils/SortUtils.h"
38 #include "utils/StringUtils.h"
39 #include "utils/URIUtils.h"
40 #include "utils/Variant.h"
41 #include "utils/XTimeUtils.h"
42 #include "utils/log.h"
43 #include "view/GUIViewState.h"
45 #define CONTROL_BTNSORTASC 4
46 #define CONTROL_LABELFILES 12
48 using namespace XFILE;
49 using namespace KODI::MESSAGING;
51 using namespace std::chrono_literals;
53 #define CONTROL_BTNSLIDESHOW 6
54 #define CONTROL_BTNSLIDESHOW_RECURSIVE 7
55 #define CONTROL_SHUFFLE 9
57 CGUIWindowPictures::CGUIWindowPictures(void)
58 : CGUIMediaWindow(WINDOW_PICTURES, "MyPics.xml")
60 m_thumbLoader.SetObserver(this);
61 m_slideShowStarted = false;
62 m_dlgProgress = NULL;
65 void CGUIWindowPictures::OnInitWindow()
67 CGUIMediaWindow::OnInitWindow();
68 if (m_slideShowStarted)
70 CGUIWindowSlideShow* wndw = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
71 std::string path;
72 if (wndw && wndw->GetCurrentSlide())
73 path = URIUtils::GetDirectory(wndw->GetCurrentSlide()->GetPath());
74 if (m_vecItems->IsPath(path))
76 if (wndw && wndw->GetCurrentSlide())
77 m_viewControl.SetSelectedItem(wndw->GetCurrentSlide()->GetPath());
78 SaveSelectedItemInHistory();
80 m_slideShowStarted = false;
84 CGUIWindowPictures::~CGUIWindowPictures(void) = default;
86 bool CGUIWindowPictures::OnMessage(CGUIMessage& message)
88 switch ( message.GetMessage() )
90 case GUI_MSG_WINDOW_DEINIT:
92 if (m_thumbLoader.IsLoading())
93 m_thumbLoader.StopThread();
96 break;
98 case GUI_MSG_WINDOW_INIT:
100 // is this the first time accessing this window?
101 if (m_vecItems->GetPath() == "?" && message.GetStringParam().empty())
102 message.SetStringParam(CMediaSourceSettings::GetInstance().GetDefaultSource("pictures"));
104 m_dlgProgress = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(WINDOW_DIALOG_PROGRESS);
106 break;
108 case GUI_MSG_CLICKED:
110 int iControl = message.GetSenderId();
111 if (iControl == CONTROL_BTNSLIDESHOW) // Slide Show
113 OnSlideShow();
115 else if (iControl == CONTROL_BTNSLIDESHOW_RECURSIVE) // Recursive Slide Show
117 OnSlideShowRecursive();
119 else if (iControl == CONTROL_SHUFFLE)
121 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
122 settings->ToggleBool(CSettings::SETTING_SLIDESHOW_SHUFFLE);
123 settings->Save();
125 else if (m_viewControl.HasControl(iControl)) // list/thumb control
127 int iItem = m_viewControl.GetSelectedItem();
128 int iAction = message.GetParam1();
130 // iItem is checked for validity inside these routines
131 if (iAction == ACTION_DELETE_ITEM)
133 // is delete allowed?
134 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_ALLOWFILEDELETION))
135 OnDeleteItem(iItem);
136 else
137 return false;
139 else if (iAction == ACTION_PLAYER_PLAY)
141 ShowPicture(iItem, true);
142 return true;
144 else if (iAction == ACTION_SHOW_INFO)
146 OnItemInfo(iItem);
147 return true;
151 break;
153 return CGUIMediaWindow::OnMessage(message);
156 void CGUIWindowPictures::UpdateButtons()
158 CGUIMediaWindow::UpdateButtons();
160 // Update the shuffle button
161 SET_CONTROL_SELECTED(GetID(), CONTROL_SHUFFLE, CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_SLIDESHOW_SHUFFLE));
163 // check we can slideshow or recursive slideshow
164 int nFolders = m_vecItems->GetFolderCount();
165 if (nFolders == m_vecItems->Size() ||
166 m_vecItems->GetPath() == "addons://sources/image/")
168 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW);
170 else
172 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW);
174 if (m_guiState.get() && !m_guiState->HideParentDirItems())
175 nFolders--;
176 if (m_vecItems->Size() == 0 || nFolders == 0 ||
177 m_vecItems->GetPath() == "addons://sources/image/")
179 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
181 else
183 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
187 void CGUIWindowPictures::OnPrepareFileItems(CFileItemList& items)
189 CGUIMediaWindow::OnPrepareFileItems(items);
191 for (int i=0;i<items.Size();++i )
192 if (StringUtils::EqualsNoCase(items[i]->GetLabel(), "folder.jpg"))
193 items.Remove(i);
195 if (items.GetFolderCount() == items.Size() || !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_PICTURES_USETAGS))
196 return;
198 // Start the music info loader thread
199 CPictureInfoLoader loader;
200 loader.SetProgressCallback(m_dlgProgress);
201 loader.Load(items);
203 bool bShowProgress = !CServiceBroker::GetGUI()->GetWindowManager().HasModalDialog(true);
204 bool bProgressVisible = false;
206 auto start = std::chrono::steady_clock::now();
208 while (loader.IsLoading() && m_dlgProgress && !m_dlgProgress->IsCanceled())
210 if (bShowProgress)
211 { // Do we have to init a progress dialog?
212 auto end = std::chrono::steady_clock::now();
213 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
215 if (!bProgressVisible && duration.count() > 1500 && m_dlgProgress)
216 { // tag loading takes more then 1.5 secs, show a progress dialog
217 CURL url(items.GetPath());
219 m_dlgProgress->SetHeading(CVariant{189});
220 m_dlgProgress->SetLine(0, CVariant{505});
221 m_dlgProgress->SetLine(1, CVariant{""});
222 m_dlgProgress->SetLine(2, CVariant{url.GetWithoutUserDetails()});
223 m_dlgProgress->Open();
224 m_dlgProgress->ShowProgressBar(true);
225 bProgressVisible = true;
228 if (bProgressVisible && m_dlgProgress)
229 { // keep GUI alive
230 m_dlgProgress->Progress();
232 } // if (bShowProgress)
233 KODI::TIME::Sleep(1ms);
234 } // while (loader.IsLoading())
236 if (bProgressVisible && m_dlgProgress)
237 m_dlgProgress->Close();
240 bool CGUIWindowPictures::Update(const std::string &strDirectory, bool updateFilterPath /* = true */)
242 if (m_thumbLoader.IsLoading())
243 m_thumbLoader.StopThread();
245 if (!CGUIMediaWindow::Update(strDirectory, updateFilterPath))
246 return false;
248 m_vecItems->SetArt("thumb", "");
249 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_PICTURES_GENERATETHUMBS))
250 m_thumbLoader.Load(*m_vecItems);
252 CPictureThumbLoader thumbLoader;
253 std::string thumb = thumbLoader.GetCachedImage(*m_vecItems, "thumb");
254 m_vecItems->SetArt("thumb", thumb);
256 return true;
259 bool CGUIWindowPictures::OnClick(int iItem, const std::string &player)
261 if ( iItem < 0 || iItem >= m_vecItems->Size() ) return true;
262 CFileItemPtr pItem = m_vecItems->Get(iItem);
264 if (pItem->IsCBZ() || pItem->IsCBR())
266 CURL pathToUrl;
267 if (pItem->IsCBZ())
268 pathToUrl = URIUtils::CreateArchivePath("zip", pItem->GetURL(), "");
269 else
270 pathToUrl = URIUtils::CreateArchivePath("rar", pItem->GetURL(), "");
272 OnShowPictureRecursive(pathToUrl.Get());
273 return true;
275 else if (CGUIMediaWindow::OnClick(iItem, player))
276 return true;
278 return false;
281 bool CGUIWindowPictures::GetDirectory(const std::string &strDirectory, CFileItemList& items)
283 if (!CGUIMediaWindow::GetDirectory(strDirectory, items))
284 return false;
286 std::string label;
287 if (items.GetLabel().empty() && m_rootDir.IsSource(items.GetPath(), CMediaSourceSettings::GetInstance().GetSources("pictures"), &label))
288 items.SetLabel(label);
290 if (items.GetContent().empty() && !items.IsVirtualDirectoryRoot() && !items.IsPlugin())
291 items.SetContent("images");
292 return true;
295 bool CGUIWindowPictures::OnPlayMedia(int iItem, const std::string &player)
297 if (m_vecItems->Get(iItem)->IsVideo())
298 return CGUIMediaWindow::OnPlayMedia(iItem);
300 return ShowPicture(iItem, false);
303 bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow)
305 if ( iItem < 0 || iItem >= m_vecItems->Size() ) return false;
306 CFileItemPtr pItem = m_vecItems->Get(iItem);
307 std::string strPicture = pItem->GetPath();
309 #ifdef HAS_DVD_DRIVE
310 if (pItem->IsDVD())
311 return MEDIA_DETECT::CAutorun::PlayDiscAskResume(m_vecItems->Get(iItem)->GetPath());
312 #endif
314 if (pItem->m_bIsShareOrDrive)
315 return false;
317 CGUIWindowSlideShow *pSlideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
318 if (!pSlideShow)
319 return false;
320 const auto& components = CServiceBroker::GetAppComponents();
321 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
322 if (appPlayer->IsPlayingVideo())
323 g_application.StopPlaying();
325 pSlideShow->Reset();
326 bool bShowVideos = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_PICTURES_SHOWVIDEOS);
327 for (const auto& pItem : *m_vecItems)
329 if (!pItem->m_bIsFolder &&
330 !(URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath())) &&
331 (pItem->IsPicture() || (bShowVideos && pItem->IsVideo())))
333 pSlideShow->Add(pItem.get());
337 if (pSlideShow->NumSlides() == 0)
338 return false;
340 pSlideShow->Select(strPicture);
342 if (startSlideShow)
343 pSlideShow->StartSlideShow();
344 else
346 CVariant param;
347 param["player"]["speed"] = 1;
348 param["player"]["playerid"] = PLAYLIST::TYPE_PICTURE;
349 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Player, "OnPlay",
350 pSlideShow->GetCurrentSlide(), param);
353 m_slideShowStarted = true;
354 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_SLIDESHOW);
356 return true;
359 void CGUIWindowPictures::OnShowPictureRecursive(const std::string& strPath)
361 CGUIWindowSlideShow *pSlideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
362 if (pSlideShow)
364 // stop any video
365 const auto& components = CServiceBroker::GetAppComponents();
366 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
367 if (appPlayer->IsPlayingVideo())
368 g_application.StopPlaying();
370 SortDescription sorting = m_guiState->GetSortMethod();
371 pSlideShow->AddFromPath(strPath, true,
372 sorting.sortBy, sorting.sortOrder, sorting.sortAttributes);
373 if (pSlideShow->NumSlides())
375 m_slideShowStarted = true;
376 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_SLIDESHOW);
381 void CGUIWindowPictures::OnSlideShowRecursive(const std::string &strPicture)
383 CGUIWindowSlideShow *pSlideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
384 if (pSlideShow)
386 std::string strExtensions;
387 CFileItemList items;
388 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
389 if (viewState)
391 strExtensions = viewState->GetExtensions();
392 delete viewState;
394 m_slideShowStarted = true;
396 SortDescription sorting = m_guiState->GetSortMethod();
397 pSlideShow->RunSlideShow(strPicture, true,
398 CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_SLIDESHOW_SHUFFLE),false,
399 "", true,
400 sorting.sortBy, sorting.sortOrder, sorting.sortAttributes,
401 strExtensions);
405 void CGUIWindowPictures::OnSlideShowRecursive()
407 OnSlideShowRecursive(m_vecItems->GetPath());
410 void CGUIWindowPictures::OnSlideShow()
412 OnSlideShow(m_vecItems->GetPath());
415 void CGUIWindowPictures::OnSlideShow(const std::string &strPicture)
417 CGUIWindowSlideShow *pSlideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
418 if (pSlideShow)
420 std::string strExtensions;
421 CFileItemList items;
422 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
423 if (viewState)
425 strExtensions = viewState->GetExtensions();
426 delete viewState;
428 m_slideShowStarted = true;
430 SortDescription sorting = m_guiState->GetSortMethod();
431 pSlideShow->RunSlideShow(strPicture, false ,false, false,
432 "", true,
433 sorting.sortBy, sorting.sortOrder, sorting.sortAttributes,
434 strExtensions);
438 void CGUIWindowPictures::OnRegenerateThumbs()
440 if (m_thumbLoader.IsLoading()) return;
441 m_thumbLoader.SetRegenerateThumbs(true);
442 m_thumbLoader.Load(*m_vecItems);
445 void CGUIWindowPictures::GetContextButtons(int itemNumber, CContextButtons &buttons)
447 CFileItemPtr item;
448 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
449 item = m_vecItems->Get(itemNumber);
451 if (item)
453 if ( m_vecItems->IsVirtualDirectoryRoot() || m_vecItems->GetPath() == "sources://pictures/" )
455 CGUIDialogContextMenu::GetContextButtons("pictures", item, buttons);
457 else
459 if (item)
461 if (!(item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || item->IsScript()))
463 if (item->IsPicture())
464 buttons.Add(CONTEXT_BUTTON_INFO, 13406); // picture info
465 buttons.Add(CONTEXT_BUTTON_VIEW_SLIDESHOW, item->m_bIsFolder ? 13317 : 13422); // View Slideshow
467 if (item->m_bIsFolder)
468 buttons.Add(CONTEXT_BUTTON_RECURSIVE_SLIDESHOW, 13318); // Recursive Slideshow
470 if (!m_thumbLoader.IsLoading())
471 buttons.Add(CONTEXT_BUTTON_REFRESH_THUMBS, 13315); // Create Thumbnails
472 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_ALLOWFILEDELETION) && !item->IsReadOnly())
474 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
475 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
479 if (!item->IsPlugin() && !item->IsScript() && !m_vecItems->IsPlugin())
480 buttons.Add(CONTEXT_BUTTON_SWITCH_MEDIA, 523);
483 CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
486 bool CGUIWindowPictures::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
488 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
489 if (CGUIDialogContextMenu::OnContextButton("pictures", item, button))
491 Update("");
492 return true;
494 switch (button)
496 case CONTEXT_BUTTON_VIEW_SLIDESHOW:
497 if (item && item->m_bIsFolder)
498 OnSlideShow(item->GetPath());
499 else
500 ShowPicture(itemNumber, true);
501 return true;
502 case CONTEXT_BUTTON_RECURSIVE_SLIDESHOW:
503 if (item)
504 OnSlideShowRecursive(item->GetPath());
505 return true;
506 case CONTEXT_BUTTON_INFO:
507 OnItemInfo(itemNumber);
508 return true;
509 case CONTEXT_BUTTON_REFRESH_THUMBS:
510 OnRegenerateThumbs();
511 return true;
512 case CONTEXT_BUTTON_DELETE:
513 OnDeleteItem(itemNumber);
514 return true;
515 case CONTEXT_BUTTON_RENAME:
516 OnRenameItem(itemNumber);
517 return true;
518 case CONTEXT_BUTTON_SWITCH_MEDIA:
519 CGUIDialogContextMenu::SwitchMedia("pictures", m_vecItems->GetPath());
520 return true;
521 default:
522 break;
524 return CGUIMediaWindow::OnContextButton(itemNumber, button);
527 bool CGUIWindowPictures::OnAddMediaSource()
529 return CGUIDialogMediaSource::ShowAndAddMediaSource("pictures");
532 void CGUIWindowPictures::OnItemLoaded(CFileItem *pItem)
534 CPictureThumbLoader::ProcessFoldersAndArchives(pItem);
537 void CGUIWindowPictures::LoadPlayList(const std::string& strPlayList)
539 CLog::Log(LOGDEBUG,
540 "CGUIWindowPictures::LoadPlayList()... converting playlist into slideshow: {}",
541 strPlayList);
542 std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(strPlayList));
543 if (nullptr != pPlayList)
545 if (!pPlayList->Load(strPlayList))
547 HELPERS::ShowOKDialogText(CVariant{6}, CVariant{477});
548 return ; //hmmm unable to load playlist?
552 PLAYLIST::CPlayList playlist = *pPlayList;
553 if (playlist.size() > 0)
555 // set up slideshow
556 CGUIWindowSlideShow *pSlideShow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIWindowSlideShow>(WINDOW_SLIDESHOW);
557 if (!pSlideShow)
558 return;
559 const auto& components = CServiceBroker::GetAppComponents();
560 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
561 if (appPlayer->IsPlayingVideo())
562 g_application.StopPlaying();
564 // convert playlist items into slideshow items
565 pSlideShow->Reset();
566 for (int i = 0; i < playlist.size(); ++i)
568 CFileItemPtr pItem = playlist[i];
569 //CLog::Log(LOGDEBUG,"-- playlist item: {}", pItem->GetPath());
570 if (pItem->IsPicture() && !(pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBZ() || pItem->IsCBR()))
571 pSlideShow->Add(pItem.get());
574 // start slideshow if there are items
575 pSlideShow->StartSlideShow();
576 if (pSlideShow->NumSlides())
577 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_SLIDESHOW);
581 void CGUIWindowPictures::OnItemInfo(int itemNumber)
583 CFileItemPtr item = m_vecItems->Get(itemNumber);
584 if (!item)
585 return;
586 if (!m_vecItems->IsPlugin() && (item->IsPlugin() || item->IsScript()))
588 CGUIDialogAddonInfo::ShowForItem(item);
589 return;
591 if (item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || !item->IsPicture())
592 return;
593 CGUIDialogPictureInfo *pictureInfo = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogPictureInfo>(WINDOW_DIALOG_PICTURE_INFO);
594 if (pictureInfo)
596 pictureInfo->SetPicture(item.get());
597 pictureInfo->Open();
601 std::string CGUIWindowPictures::GetStartFolder(const std::string &dir)
603 if (StringUtils::EqualsNoCase(dir, "plugins") ||
604 StringUtils::EqualsNoCase(dir, "addons"))
605 return "addons://sources/image/";
607 SetupShares();
608 VECSOURCES shares;
609 m_rootDir.GetSources(shares);
610 bool bIsSourceName = false;
611 int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName);
612 if (iIndex > -1)
614 if (iIndex < static_cast<int>(shares.size()) && shares[iIndex].m_iHasLock == LOCK_STATE_LOCKED)
616 CFileItem item(shares[iIndex]);
617 if (!g_passwordManager.IsItemUnlocked(&item,"pictures"))
618 return "";
620 if (bIsSourceName)
621 return shares[iIndex].strPath;
622 return dir;
624 return CGUIMediaWindow::GetStartFolder(dir);