2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "threads/SystemClock.h"
24 #include "GUIWindowPictures.h"
27 #include "Application.h"
28 #include "GUIPassword.h"
29 #include "dialogs/GUIDialogMediaSource.h"
30 #include "GUIDialogPictureInfo.h"
31 #include "dialogs/GUIDialogProgress.h"
32 #include "playlists/PlayListFactory.h"
33 #include "PictureInfoLoader.h"
34 #include "guilib/GUIWindowManager.h"
35 #include "dialogs/GUIDialogOK.h"
36 #include "dialogs/GUIDialogYesNo.h"
37 #include "playlists/PlayList.h"
38 #include "settings/Settings.h"
39 #include "settings/GUISettings.h"
40 #include "utils/TimeUtils.h"
41 #include "utils/log.h"
42 #include "utils/URIUtils.h"
45 #define CONTROL_BTNVIEWASICONS 2
46 #define CONTROL_BTNSORTBY 3
47 #define CONTROL_BTNSORTASC 4
48 #define CONTROL_LABELFILES 12
51 using namespace XFILE;
52 using namespace PLAYLIST;
54 #define CONTROL_BTNSLIDESHOW 6
55 #define CONTROL_BTNSLIDESHOW_RECURSIVE 7
56 #define CONTROL_SHUFFLE 9
58 CGUIWindowPictures::CGUIWindowPictures(void)
59 : CGUIMediaWindow(WINDOW_PICTURES, "MyPics.xml")
61 m_thumbLoader.SetObserver(this);
64 CGUIWindowPictures::~CGUIWindowPictures(void)
68 bool CGUIWindowPictures::OnMessage(CGUIMessage& message)
70 switch ( message.GetMessage() )
72 case GUI_MSG_WINDOW_DEINIT:
74 if (m_thumbLoader.IsLoading())
75 m_thumbLoader.StopThread();
77 if (message.GetParam1() != WINDOW_SLIDESHOW)
84 case GUI_MSG_WINDOW_INIT:
86 // is this the first time accessing this window?
87 if (m_vecItems->GetPath() == "?" && message.GetStringParam().IsEmpty())
88 message.SetStringParam(g_settings.m_defaultPictureSource);
90 m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
92 if (message.GetParam1() != WINDOW_SLIDESHOW)
97 if (!CGUIMediaWindow::OnMessage(message))
104 case GUI_MSG_CLICKED:
106 int iControl = message.GetSenderId();
107 if (iControl == CONTROL_BTNSLIDESHOW) // Slide Show
111 else if (iControl == CONTROL_BTNSLIDESHOW_RECURSIVE) // Recursive Slide Show
113 OnSlideShowRecursive();
115 else if (iControl == CONTROL_SHUFFLE)
117 g_guiSettings.ToggleBool("slideshow.shuffle");
120 else if (m_viewControl.HasControl(iControl)) // list/thumb control
122 int iItem = m_viewControl.GetSelectedItem();
123 int iAction = message.GetParam1();
125 // iItem is checked for validity inside these routines
126 if (iAction == ACTION_DELETE_ITEM)
128 // is delete allowed?
129 if (g_guiSettings.GetBool("filelists.allowfiledeletion"))
134 else if (iAction == ACTION_PLAYER_PLAY)
136 ShowPicture(iItem, true);
139 else if (iAction == ACTION_SHOW_INFO)
148 return CGUIMediaWindow::OnMessage(message);
151 void CGUIWindowPictures::UpdateButtons()
153 CGUIMediaWindow::UpdateButtons();
155 // Update the shuffle button
156 if (g_guiSettings.GetBool("slideshow.shuffle"))
158 CGUIMessage msg2(GUI_MSG_SELECTED, GetID(), CONTROL_SHUFFLE);
159 g_windowManager.SendMessage(msg2);
163 CGUIMessage msg2(GUI_MSG_DESELECTED, GetID(), CONTROL_SHUFFLE);
164 g_windowManager.SendMessage(msg2);
167 // check we can slideshow or recursive slideshow
168 int nFolders = m_vecItems->GetFolderCount();
169 if (nFolders == m_vecItems->Size())
171 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW);
175 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW);
177 if (m_guiState.get() && !m_guiState->HideParentDirItems())
179 if (m_vecItems->Size() == 0 || nFolders == 0)
181 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
185 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
189 void CGUIWindowPictures::OnPrepareFileItems(CFileItemList& items)
191 for (int i=0;i<items.Size();++i )
192 if (items[i]->GetLabel().Equals("folder.jpg"))
195 if (items.GetFolderCount()==items.Size() || !g_guiSettings.GetBool("pictures.usetags"))
198 // Start the music info loader thread
199 CPictureInfoLoader loader;
200 loader.SetProgressCallback(m_dlgProgress);
203 bool bShowProgress=!g_windowManager.HasModalDialog();
204 bool bProgressVisible=false;
206 unsigned int tick=XbmcThreads::SystemClockMillis();
208 while (loader.IsLoading() && m_dlgProgress && !m_dlgProgress->IsCanceled())
211 { // Do we have to init a progress dialog?
212 unsigned int elapsed=XbmcThreads::SystemClockMillis()-tick;
214 if (!bProgressVisible && elapsed>1500 && m_dlgProgress)
215 { // tag loading takes more then 1.5 secs, show a progress dialog
216 CURL url(items.GetPath());
218 m_dlgProgress->SetHeading(189);
219 m_dlgProgress->SetLine(0, 505);
220 m_dlgProgress->SetLine(1, "");
221 m_dlgProgress->SetLine(2, url.GetWithoutUserDetails());
222 m_dlgProgress->StartModal();
223 m_dlgProgress->ShowProgressBar(true);
224 bProgressVisible = true;
227 if (bProgressVisible && m_dlgProgress)
229 m_dlgProgress->Progress();
231 } // if (bShowProgress)
233 } // while (loader.IsLoading())
235 if (bProgressVisible && m_dlgProgress)
236 m_dlgProgress->Close();
239 bool CGUIWindowPictures::Update(const CStdString &strDirectory)
241 if (m_thumbLoader.IsLoading())
242 m_thumbLoader.StopThread();
244 if (!CGUIMediaWindow::Update(strDirectory))
247 m_vecItems->SetThumbnailImage("");
248 if (g_guiSettings.GetBool("pictures.generatethumbs"))
249 m_thumbLoader.Load(*m_vecItems);
250 m_vecItems->SetThumbnailImage(CPictureThumbLoader::GetCachedThumb(*m_vecItems));
255 bool CGUIWindowPictures::OnClick(int iItem)
257 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return true;
258 CFileItemPtr pItem = m_vecItems->Get(iItem);
260 if (pItem->IsCBZ() || pItem->IsCBR())
262 CStdString strComicPath;
264 URIUtils::CreateArchivePath(strComicPath, "zip", pItem->GetPath(), "");
266 URIUtils::CreateArchivePath(strComicPath, "rar", pItem->GetPath(), "");
268 OnShowPictureRecursive(strComicPath);
271 else if (CGUIMediaWindow::OnClick(iItem))
277 bool CGUIWindowPictures::GetDirectory(const CStdString &strDirectory, CFileItemList& items)
279 if (!CGUIMediaWindow::GetDirectory(strDirectory, items))
283 if (items.GetLabel().IsEmpty() && m_rootDir.IsSource(items.GetPath(), g_settings.GetSourcesFromType("pictures"), &label))
284 items.SetLabel(label);
289 bool CGUIWindowPictures::OnPlayMedia(int iItem)
291 if (m_vecItems->Get(iItem)->IsVideo())
292 return CGUIMediaWindow::OnPlayMedia(iItem);
294 return ShowPicture(iItem, false);
297 bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow)
299 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return false;
300 CFileItemPtr pItem = m_vecItems->Get(iItem);
301 CStdString strPicture = pItem->GetPath();
305 return MEDIA_DETECT::CAutorun::PlayDiscAskResume(m_vecItems->Get(iItem)->GetPath());
308 if (pItem->m_bIsShareOrDrive)
311 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
314 if (g_application.IsPlayingVideo())
315 g_application.StopPlaying();
318 for (int i = 0; i < (int)m_vecItems->Size();++i)
320 CFileItemPtr pItem = m_vecItems->Get(i);
321 if (!pItem->m_bIsFolder && !(URIUtils::IsRAR(pItem->GetPath()) ||
322 URIUtils::IsZIP(pItem->GetPath())) && (pItem->IsPicture() || (
323 g_guiSettings.GetBool("pictures.showvideos") &&
326 pSlideShow->Add(pItem.get());
330 if (pSlideShow->NumSlides() == 0)
333 pSlideShow->Select(strPicture);
336 pSlideShow->StartSlideShow(false);
338 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
343 void CGUIWindowPictures::OnShowPictureRecursive(const CStdString& strPath)
345 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
349 if (g_application.IsPlayingVideo())
350 g_application.StopPlaying();
351 pSlideShow->AddFromPath(strPath, true,
352 m_guiState->GetSortMethod(),
353 m_guiState->GetSortOrder());
354 if (pSlideShow->NumSlides())
355 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
359 void CGUIWindowPictures::OnSlideShowRecursive(const CStdString &strPicture)
361 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
364 CStdString strExtensions;
366 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
369 strExtensions = viewState->GetExtensions();
372 pSlideShow->RunSlideShow(strPicture, true,
373 g_guiSettings.GetBool("slideshow.shuffle"),false,
374 m_guiState->GetSortMethod(),
375 m_guiState->GetSortOrder(),
380 void CGUIWindowPictures::OnSlideShowRecursive()
382 CStdString strEmpty = "";
383 OnSlideShowRecursive(m_vecItems->GetPath());
386 void CGUIWindowPictures::OnSlideShow()
388 OnSlideShow(m_vecItems->GetPath());
391 void CGUIWindowPictures::OnSlideShow(const CStdString &strPicture)
393 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
396 CStdString strExtensions;
398 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
401 strExtensions = viewState->GetExtensions();
404 pSlideShow->RunSlideShow(strPicture, false ,false, false,
405 m_guiState->GetSortMethod(),
406 m_guiState->GetSortOrder(),
411 void CGUIWindowPictures::OnRegenerateThumbs()
413 if (m_thumbLoader.IsLoading()) return;
414 m_thumbLoader.SetRegenerateThumbs(true);
415 m_thumbLoader.Load(*m_vecItems);
418 void CGUIWindowPictures::GetContextButtons(int itemNumber, CContextButtons &buttons)
421 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
422 item = m_vecItems->Get(itemNumber);
424 if (item && !item->GetProperty("pluginreplacecontextitems").asBoolean())
426 if ( m_vecItems->IsVirtualDirectoryRoot() && item)
428 CGUIDialogContextMenu::GetContextButtons("pictures", item, buttons);
434 if (!(item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR()))
435 buttons.Add(CONTEXT_BUTTON_INFO, 13406); // picture info
436 buttons.Add(CONTEXT_BUTTON_VIEW_SLIDESHOW, item->m_bIsFolder ? 13317 : 13422); // View Slideshow
437 if (item->m_bIsFolder)
438 buttons.Add(CONTEXT_BUTTON_RECURSIVE_SLIDESHOW, 13318); // Recursive Slideshow
440 if (!m_thumbLoader.IsLoading())
441 buttons.Add(CONTEXT_BUTTON_REFRESH_THUMBS, 13315); // Create Thumbnails
442 if (g_guiSettings.GetBool("filelists.allowfiledeletion") && !item->IsReadOnly())
444 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
445 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
449 if (item->IsPlugin() || item->IsScript() || m_vecItems->IsPlugin())
450 buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
452 buttons.Add(CONTEXT_BUTTON_GOTO_ROOT, 20128);
453 buttons.Add(CONTEXT_BUTTON_SWITCH_MEDIA, 523);
456 CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
457 if (item && !item->GetProperty("pluginreplacecontextitems").asBoolean())
458 buttons.Add(CONTEXT_BUTTON_SETTINGS, 5); // Settings
461 bool CGUIWindowPictures::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
463 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
464 if (m_vecItems->IsVirtualDirectoryRoot() && item)
466 if (CGUIDialogContextMenu::OnContextButton("pictures", item, button))
474 case CONTEXT_BUTTON_VIEW_SLIDESHOW:
475 if (item && item->m_bIsFolder)
476 OnSlideShow(item->GetPath());
478 ShowPicture(itemNumber, true);
480 case CONTEXT_BUTTON_RECURSIVE_SLIDESHOW:
482 OnSlideShowRecursive(item->GetPath());
484 case CONTEXT_BUTTON_INFO:
487 case CONTEXT_BUTTON_REFRESH_THUMBS:
488 OnRegenerateThumbs();
490 case CONTEXT_BUTTON_DELETE:
491 OnDeleteItem(itemNumber);
493 case CONTEXT_BUTTON_RENAME:
494 OnRenameItem(itemNumber);
496 case CONTEXT_BUTTON_SETTINGS:
497 g_windowManager.ActivateWindow(WINDOW_SETTINGS_MYPICTURES);
499 case CONTEXT_BUTTON_GOTO_ROOT:
502 case CONTEXT_BUTTON_SWITCH_MEDIA:
503 CGUIDialogContextMenu::SwitchMedia("pictures", m_vecItems->GetPath());
508 return CGUIMediaWindow::OnContextButton(itemNumber, button);
511 void CGUIWindowPictures::OnItemLoaded(CFileItem *pItem)
513 CPictureThumbLoader::ProcessFoldersAndArchives(pItem);
516 void CGUIWindowPictures::LoadPlayList(const CStdString& strPlayList)
518 CLog::Log(LOGDEBUG,"CGUIWindowPictures::LoadPlayList()... converting playlist into slideshow: %s", strPlayList.c_str());
519 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(strPlayList));
520 if ( NULL != pPlayList.get())
522 if (!pPlayList->Load(strPlayList))
524 CGUIDialogOK::ShowAndGetInput(6, 0, 477, 0);
525 return ; //hmmm unable to load playlist?
529 CPlayList playlist = *pPlayList;
530 if (playlist.size() > 0)
533 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
536 if (g_application.IsPlayingVideo())
537 g_application.StopPlaying();
539 // convert playlist items into slideshow items
541 for (int i = 0; i < (int)playlist.size(); ++i)
543 CFileItemPtr pItem = playlist[i];
544 //CLog::Log(LOGDEBUG,"-- playlist item: %s", pItem->GetPath().c_str());
545 if (pItem->IsPicture() && !(pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBZ() || pItem->IsCBR()))
546 pSlideShow->Add(pItem.get());
549 // start slideshow if there are items
550 pSlideShow->StartSlideShow();
551 if (pSlideShow->NumSlides())
552 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
556 void CGUIWindowPictures::OnInfo(int itemNumber)
558 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
559 if (!item || item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || !item->IsPicture())
561 CGUIDialogPictureInfo *pictureInfo = (CGUIDialogPictureInfo *)g_windowManager.GetWindow(WINDOW_DIALOG_PICTURE_INFO);
564 pictureInfo->SetPicture(item.get());
565 pictureInfo->DoModal();
569 CStdString CGUIWindowPictures::GetStartFolder(const CStdString &dir)
571 if (dir.Equals("Plugins") || dir.Equals("Addons"))
572 return "addons://sources/image/";
576 m_rootDir.GetSources(shares);
577 bool bIsSourceName = false;
578 int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName);
581 if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2)
583 CFileItem item(shares[iIndex]);
584 if (!g_passwordManager.IsItemUnlocked(&item,"pictures"))
588 return shares[iIndex].strPath;
591 return CGUIMediaWindow::GetStartFolder(dir);