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
23 #include "GUIWindowPictures.h"
26 #include "Application.h"
27 #include "GUIPassword.h"
28 #include "dialogs/GUIDialogMediaSource.h"
29 #include "GUIDialogPictureInfo.h"
30 #include "dialogs/GUIDialogProgress.h"
31 #include "playlists/PlayListFactory.h"
32 #include "PictureInfoLoader.h"
33 #include "guilib/GUIWindowManager.h"
34 #include "dialogs/GUIDialogOK.h"
35 #include "playlists/PlayList.h"
36 #include "settings/Settings.h"
37 #include "settings/GUISettings.h"
38 #include "utils/TimeUtils.h"
39 #include "utils/log.h"
40 #include "utils/URIUtils.h"
42 #define CONTROL_BTNVIEWASICONS 2
43 #define CONTROL_BTNSORTBY 3
44 #define CONTROL_BTNSORTASC 4
45 #define CONTROL_LABELFILES 12
48 using namespace XFILE;
49 using namespace PLAYLIST;
51 #define CONTROL_BTNSLIDESHOW 6
52 #define CONTROL_BTNSLIDESHOW_RECURSIVE 7
53 #define CONTROL_SHUFFLE 9
55 CGUIWindowPictures::CGUIWindowPictures(void)
56 : CGUIMediaWindow(WINDOW_PICTURES, "MyPics.xml")
58 m_thumbLoader.SetObserver(this);
61 CGUIWindowPictures::~CGUIWindowPictures(void)
65 bool CGUIWindowPictures::OnMessage(CGUIMessage& message)
67 switch ( message.GetMessage() )
69 case GUI_MSG_WINDOW_DEINIT:
71 if (m_thumbLoader.IsLoading())
72 m_thumbLoader.StopThread();
74 if (message.GetParam1() != WINDOW_SLIDESHOW)
81 case GUI_MSG_WINDOW_INIT:
83 // is this the first time accessing this window?
84 if (m_vecItems->m_strPath == "?" && message.GetStringParam().IsEmpty())
85 message.SetStringParam(g_settings.m_defaultPictureSource);
87 m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
89 if (message.GetParam1() != WINDOW_SLIDESHOW)
94 if (!CGUIMediaWindow::OnMessage(message))
101 case GUI_MSG_CLICKED:
103 int iControl = message.GetSenderId();
104 if (iControl == CONTROL_BTNSLIDESHOW) // Slide Show
108 else if (iControl == CONTROL_BTNSLIDESHOW_RECURSIVE) // Recursive Slide Show
110 OnSlideShowRecursive();
112 else if (iControl == CONTROL_SHUFFLE)
114 g_guiSettings.ToggleBool("slideshow.shuffle");
117 else if (m_viewControl.HasControl(iControl)) // list/thumb control
119 int iItem = m_viewControl.GetSelectedItem();
120 int iAction = message.GetParam1();
122 // iItem is checked for validity inside these routines
123 if (iAction == ACTION_DELETE_ITEM)
125 // is delete allowed?
126 if (g_guiSettings.GetBool("filelists.allowfiledeletion"))
131 else if (iAction == ACTION_PLAYER_PLAY)
133 ShowPicture(iItem, true);
136 else if (iAction == ACTION_SHOW_INFO)
145 return CGUIMediaWindow::OnMessage(message);
148 void CGUIWindowPictures::UpdateButtons()
150 CGUIMediaWindow::UpdateButtons();
152 // Update the shuffle button
153 if (g_guiSettings.GetBool("slideshow.shuffle"))
155 CGUIMessage msg2(GUI_MSG_SELECTED, GetID(), CONTROL_SHUFFLE);
156 g_windowManager.SendMessage(msg2);
160 CGUIMessage msg2(GUI_MSG_DESELECTED, GetID(), CONTROL_SHUFFLE);
161 g_windowManager.SendMessage(msg2);
164 // check we can slideshow or recursive slideshow
165 int nFolders = m_vecItems->GetFolderCount();
166 if (nFolders == m_vecItems->Size())
168 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW);
172 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW);
174 if (m_guiState.get() && !m_guiState->HideParentDirItems())
176 if (m_vecItems->Size() == 0 || nFolders == 0)
178 CONTROL_DISABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
182 CONTROL_ENABLE(CONTROL_BTNSLIDESHOW_RECURSIVE);
186 void CGUIWindowPictures::OnPrepareFileItems(CFileItemList& items)
188 for (int i=0;i<items.Size();++i )
189 if (items[i]->GetLabel().Equals("folder.jpg"))
192 if (items.GetFolderCount()==items.Size() || !g_guiSettings.GetBool("pictures.usetags"))
195 // Start the music info loader thread
196 CPictureInfoLoader loader;
197 loader.SetProgressCallback(m_dlgProgress);
200 bool bShowProgress=!g_windowManager.HasModalDialog();
201 bool bProgressVisible=false;
203 unsigned int tick=CTimeUtils::GetTimeMS();
205 while (loader.IsLoading() && m_dlgProgress && !m_dlgProgress->IsCanceled())
208 { // Do we have to init a progress dialog?
209 unsigned int elapsed=CTimeUtils::GetTimeMS()-tick;
211 if (!bProgressVisible && elapsed>1500 && m_dlgProgress)
212 { // tag loading takes more then 1.5 secs, show a progress dialog
213 CURL url(items.m_strPath);
215 m_dlgProgress->SetHeading(189);
216 m_dlgProgress->SetLine(0, 505);
217 m_dlgProgress->SetLine(1, "");
218 m_dlgProgress->SetLine(2, url.GetWithoutUserDetails());
219 m_dlgProgress->StartModal();
220 m_dlgProgress->ShowProgressBar(true);
221 bProgressVisible = true;
224 if (bProgressVisible && m_dlgProgress)
226 m_dlgProgress->Progress();
228 } // if (bShowProgress)
230 } // while (loader.IsLoading())
232 if (bProgressVisible && m_dlgProgress)
233 m_dlgProgress->Close();
236 bool CGUIWindowPictures::Update(const CStdString &strDirectory)
238 if (m_thumbLoader.IsLoading())
239 m_thumbLoader.StopThread();
241 if (!CGUIMediaWindow::Update(strDirectory))
244 m_vecItems->SetThumbnailImage("");
245 if (g_guiSettings.GetBool("pictures.generatethumbs"))
246 m_thumbLoader.Load(*m_vecItems);
247 m_vecItems->SetThumbnailImage(CPictureThumbLoader::GetCachedThumb(*m_vecItems));
252 bool CGUIWindowPictures::OnClick(int iItem)
254 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return true;
255 CFileItemPtr pItem = m_vecItems->Get(iItem);
257 if (pItem->IsCBZ() || pItem->IsCBR())
259 CStdString strComicPath;
261 URIUtils::CreateArchivePath(strComicPath, "zip", pItem->m_strPath, "");
263 URIUtils::CreateArchivePath(strComicPath, "rar", pItem->m_strPath, "");
265 OnShowPictureRecursive(strComicPath);
268 else if (CGUIMediaWindow::OnClick(iItem))
274 bool CGUIWindowPictures::OnPlayMedia(int iItem)
276 if (m_vecItems->Get(iItem)->IsVideo())
277 return CGUIMediaWindow::OnPlayMedia(iItem);
279 return ShowPicture(iItem, false);
282 bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow)
284 if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return false;
285 CFileItemPtr pItem = m_vecItems->Get(iItem);
286 CStdString strPicture = pItem->m_strPath;
290 return MEDIA_DETECT::CAutorun::PlayDisc();
293 if (pItem->m_bIsShareOrDrive)
296 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
299 if (g_application.IsPlayingVideo())
300 g_application.StopPlaying();
303 for (int i = 0; i < (int)m_vecItems->Size();++i)
305 CFileItemPtr pItem = m_vecItems->Get(i);
306 if (!pItem->m_bIsFolder && !(URIUtils::IsRAR(pItem->m_strPath) || URIUtils::IsZIP(pItem->m_strPath)) && pItem->IsPicture())
308 pSlideShow->Add(pItem.get());
312 if (pSlideShow->NumSlides() == 0)
315 pSlideShow->Select(strPicture);
318 pSlideShow->StartSlideShow(false);
320 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
325 void CGUIWindowPictures::OnShowPictureRecursive(const CStdString& strPath)
327 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
331 if (g_application.IsPlayingVideo())
332 g_application.StopPlaying();
333 pSlideShow->AddFromPath(strPath, true,
334 m_guiState->GetSortMethod(),
335 m_guiState->GetSortOrder());
336 if (pSlideShow->NumSlides())
337 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
341 void CGUIWindowPictures::OnSlideShowRecursive(const CStdString &strPicture)
343 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
346 CStdString strExtensions;
348 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
351 strExtensions = viewState->GetExtensions();
354 pSlideShow->RunSlideShow(strPicture, true,
355 g_guiSettings.GetBool("slideshow.shuffle"),false,
356 m_guiState->GetSortMethod(),
357 m_guiState->GetSortOrder(),
362 void CGUIWindowPictures::OnSlideShowRecursive()
364 CStdString strEmpty = "";
365 OnSlideShowRecursive(m_vecItems->m_strPath);
368 void CGUIWindowPictures::OnSlideShow()
370 OnSlideShow(m_vecItems->m_strPath);
373 void CGUIWindowPictures::OnSlideShow(const CStdString &strPicture)
375 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
378 CStdString strExtensions;
380 CGUIViewState* viewState=CGUIViewState::GetViewState(GetID(), items);
383 strExtensions = viewState->GetExtensions();
386 pSlideShow->RunSlideShow(strPicture, false ,false, false,
387 m_guiState->GetSortMethod(),
388 m_guiState->GetSortOrder(),
393 void CGUIWindowPictures::OnRegenerateThumbs()
395 if (m_thumbLoader.IsLoading()) return;
396 m_thumbLoader.SetRegenerateThumbs(true);
397 m_thumbLoader.Load(*m_vecItems);
400 void CGUIWindowPictures::GetContextButtons(int itemNumber, CContextButtons &buttons)
403 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
404 item = m_vecItems->Get(itemNumber);
406 if (item && !item->GetPropertyBOOL("pluginreplacecontextitems"))
408 if ( m_vecItems->IsVirtualDirectoryRoot() && item)
410 CGUIDialogContextMenu::GetContextButtons("pictures", item, buttons);
416 if (!(item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR()))
417 buttons.Add(CONTEXT_BUTTON_INFO, 13406); // picture info
418 buttons.Add(CONTEXT_BUTTON_VIEW_SLIDESHOW, item->m_bIsFolder ? 13317 : 13422); // View Slideshow
419 if (item->m_bIsFolder)
420 buttons.Add(CONTEXT_BUTTON_RECURSIVE_SLIDESHOW, 13318); // Recursive Slideshow
422 if (!m_thumbLoader.IsLoading())
423 buttons.Add(CONTEXT_BUTTON_REFRESH_THUMBS, 13315); // Create Thumbnails
424 if (g_guiSettings.GetBool("filelists.allowfiledeletion") && !item->IsReadOnly())
426 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
427 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
431 if (item->IsPlugin() || item->m_strPath.Left(9).Equals("script://") || m_vecItems->IsPlugin())
432 buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
434 buttons.Add(CONTEXT_BUTTON_GOTO_ROOT, 20128);
435 buttons.Add(CONTEXT_BUTTON_SWITCH_MEDIA, 523);
438 CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
439 if (item && !item->GetPropertyBOOL("pluginreplacecontextitems"))
440 buttons.Add(CONTEXT_BUTTON_SETTINGS, 5); // Settings
443 bool CGUIWindowPictures::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
445 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
446 if (m_vecItems->IsVirtualDirectoryRoot() && item)
448 if (CGUIDialogContextMenu::OnContextButton("pictures", item, button))
456 case CONTEXT_BUTTON_VIEW_SLIDESHOW:
457 if (item && item->m_bIsFolder)
458 OnSlideShow(item->m_strPath);
460 ShowPicture(itemNumber, true);
462 case CONTEXT_BUTTON_RECURSIVE_SLIDESHOW:
464 OnSlideShowRecursive(item->m_strPath);
466 case CONTEXT_BUTTON_INFO:
469 case CONTEXT_BUTTON_REFRESH_THUMBS:
470 OnRegenerateThumbs();
472 case CONTEXT_BUTTON_DELETE:
473 OnDeleteItem(itemNumber);
475 case CONTEXT_BUTTON_RENAME:
476 OnRenameItem(itemNumber);
478 case CONTEXT_BUTTON_SETTINGS:
479 g_windowManager.ActivateWindow(WINDOW_SETTINGS_MYPICTURES);
481 case CONTEXT_BUTTON_GOTO_ROOT:
484 case CONTEXT_BUTTON_SWITCH_MEDIA:
485 CGUIDialogContextMenu::SwitchMedia("pictures", m_vecItems->m_strPath);
490 return CGUIMediaWindow::OnContextButton(itemNumber, button);
493 void CGUIWindowPictures::OnItemLoaded(CFileItem *pItem)
495 CPictureThumbLoader::ProcessFoldersAndArchives(pItem);
498 void CGUIWindowPictures::LoadPlayList(const CStdString& strPlayList)
500 CLog::Log(LOGDEBUG,"CGUIWindowPictures::LoadPlayList()... converting playlist into slideshow: %s", strPlayList.c_str());
501 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(strPlayList));
502 if ( NULL != pPlayList.get())
504 if (!pPlayList->Load(strPlayList))
506 CGUIDialogOK::ShowAndGetInput(6, 0, 477, 0);
507 return ; //hmmm unable to load playlist?
511 CPlayList playlist = *pPlayList;
512 if (playlist.size() > 0)
515 CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
518 if (g_application.IsPlayingVideo())
519 g_application.StopPlaying();
521 // convert playlist items into slideshow items
523 for (int i = 0; i < (int)playlist.size(); ++i)
525 CFileItemPtr pItem = playlist[i];
526 //CLog::Log(LOGDEBUG,"-- playlist item: %s", pItem->m_strPath.c_str());
527 if (pItem->IsPicture() && !(pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBZ() || pItem->IsCBR()))
528 pSlideShow->Add(pItem.get());
531 // start slideshow if there are items
532 pSlideShow->StartSlideShow();
533 if (pSlideShow->NumSlides())
534 g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
538 void CGUIWindowPictures::OnInfo(int itemNumber)
540 CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr();
541 if (!item || item->m_bIsFolder || item->IsZIP() || item->IsRAR() || item->IsCBZ() || item->IsCBR() || !item->IsPicture())
543 CGUIDialogPictureInfo *pictureInfo = (CGUIDialogPictureInfo *)g_windowManager.GetWindow(WINDOW_DIALOG_PICTURE_INFO);
546 pictureInfo->SetPicture(item.get());
547 pictureInfo->DoModal();
551 CStdString CGUIWindowPictures::GetStartFolder(const CStdString &dir)
553 if (dir.Equals("Plugins") || dir.Equals("Addons"))
554 return "addons://sources/image/";
558 m_rootDir.GetSources(shares);
559 bool bIsSourceName = false;
560 int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName);
563 if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2)
565 CFileItem item(shares[iIndex]);
566 if (!g_passwordManager.IsItemUnlocked(&item,"pictures"))
570 return shares[iIndex].strPath;
573 return CGUIMediaWindow::GetStartFolder(dir);