/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* .
*
*/
#include "GUIViewState.h"
#include "music/GUIViewStateMusic.h"
#include "video/GUIViewStateVideo.h"
#include "pictures/GUIViewStatePictures.h"
#include "programs/GUIViewStatePrograms.h"
#include "GUIViewStateScripts.h"
#include "GUIViewStateGameSaves.h"
#include "PlayListPlayer.h"
#include "utils/URIUtils.h"
#include "URL.h"
#include "GUIPassword.h"
#include "GUIBaseContainer.h" // for VIEW_TYPE_*
#include "ViewDatabase.h"
#include "AutoSwitch.h"
#include "GUIWindowManager.h"
#include "ViewState.h"
#include "settings/Settings.h"
#include "FileItem.h"
using namespace std;
CStdString CGUIViewState::m_strPlaylistDirectory;
VECSOURCES CGUIViewState::m_sources;
CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& items)
{
if (windowId == 0)
return GetViewState(g_windowManager.GetActiveWindow(),items);
const CURL url=items.GetAsUrl();
if (items.HasSortDetails())
return new CGUIViewStateFromItems(items);
if (url.GetProtocol()=="musicdb")
return new CGUIViewStateMusicDatabase(items);
if (url.GetProtocol()=="musicsearch")
return new CGUIViewStateMusicSearch(items);
if (items.IsSmartPlayList() || url.GetProtocol() == "upnp")
{
if (items.GetContent() == "songs")
return new CGUIViewStateMusicSmartPlaylist(items);
else if (items.GetContent() == "albums")
return new CGUIViewStateMusicSmartPlaylist(items);
else if (items.GetContent() == "musicvideos") // TODO: Update this
return new CGUIViewStateMusicSmartPlaylist(items);
else if (items.GetContent() == "tvshows")
return new CGUIViewStateVideoTVShows(items);
else if (items.GetContent() == "episodes")
return new CGUIViewStateVideoEpisodes(items);
else if (items.GetContent() == "movies")
return new CGUIViewStateVideoMovies(items);
}
if (items.IsPlayList())
return new CGUIViewStateMusicPlaylist(items);
if (url.GetProtocol() == "shout")
return new CGUIViewStateMusicShoutcast(items);
if (url.GetProtocol() == "lastfm")
return new CGUIViewStateMusicLastFM(items);
if (items.GetPath() == "special://musicplaylists/")
return new CGUIViewStateWindowMusicSongs(items);
if (windowId==WINDOW_MUSIC_NAV)
return new CGUIViewStateWindowMusicNav(items);
if (windowId==WINDOW_MUSIC_FILES)
return new CGUIViewStateWindowMusicSongs(items);
if (windowId==WINDOW_MUSIC_PLAYLIST)
return new CGUIViewStateWindowMusicPlaylist(items);
if (windowId==WINDOW_MUSIC_PLAYLIST_EDITOR)
return new CGUIViewStateWindowMusicSongs(items);
if (windowId==WINDOW_VIDEO_FILES)
return new CGUIViewStateWindowVideoFiles(items);
if (windowId==WINDOW_VIDEO_NAV)
return new CGUIViewStateWindowVideoNav(items);
if (windowId==WINDOW_VIDEO_PLAYLIST)
return new CGUIViewStateWindowVideoPlaylist(items);
if (windowId==WINDOW_SCRIPTS)
return new CGUIViewStateWindowScripts(items);
if (windowId==WINDOW_GAMESAVES)
return new CGUIViewStateWindowGameSaves(items);
if (windowId==WINDOW_PICTURES)
return new CGUIViewStateWindowPictures(items);
if (windowId==WINDOW_PROGRAMS)
return new CGUIViewStateWindowPrograms(items);
// Use as fallback/default
return new CGUIViewStateGeneral(items);
}
CGUIViewState::CGUIViewState(const CFileItemList& items) : m_items(items)
{
m_currentViewAsControl=0;
m_currentSortMethod=0;
m_sortOrder=SORT_ORDER_ASC;
}
CGUIViewState::~CGUIViewState()
{
}
SORT_ORDER CGUIViewState::GetDisplaySortOrder() const
{
// we actually treat some sort orders in reverse, so that we can have
// the one sort order variable to save but it can be ascending usually,
// and descending for the views which should be usually descending.
// default sort order for date, size, program count + rating is reversed
SORT_METHOD sortMethod = GetSortMethod();
if (sortMethod == SORT_METHOD_DATE || sortMethod == SORT_METHOD_SIZE ||
sortMethod == SORT_METHOD_VIDEO_RATING || sortMethod == SORT_METHOD_PROGRAM_COUNT ||
sortMethod == SORT_METHOD_SONG_RATING || sortMethod == SORT_METHOD_BITRATE || sortMethod == SORT_METHOD_LISTENERS)
{
if (m_sortOrder == SORT_ORDER_ASC) return SORT_ORDER_DESC;
if (m_sortOrder == SORT_ORDER_DESC) return SORT_ORDER_ASC;
}
return m_sortOrder;
}
SORT_ORDER CGUIViewState::SetNextSortOrder()
{
if (m_sortOrder==SORT_ORDER_ASC)
SetSortOrder(SORT_ORDER_DESC);
else
SetSortOrder(SORT_ORDER_ASC);
SaveViewState();
return m_sortOrder;
}
int CGUIViewState::GetViewAsControl() const
{
return m_currentViewAsControl;
}
void CGUIViewState::SetViewAsControl(int viewAsControl)
{
if (viewAsControl == DEFAULT_VIEW_AUTO)
m_currentViewAsControl = CAutoSwitch::GetView(m_items);
else
m_currentViewAsControl = viewAsControl;
}
void CGUIViewState::SaveViewAsControl(int viewAsControl)
{
SetViewAsControl(viewAsControl);
SaveViewState();
}
SORT_METHOD CGUIViewState::GetSortMethod() const
{
if (m_currentSortMethod>=0 && m_currentSortMethod<(int)m_sortMethods.size())
return m_sortMethods[m_currentSortMethod].m_sortMethod;
return SORT_METHOD_NONE;
}
int CGUIViewState::GetSortMethodLabel() const
{
if (m_currentSortMethod>=0 && m_currentSortMethod<(int)m_sortMethods.size())
return m_sortMethods[m_currentSortMethod].m_buttonLabel;
return 103; // Sort By: Name
}
void CGUIViewState::GetSortMethods(vector< pair > &sortMethods) const
{
for (unsigned int i = 0; i < m_sortMethods.size(); i++)
sortMethods.push_back(make_pair(m_sortMethods[i].m_sortMethod, m_sortMethods[i].m_buttonLabel));
}
void CGUIViewState::GetSortMethodLabelMasks(LABEL_MASKS& masks) const
{
if (m_currentSortMethod>=0 && m_currentSortMethod<(int)m_sortMethods.size())
{
masks=m_sortMethods[m_currentSortMethod].m_labelMasks;
return;
}
masks.m_strLabelFile.Empty();
masks.m_strLabel2File.Empty();
masks.m_strLabelFolder.Empty();
masks.m_strLabel2Folder.Empty();
return;
}
void CGUIViewState::AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, LABEL_MASKS labelmasks)
{
SORT_METHOD_DETAILS sort;
sort.m_sortMethod=sortMethod;
sort.m_buttonLabel=buttonLabel;
sort.m_labelMasks=labelmasks;
m_sortMethods.push_back(sort);
}
void CGUIViewState::SetCurrentSortMethod(int method)
{
bool ignoreThe = g_guiSettings.GetBool("filelists.ignorethewhensorting");
if (method < SORT_METHOD_NONE || method >= SORT_METHOD_MAX)
return; // invalid
// compensate for "Ignore The" options to make it easier on the skin
if (ignoreThe && (method == SORT_METHOD_LABEL || method == SORT_METHOD_TITLE || method == SORT_METHOD_ARTIST || method == SORT_METHOD_ALBUM || method == SORT_METHOD_STUDIO || method == SORT_METHOD_VIDEO_SORT_TITLE))
method++;
else if (!ignoreThe && (method == SORT_METHOD_LABEL_IGNORE_THE || method == SORT_METHOD_TITLE_IGNORE_THE || method == SORT_METHOD_ARTIST_IGNORE_THE || method==SORT_METHOD_ALBUM_IGNORE_THE || method == SORT_METHOD_STUDIO_IGNORE_THE || method == SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE))
method--;
SetSortMethod((SORT_METHOD)method);
SaveViewState();
}
void CGUIViewState::SetSortMethod(SORT_METHOD sortMethod)
{
for (int i=0; i<(int)m_sortMethods.size(); ++i)
{
if (m_sortMethods[i].m_sortMethod==sortMethod)
{
m_currentSortMethod=i;
break;
}
}
}
SORT_METHOD CGUIViewState::SetNextSortMethod(int direction /* = 1 */)
{
m_currentSortMethod += direction;
if (m_currentSortMethod >= (int)m_sortMethods.size())
m_currentSortMethod=0;
if (m_currentSortMethod < 0)
m_currentSortMethod = m_sortMethods.size() ? (int)m_sortMethods.size() - 1 : 0;
SaveViewState();
return GetSortMethod();
}
bool CGUIViewState::HideExtensions()
{
return !g_guiSettings.GetBool("filelists.showextensions");
}
bool CGUIViewState::HideParentDirItems()
{
return !g_guiSettings.GetBool("filelists.showparentdiritems");
}
bool CGUIViewState::DisableAddSourceButtons()
{
if (g_settings.GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser)
return !g_guiSettings.GetBool("filelists.showaddsourcebuttons");
return true;
}
int CGUIViewState::GetPlaylist()
{
return PLAYLIST_NONE;
}
const CStdString& CGUIViewState::GetPlaylistDirectory()
{
return m_strPlaylistDirectory;
}
void CGUIViewState::SetPlaylistDirectory(const CStdString& strDirectory)
{
m_strPlaylistDirectory=strDirectory;
URIUtils::RemoveSlashAtEnd(m_strPlaylistDirectory);
}
bool CGUIViewState::IsCurrentPlaylistDirectory(const CStdString& strDirectory)
{
if (g_playlistPlayer.GetCurrentPlaylist()!=GetPlaylist())
return false;
CStdString strDir=strDirectory;
URIUtils::RemoveSlashAtEnd(strDir);
return (m_strPlaylistDirectory==strDir);
}
bool CGUIViewState::UnrollArchives()
{
return false;
}
bool CGUIViewState::AutoPlayNextItem()
{
return false;
}
CStdString CGUIViewState::GetLockType()
{
return "";
}
CStdString CGUIViewState::GetExtensions()
{
return "";
}
VECSOURCES& CGUIViewState::GetSources()
{
return m_sources;
}
CGUIViewStateGeneral::CGUIViewStateGeneral(const CFileItemList& items) : CGUIViewState(items)
{
AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%F", "%I", "%L", "")); // Filename, size | Foldername, empty
SetSortMethod(SORT_METHOD_LABEL);
SetViewAsControl(DEFAULT_VIEW_LIST);
SetSortOrder(SORT_ORDER_ASC);
}
void CGUIViewState::SetSortOrder(SORT_ORDER sortOrder)
{
if (GetSortMethod() == SORT_METHOD_NONE)
m_sortOrder = SORT_ORDER_NONE;
else if (sortOrder == SORT_ORDER_NONE)
m_sortOrder = SORT_ORDER_ASC;
else
m_sortOrder = sortOrder;
}
void CGUIViewState::LoadViewState(const CStdString &path, int windowID)
{ // get our view state from the db
CViewDatabase db;
if (db.Open())
{
CViewState state;
if (db.GetViewState(path, windowID, state))
{
SetViewAsControl(state.m_viewMode);
SetSortMethod(state.m_sortMethod);
SetSortOrder(state.m_sortOrder);
}
db.Close();
}
}
void CGUIViewState::SaveViewToDb(const CStdString &path, int windowID, CViewState *viewState)
{
CViewDatabase db;
if (db.Open())
{
CViewState state(m_currentViewAsControl, GetSortMethod(), m_sortOrder);
if (viewState)
*viewState = state;
db.SetViewState(path, windowID, state);
db.Close();
if (viewState)
g_settings.Save();
}
}
CGUIViewStateFromItems::CGUIViewStateFromItems(const CFileItemList &items) : CGUIViewState(items)
{
const vector &details = items.GetSortDetails();
for (unsigned int i = 0; i < details.size(); i++)
{
const SORT_METHOD_DETAILS sort = details[i];
AddSortMethod(sort.m_sortMethod, sort.m_buttonLabel, sort.m_labelMasks);
}
// TODO: Should default sort/view mode be specified?
m_currentSortMethod = 0;
SetViewAsControl(DEFAULT_VIEW_LIST);
SetSortOrder(SORT_ORDER_ASC);
LoadViewState(items.GetPath(), g_windowManager.GetActiveWindow());
}
void CGUIViewStateFromItems::SaveViewState()
{
SaveViewToDb(m_items.GetPath(), g_windowManager.GetActiveWindow());
}