#include "../../../stdafx.h" #include "GUIPythonWindowXML.h" #include "guiwindow.h" #include "pyutil.h" #include "..\..\..\application.h" #include "..\..\..\GUIMediaWindow.h" #include "window.h" #include "control.h" #include "action.h" #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 #define CONTROL_BTNSORTASC 4 #define CONTROL_LIST 50 #define CONTROL_LABELFILES 12 #define CONTROL_VIEW_START 50 #define CONTROL_VIEW_END 59 using namespace PYXBMC; CGUIPythonWindowXML::CGUIPythonWindowXML(DWORD dwId, CStdString strXML, CStdString strFallBackPath) : CGUIWindow(dwId,strXML) { pCallbackWindow = NULL; m_actionEvent = CreateEvent(NULL, true, false, NULL); m_loadOnDemand = false; m_guiState.reset(CGUIViewState::GetViewState(GetID(), m_vecItems)); m_coordsRes = PAL_4x3; m_fallbackPath = strFallBackPath; } CGUIPythonWindowXML::~CGUIPythonWindowXML(void) { CloseHandle(m_actionEvent); } void CGUIPythonWindowXML::Update() { } bool CGUIPythonWindowXML::OnAction(const CAction &action) { // do the base class window first, and the call to python after this bool ret = CGUIWindow::OnAction(action); if(pCallbackWindow) { PyXBMCAction* inf = new PyXBMCAction; inf->pObject = Action_FromAction(action); inf->pCallbackWindow = pCallbackWindow; // aquire lock? Py_AddPendingCall(Py_XBMC_Event_OnAction, inf); PulseActionEvent(); } return ret; } void CGUIPythonWindowXML::OnWindowLoaded() { CGUIWindow::OnWindowLoaded(); m_viewControl.Reset(); m_viewControl.SetParentWindow(GetID()); for (int i = CONTROL_VIEW_START; i <= CONTROL_VIEW_END; i++) { m_viewControl.AddView(GetControl(i)); } m_viewControl.SetViewControlID(CONTROL_BTNVIEWASICONS); UpdateButtons(); } bool CGUIPythonWindowXML::OnMessage(CGUIMessage& message) { switch (message.GetMessage()) { case GUI_MSG_WINDOW_DEINIT: { m_gWindowManager.ShowOverlay(OVERLAY_STATE_SHOWN); } break; case GUI_MSG_WINDOW_INIT: { CGUIWindow::OnMessage(message); m_gWindowManager.ShowOverlay(OVERLAY_STATE_HIDDEN); PyXBMCAction* inf = new PyXBMCAction; inf->pObject = NULL; // create a new call and set it in the python queue inf->pCallbackWindow = pCallbackWindow; Py_AddPendingCall(Py_XBMC_Event_OnInit, inf); return true; } break; case GUI_MSG_SETFOCUS: { if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId()) { m_viewControl.SetFocused(); return true; } // check if our focused control is one of our category buttons int iControl=message.GetControlId(); if(pCallbackWindow) { PyXBMCAction* inf = new PyXBMCAction; inf->pObject = NULL; // create a new call and set it in the python queue inf->pCallbackWindow = pCallbackWindow; inf->controlId = iControl; // aquire lock? Py_AddPendingCall(Py_XBMC_Event_OnFocus, inf); PulseActionEvent(); } } break; case GUI_MSG_CLICKED: { int iControl=message.GetSenderId(); // Handle Sort/View internally. Scripters shouldn't use ID 2, 3 or 4. if (iControl == CONTROL_BTNVIEWASICONS) { if (m_guiState.get()) { m_guiState->SaveViewAsControl(m_viewControl.GetNextViewMode()); } UpdateButtons(); return true; } else if (iControl == CONTROL_BTNSORTASC) // sort asc { CLog::Log(LOGINFO,"WindowXML: Internal asc/dsc button not implemented"); /*if (m_guiState.get()) m_guiState->SetNextSortOrder(); UpdateFileList();*/ return true; } else if (iControl == CONTROL_BTNSORTBY) // sort by { CLog::Log(LOGINFO,"WindowXML: Internal sort button not implemented"); /*if (m_guiState.get()) m_guiState->SetNextSortMethod(); UpdateFileList();*/ return true; } if(pCallbackWindow && iControl && iControl != this->GetID()) // pCallbackWindow && != this->GetID()) { CGUIControl* controlClicked = (CGUIControl*)this->GetControl(iControl); // The old python way used to check list AND SELECITEM method or if its a button, checkmark. // Its done this way for now to allow other controls without a python version like togglebutton to still raise a onAction event if (controlClicked) // Will get problems if we the id is not on the window and we try to do GetControlType on it. So check to make sure it exists { if (controlClicked->GetControlType() == CGUIControl::GUICONTAINER_LIST && message.GetParam1() == ACTION_SELECT_ITEM || controlClicked->GetControlType() != CGUIControl::GUICONTAINER_LIST) { PyXBMCAction* inf = new PyXBMCAction; inf->pObject = NULL; // create a new call and set it in the python queue inf->pCallbackWindow = pCallbackWindow; inf->controlId = iControl; // aquire lock? Py_AddPendingCall(Py_XBMC_Event_OnClick, inf); PulseActionEvent(); } } } } break; } return CGUIWindow::OnMessage(message); } void CGUIPythonWindowXML::AddItem(CFileItem * fileItem,int intPosition) { if (intPosition == 0) m_vecItems.AddFront(fileItem); else if (intPosition == -1)m_vecItems.Add(fileItem); else { if (intPosition > m_vecItems.Size())return; CFileItemList*orgVecItems = new CFileItemList(m_vecItems); m_vecItems.Clear(); for (int i = 0; i < orgVecItems->Size(); ++i) if (i == intPosition){ m_vecItems.Add(fileItem);} m_vecItems.Add(&orgVecItems[i]); } m_viewControl.SetItems(m_vecItems); UpdateButtons(); } void CGUIPythonWindowXML::RemoveItem(int itemPosition) { m_vecItems.Remove(itemPosition); m_viewControl.SetItems(m_vecItems); UpdateButtons(); } int CGUIPythonWindowXML::GetCurrentListPosition() { return m_viewControl.GetSelectedItem(); } void CGUIPythonWindowXML::SetCurrentListPosition(int item) { return m_viewControl.SetSelectedItem(item); } CFileItem * CGUIPythonWindowXML::GetListItem(int position) { CFileItem * selectedItem = new CFileItem("Item Index doesn't exist"); if (position < m_vecItems.Size()) { selectedItem = m_vecItems[position]; } return selectedItem; } void CGUIPythonWindowXML::RefreshList() { m_viewControl.SetItems(m_vecItems); UpdateButtons(); } void CGUIPythonWindowXML::ClearList() { m_viewControl.Clear(); m_vecItems.Clear(); m_viewControl.SetItems(m_vecItems); UpdateButtons(); } void CGUIPythonWindowXML::WaitForActionEvent(DWORD timeout) { WaitForSingleObject(m_actionEvent, timeout); ResetEvent(m_actionEvent); } void CGUIPythonWindowXML::PulseActionEvent() { SetEvent(m_actionEvent); } void CGUIPythonWindowXML::Render() { string backupMediaDir = g_graphicsContext.GetMediaDir(); g_graphicsContext.SetMediaDir(m_fallbackPath+"\\skins"); CGUIWindow::Render(); g_graphicsContext.SetMediaDir(backupMediaDir); } int Py_XBMC_Event_OnClick(void* arg) { if (arg != NULL) { PyXBMCAction* action = (PyXBMCAction*)arg; PyObject_CallMethod(action->pCallbackWindow, "onClick", "i", action->controlId); delete action; } return 0; } int Py_XBMC_Event_OnFocus(void* arg) { if (arg != NULL) { PyXBMCAction* action = (PyXBMCAction*)arg; PyObject_CallMethod(action->pCallbackWindow, "onFocus", "i", action->controlId); delete action; } return 0; } int Py_XBMC_Event_OnInit(void* arg) { if (arg != NULL) { PyXBMCAction* action = (PyXBMCAction*)arg; PyObject_CallMethod(action->pCallbackWindow, "onInit",""); //, "O", &self); delete action; } return 0; } /// Functions Below here are speceifc for the 'MediaWindow' Like stuff (such as Sort and View) // \brief Prepares and adds the fileitems list/thumb panel void CGUIPythonWindowXML::OnSort() { FormatItemLabels(); SortItems(m_vecItems); } // \brief Formats item labels based on the formatting provided by guiViewState void CGUIPythonWindowXML::FormatItemLabels() { if (!m_guiState.get()) return; CGUIViewState::LABEL_MASKS labelMasks; m_guiState->GetSortMethodLabelMasks(labelMasks); } // \brief Sorts Fileitems based on the sort method and sort oder provided by guiViewState void CGUIPythonWindowXML::SortItems(CFileItemList &items) { auto_ptr guiState(CGUIViewState::GetViewState(GetID(), items)); if (guiState.get()) { items.Sort(guiState->GetSortMethod(), guiState->GetDisplaySortOrder()); // Should these items be saved to the hdd if (items.GetCacheToDisc()) items.Save(); } } // \brief Synchonize the fileitems with the playlistplayer // It recreated the playlist of the playlistplayer based // on the fileitems of the window void CGUIPythonWindowXML::UpdateFileList() { int nItem = m_viewControl.GetSelectedItem(); CFileItem* pItem = m_vecItems[nItem]; const CStdString& strSelected = pItem->m_strPath; OnSort(); UpdateButtons(); m_viewControl.SetItems(m_vecItems); m_viewControl.SetSelectedItem(strSelected); } // \brief Updates the states (enable, disable, visible...) // of the controls defined by this window // Override this function in a derived class to add new controls void CGUIPythonWindowXML::UpdateButtons() { if (m_guiState.get()) { // Update sorting controls if (m_guiState->GetDisplaySortOrder()==SORT_ORDER_NONE) { CONTROL_DISABLE(CONTROL_BTNSORTASC); } else { CONTROL_ENABLE(CONTROL_BTNSORTASC); if (m_guiState->GetDisplaySortOrder()==SORT_ORDER_ASC) { CGUIMessage msg(GUI_MSG_DESELECTED, GetID(), CONTROL_BTNSORTASC); g_graphicsContext.SendMessage(msg); } else { CGUIMessage msg(GUI_MSG_SELECTED, GetID(), CONTROL_BTNSORTASC); g_graphicsContext.SendMessage(msg); } } // Update list/thumb control m_viewControl.SetCurrentView(m_guiState->GetViewAsControl()); // Update sort by button if (m_guiState->GetSortMethod()==SORT_METHOD_NONE) { CONTROL_DISABLE(CONTROL_BTNSORTBY); } else { CONTROL_ENABLE(CONTROL_BTNSORTBY); } CStdString sortLabel; sortLabel.Format(g_localizeStrings.Get(550).c_str(), g_localizeStrings.Get(m_guiState->GetSortMethodLabel()).c_str()); SET_CONTROL_LABEL(CONTROL_BTNSORTBY, sortLabel); } int iItems = m_vecItems.Size(); if (iItems) { CFileItem* pItem = m_vecItems[0]; if (pItem->IsParentFolder()) iItems--; } CStdString items; items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str()); SET_CONTROL_LABEL(CONTROL_LABELFILES, items); } void CGUIPythonWindowXML::OnInitWindow() { // Update list/thumb control m_viewControl.SetCurrentView(DEFAULT_VIEW_LIST); m_viewControl.SetFocused(); SET_CONTROL_VISIBLE(CONTROL_LIST); CGUIWindow::OnInitWindow(); } CGUIControl *CGUIPythonWindowXML::GetFirstFocusableControl(int id) { if (m_viewControl.HasControl(id)) id = m_viewControl.GetCurrentControl(); return CGUIWindow::GetFirstFocusableControl(id); }