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"
28 #include "Application.h"
29 #include "GUIPassword.h"
30 #include "dialogs/GUIDialogMediaSource.h"
31 #include "GUIDialogPictureInfo.h"
32 #include "addons/GUIDialogAddonInfo.h"
33 #include "dialogs/GUIDialogProgress.h"
34 #include "playlists/PlayListFactory.h"
35 #include "PictureInfoLoader.h"
36 #include "guilib/GUIWindowManager.h"
37 #include "dialogs/GUIDialogOK.h"
38 #include "dialogs/GUIDialogYesNo.h"
39 #include "playlists/PlayList.h"
40 #include "settings/Settings.h"
41 #include "settings/GUISettings.h"
42 #include "utils/TimeUtils.h"
43 #include "utils/log.h"
44 #include "utils/URIUtils.h"
47 #define CONTROL_BTNVIEWASICONS 2
48 #define CONTROL_BTNSORTBY 3
49 #define CONTROL_BTNSORTASC 4
50 #define CONTROL_LABELFILES 12
53 using namespace XFILE;
54 using namespace PLAYLIST;
56 #define CONTROL_BTNSLIDESHOW 6
57 #define CONTROL_BTNSLIDESHOW_RECURSIVE 7
58 #define CONTROL_SHUFFLE 9
60 CGUIWindowPictures::CGUIWindowPictures(void)
61 : CGUIMediaWindow(WINDOW_PICTURES, "MyPics.xml")
63 m_thumbLoader.SetObserver(this);
64 m_slideShowStarted = false;
67 void CGUIWindowPictures::OnInitWindow()
69 CGUIMediaWindow::OnInitWindow();
70 if (m_slideShowStarted)
72 CGUIWindowSlideShow* wndw = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
74 if (wndw && wndw->GetCurrentSlide())
75 URIUtils::GetDirectory(wndw->GetCurrentSlide()->GetPath(),path);
76 if (path.Equals(m_vecItems->GetPath()))
78 if (wndw && wndw->GetCurrentSlide())
79 m_viewControl.SetSelectedItem(wndw->GetCurrentSlide()->GetPath());
80 m_iSelectedItem = m_viewControl.GetSelectedItem();
82 m_slideShowStarted = false;
86 CGUIWindowPictures::~CGUIWindowPictures(void)
90 bool CGUIWindowPictures::OnMessage(CGUIMessage& message)
92 switch ( message.GetMessage() )
94 case GUI_MSG_WINDOW_DEINIT:
96 if (m_thumbLoader.IsLoading())
97 m_thumbLoader.StopThread();
99 if (message.GetParam1() != WINDOW_SLIDESHOW)
106 case GUI_MSG_WINDOW_INIT:
108 // is this the first time accessing this window?
109 if (m_vecItems->GetPath() == "?" && message.GetStringParam().IsEmpty())
110 message.SetStringParam(g_settings.m_defaultPictureSource);
112 m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
114 if (message.GetParam1() != WINDOW_SLIDESHOW)
119 if (!CGUIMediaWindow::OnMessage(message))
126 case GUI_MSG_CLICKED:
128 int iControl = message.GetSenderId();
129 if (iControl == CONTROL_BTNSLIDESHOW) // Slide Show
133 else if (iControl == CONTROL_BTNSLIDESHOW_RECURSIVE) // Recursive Slide Show
135 OnSlideShowRecursive();
137 else if (iControl == CONTROL_SHUFFLE)
139 g_guiSettings.ToggleBool("slideshow.shuffle");
142 else if (m_viewControl.HasControl(iControl)) // list/thumb control
144 int iItem = m_viewControl.GetSelectedItem();
145 int iAction = message.GetParam1();
147 // iItem is checked for validity inside these routines
148 if (iAction == ACTION_DELETE_ITEM)
150 // is delete allowed?
151 if (g_guiSettings.GetBool("filelists.allowfiledeletion"))
156 else if (iAction == ACTION_PLAYER_PLAY)
158 ShowPicture(iItem, true);
161 else if (iAction == ACTION_SHOW_INFO)
170 return CGUIMediaWindow::OnMessage(message);
173 void CGUIWindowPictures::UpdateButtons()
175 CGUIMediaWindow::UpdateButtons();
177 // Update the shuffle button
178 if (g_guiSettings.GetBool("slideshow.shuffle"))
180 CGUIMessage msg2(GUI_MSG_SELECTED, GetID(), CONTROL_SHUFFLE);
181 g_windowManager.SendMessage(msg2);
185 CGUIMessage msg2(GUI_MSG_DESELECTED, GetID(), CONTROL_SHUFFLE);
186 g_windowManager.SendMessage(msg2);
189 // check we can slideshow or recursive slideshow
190 int nFolders = m_vecItems->GetFolderCount();
191 if (nFolders == m_vecItems->Size())
193 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW);
197 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW);
199 if (m_guiState.get() && !m_guiState->HideParentDirItems())
201 if (m_vecItems->Size() == 0 || nFolders == 0)
203 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
207 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
211 void CGUIWindowPictures::OnPrepareFileItems(CFileItemList& items)
213 for (int i=0;i<items.Size();++i )
214 if (items[i]->GetLabel().Equals("folder.jpg"))
217 if (items.GetFolderCount()==items.Size() || !g_guiSettings.GetBool("pictures.usetags"))
220 // Start the music info loader thread
221 CPictureInfoLoader loader;
222 loader.SetProgressCallback(m_dlgProgress);
225 bool bShowProgress=!g_windowManager.HasModalDialog();
226 bool bProgressVisible=false;
228 unsigned int tick=XbmcThreads::SystemClockMillis();
230 while (loader.IsLoading() && m_dlgProgress && !m_dlgProgress->IsCanceled())
233 { // Do we have to init a progress dialog?
234 unsigned int elapsed=XbmcThreads::SystemClockMillis()-tick;
236 if (!bProgressVisible && elapsed>1500 && m_dlgProgress)
237 { // tag loading takes more then 1.5 secs, show a progress dialog
238 CURL url(items.GetPath());
240 m_dlgProgress->SetHeading(189);
241 m_dlgProgress->SetLine(0, 505);
242 m_dlgProgress->SetLine(1, "");
243 m_dlgProgress->SetLine(2, url.GetWithoutUserDetails());
244 m_dlgProgress->StartModal();
245 m_dlgProgress->ShowProgressBar(true);
246 bProgressVisible = true;
249 if (bProgressVisible && m_dlgProgress)
251 m_dlgProgress->Progress();
253 } // if (bShowProgress)
255 } // while (loader.IsLoading())
257 if (bProgressVisible && m_dlgProgress)
258 m_dlgProgress->Close();
261 bool CGUIWindowPictures::Update(const CStdString &strDirectory)
263 if (m_thumbLoader.IsLoading())
264 m_thumbLoader.StopThread();
266 if (!CGUIMediaWindow::Update(strDirectory))
269 m_vecItems->SetThumbnailImage("");
270 if (g_guiSettings.GetBool("pictures.generatethumbs"))
271 m_thumbLoader.Load(*m_vecItems);
272 m_vecItems->SetThumbnailImage(CPictureThumbLoader::GetCachedImage(*m_vecItems, "thumb"));
277 bool CGUIWindowPictures::OnClick(int iItem)
279 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return true;
280 CFileItemPtr pItem = m_vecItems->Get(iItem);
282 if (pItem->IsCBZ() || pItem->IsCBR())
284 CStdString strComicPath;
286 URIUtils::CreateArchivePath(strComicPath, "zip", pItem->GetPath(), "");
288 URIUtils::CreateArchivePath(strComicPath, "rar", pItem->GetPath(), "");
290 OnShowPictureRecursive(strComicPath);
293 else if (CGUIMediaWindow::OnClick(iItem))
299 bool CGUIWindowPictures::GetDirectory(const CStdString &strDirectory, CFileItemList& items)
301 if (!CGUIMediaWindow::GetDirectory(strDirectory, items))
305 if (items.GetLabel().IsEmpty() && m_rootDir.IsSource(items.GetPath(), g_settings.GetSourcesFromType("pictures"), &label))
306 items.SetLabel(label);
311 bool CGUIWindowPictures::OnPlayMedia(int iItem)
313 if (m_vecItems->Get(iItem)->IsVideo())
314 return CGUIMediaWindow::OnPlayMedia(iItem);
316 return ShowPicture(iItem, false);
319 bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow)
321 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return false;
322 CFileItemPtr pItem = m_vecItems->Get(iItem);
323 CStdString strPicture = pItem->GetPath();
327 return MEDIA_DETECT::CAutorun::PlayDiscAskResume(m_vecItems->Get(iItem)->GetPath());
330 if (pItem->m_bIsShareOrDrive)
333 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
336 if (g_application.IsPlayingVideo())
337 g_application.StopPlaying();
340 for (int i = 0; i < (int)m_vecItems->Size();++i)
342 CFileItemPtr pItem = m_vecItems->Get(i);
343 if (!pItem->m_bIsFolder && !(URIUtils::IsRAR(pItem->GetPath()) ||
344 URIUtils::IsZIP(pItem->GetPath())) && (pItem->IsPicture() || (
345 g_guiSettings.GetBool("pictures.showvideos") &&
348 pSlideShow->Add(pItem.get());
352 if (pSlideShow->NumSlides() == 0)
355 pSlideShow->Select(strPicture);
358 pSlideShow->StartSlideShow(false);
360 m_slideShowStarted = true;
361 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
366 void CGUIWindowPictures::OnShowPictureRecursive(const CStdString& strPath)
368 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
372 if (g_application.IsPlayingVideo())
373 g_application.StopPlaying();
374 pSlideShow->AddFromPath(strPath, true,
375 m_guiState->GetSortMethod(),
376 m_guiState->GetSortOrder());
377 if (pSlideShow->NumSlides())
379 m_slideShowStarted = true;
380 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
385 void CGUIWindowPictures::OnSlideShowRecursive(const CStdString &strPicture)
387 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
390 CStdString strExtensions;
392 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
395 strExtensions = viewState->GetExtensions();
398 m_slideShowStarted = true;
399 pSlideShow->RunSlideShow(strPicture, true,
400 g_guiSettings.GetBool("slideshow.shuffle"),false,
401 m_guiState->GetSortMethod(),
402 m_guiState->GetSortOrder(),
407 void CGUIWindowPictures::OnSlideShowRecursive()
409 CStdString strEmpty = "";
410 OnSlideShowRecursive(m_vecItems->GetPath());
413 void CGUIWindowPictures::OnSlideShow()
415 OnSlideShow(m_vecItems->GetPath());
418 void CGUIWindowPictures::OnSlideShow(const CStdString &strPicture)
420 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
423 CStdString strExtensions;
425 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
428 strExtensions = viewState->GetExtensions();
431 m_slideShowStarted = true;
432 pSlideShow->RunSlideShow(strPicture, false ,false, false,
433 m_guiState->GetSortMethod(),
434 m_guiState->GetSortOrder(),
439 void CGUIWindowPictures::OnRegenerateThumbs()
441 if (m_thumbLoader.IsLoading()) return;
442 m_thumbLoader.SetRegenerateThumbs(true);
443 m_thumbLoader.Load(*m_vecItems);
446 void CGUIWindowPictures::GetContextButtons(int itemNumber, CContextButtons &buttons)
449 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
450 item = m_vecItems->Get(itemNumber);
452 if (item && !item->GetProperty("pluginreplacecontextitems").asBoolean())
454 if ( m_vecItems->IsVirtualDirectoryRoot() && item)
456 CGUIDialogContextMenu::GetContextButtons("pictures", item, buttons);
462 if (!m_vecItems->IsPlugin() && (item->IsPlugin() || item->IsScript()))
463 buttons.Add(CONTEXT_BUTTON_INFO, 24003); // Add-on info
464 if (!(item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || item->IsScript()))
465 buttons.Add(CONTEXT_BUTTON_INFO, 13406); // picture info
466 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 (g_guiSettings.GetBool("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_PLUGIN_SETTINGS, 1045);
482 buttons.Add(CONTEXT_BUTTON_GOTO_ROOT, 20128);
483 buttons.Add(CONTEXT_BUTTON_SWITCH_MEDIA, 523);
486 CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
487 if (item && !item->GetProperty("pluginreplacecontextitems").asBoolean())
488 buttons.Add(CONTEXT_BUTTON_SETTINGS, 5); // Settings
491 bool CGUIWindowPictures::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
493 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
494 if (m_vecItems->IsVirtualDirectoryRoot() && item)
496 if (CGUIDialogContextMenu::OnContextButton("pictures", item, button))
504 case CONTEXT_BUTTON_VIEW_SLIDESHOW:
505 if (item && item->m_bIsFolder)
506 OnSlideShow(item->GetPath());
508 ShowPicture(itemNumber, true);
510 case CONTEXT_BUTTON_RECURSIVE_SLIDESHOW:
512 OnSlideShowRecursive(item->GetPath());
514 case CONTEXT_BUTTON_INFO:
517 case CONTEXT_BUTTON_REFRESH_THUMBS:
518 OnRegenerateThumbs();
520 case CONTEXT_BUTTON_DELETE:
521 OnDeleteItem(itemNumber);
523 case CONTEXT_BUTTON_RENAME:
524 OnRenameItem(itemNumber);
526 case CONTEXT_BUTTON_SETTINGS:
527 g_windowManager.ActivateWindow(WINDOW_SETTINGS_MYPICTURES);
529 case CONTEXT_BUTTON_GOTO_ROOT:
532 case CONTEXT_BUTTON_SWITCH_MEDIA:
533 CGUIDialogContextMenu::SwitchMedia("pictures", m_vecItems->GetPath());
538 return CGUIMediaWindow::OnContextButton(itemNumber, button);
541 void CGUIWindowPictures::OnItemLoaded(CFileItem *pItem)
543 CPictureThumbLoader::ProcessFoldersAndArchives(pItem);
546 void CGUIWindowPictures::LoadPlayList(const CStdString& strPlayList)
548 CLog::Log(LOGDEBUG,"CGUIWindowPictures::LoadPlayList()... converting playlist into slideshow: %s", strPlayList.c_str());
549 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(strPlayList));
550 if ( NULL != pPlayList.get())
552 if (!pPlayList->Load(strPlayList))
554 CGUIDialogOK::ShowAndGetInput(6, 0, 477, 0);
555 return ; //hmmm unable to load playlist?
559 CPlayList playlist = *pPlayList;
560 if (playlist.size() > 0)
563 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
566 if (g_application.IsPlayingVideo())
567 g_application.StopPlaying();
569 // convert playlist items into slideshow items
571 for (int i = 0; i < (int)playlist.size(); ++i)
573 CFileItemPtr pItem = playlist[i];
574 //CLog::Log(LOGDEBUG,"-- playlist item: %s", pItem->GetPath().c_str());
575 if (pItem->IsPicture() && !(pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBZ() || pItem->IsCBR()))
576 pSlideShow->Add(pItem.get());
579 // start slideshow if there are items
580 pSlideShow->StartSlideShow();
581 if (pSlideShow->NumSlides())
582 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
586 void CGUIWindowPictures::OnInfo(int itemNumber)
588 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
591 if (!m_vecItems->IsPlugin() && (item->IsPlugin() || item->IsScript()))
593 CGUIDialogAddonInfo::ShowForItem(item);
596 if (item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || !item->IsPicture())
598 CGUIDialogPictureInfo *pictureInfo = (CGUIDialogPictureInfo *)g_windowManager.GetWindow(WINDOW_DIALOG_PICTURE_INFO);
601 pictureInfo->SetPicture(item.get());
602 pictureInfo->DoModal();
606 CStdString CGUIWindowPictures::GetStartFolder(const CStdString &dir)
608 if (dir.Equals("Plugins") || dir.Equals("Addons"))
609 return "addons://sources/image/";
613 m_rootDir.GetSources(shares);
614 bool bIsSourceName = false;
615 int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName);
618 if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2)
620 CFileItem item(shares[iIndex]);
621 if (!g_passwordManager.IsItemUnlocked(&item,"pictures"))
625 return shares[iIndex].strPath;
628 return CGUIMediaWindow::GetStartFolder(dir);