Merge pull request #4775 from jmarshallnz/empty_episode_playcount
[vuplus_xbmc] / xbmc / dialogs / GUIDialogSelect.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "GUIDialogSelect.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "FileItem.h"
24 #include "guilib/Key.h"
25 #include "guilib/LocalizeStrings.h"
26 #include "utils/StringUtils.h"
27
28 #define CONTROL_HEADING       1
29 #define CONTROL_LIST          3
30 #define CONTROL_NUMBEROFFILES 2
31 #define CONTROL_BUTTON        5
32 #define CONTROL_DETAILS       6
33
34 CGUIDialogSelect::CGUIDialogSelect(void)
35     : CGUIDialogBoxBase(WINDOW_DIALOG_SELECT, "DialogSelect.xml")
36 {
37   m_bButtonEnabled = false;
38   m_buttonString = -1;
39   m_useDetails = false;
40   m_vecList = new CFileItemList;
41   m_selectedItems = new CFileItemList;
42   m_multiSelection = false;
43   m_iSelected = -1;
44   m_loadType = KEEP_IN_MEMORY;
45 }
46
47 CGUIDialogSelect::~CGUIDialogSelect(void)
48 {
49   delete m_vecList;
50   delete m_selectedItems;
51 }
52
53 bool CGUIDialogSelect::OnMessage(CGUIMessage& message)
54 {
55   switch ( message.GetMessage() )
56   {
57   case GUI_MSG_WINDOW_DEINIT:
58     {
59       CGUIDialog::OnMessage(message);
60       m_viewControl.Clear();
61
62       m_bButtonEnabled = false;
63       m_useDetails = false;
64       m_multiSelection = false;
65
66       // construct selected items list
67       m_selectedItems->Clear();
68       m_iSelected = -1;
69       for (int i = 0 ; i < m_vecList->Size() ; i++)
70       {
71         CFileItemPtr item = m_vecList->Get(i);
72         if (item->IsSelected())
73         {
74           m_selectedItems->Add(item);
75           if (m_iSelected == -1)
76             m_iSelected = i;
77         }
78       }
79
80       m_vecList->Clear();
81
82       m_buttonString = -1;
83       SET_CONTROL_LABEL(CONTROL_BUTTON, "");
84       return true;
85     }
86     break;
87
88   case GUI_MSG_WINDOW_INIT:
89     {
90       m_bButtonPressed = false;
91       m_bConfirmed = false;
92       CGUIDialog::OnMessage(message);
93       return true;
94     }
95     break;
96
97
98   case GUI_MSG_CLICKED:
99     {
100       int iControl = message.GetSenderId();
101       if (m_viewControl.HasControl(CONTROL_LIST))
102       {
103         int iAction = message.GetParam1();
104         if (ACTION_SELECT_ITEM == iAction || ACTION_MOUSE_LEFT_CLICK == iAction)
105         {
106           int iSelected = m_viewControl.GetSelectedItem();
107           if(iSelected >= 0 && iSelected < (int)m_vecList->Size())
108           {
109             CFileItemPtr item(m_vecList->Get(iSelected));
110             if (m_multiSelection)
111               item->Select(!item->IsSelected());
112             else
113             {
114               for (int i = 0 ; i < m_vecList->Size() ; i++)
115                 m_vecList->Get(i)->Select(false);
116               item->Select(true);
117               m_bConfirmed = true;
118               Close();
119             }
120           }
121         }
122       }
123       if (CONTROL_BUTTON == iControl)
124       {
125         m_iSelected = -1;
126         m_bButtonPressed = true;
127         if (m_multiSelection)
128           m_bConfirmed = true;
129         Close();
130       }
131     }
132     break;
133   case GUI_MSG_SETFOCUS:
134     {
135       // make sure the additional button is focused in case the list is empty
136       // (otherwise it is impossible to navigate to the additional button)
137       if (m_vecList->IsEmpty() && m_bButtonEnabled &&
138           m_viewControl.HasControl(message.GetControlId()))
139       {
140         SET_CONTROL_FOCUS(CONTROL_BUTTON, 0);
141         return true;
142       }
143       if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId())
144       {
145         m_viewControl.SetFocused();
146         return true;
147       }
148     }
149     break;
150   }
151
152   return CGUIDialog::OnMessage(message);
153 }
154
155 bool CGUIDialogSelect::OnBack(int actionID)
156 {
157   m_iSelected = -1;
158   m_selectedItems->Clear();
159   m_bConfirmed = false;
160   return CGUIDialog::OnBack(actionID);
161 }
162
163 void CGUIDialogSelect::Reset()
164 {
165   m_bButtonEnabled = false;
166   m_useDetails = false;
167   m_multiSelection = false;
168   m_iSelected = -1;
169   m_vecList->Clear();
170   m_selectedItems->Clear();
171 }
172
173 int CGUIDialogSelect::Add(const CStdString& strLabel)
174 {
175   CFileItemPtr pItem(new CFileItem(strLabel));
176   m_vecList->Add(pItem);
177   return m_vecList->Size() - 1;
178 }
179
180 void CGUIDialogSelect::Add(const CFileItemList& items)
181 {
182   for (int i=0;i<items.Size();++i)
183   {
184     CFileItemPtr item = items[i];
185     Add(item.get());
186   }
187 }
188
189 int CGUIDialogSelect::Add(const CFileItem* pItem)
190 {
191   CFileItemPtr item(new CFileItem(*pItem));
192   m_vecList->Add(item);
193   return m_vecList->Size() - 1;
194 }
195
196 void CGUIDialogSelect::SetItems(CFileItemList* pList)
197 {
198   // need to make internal copy of list to be sure dialog is owner of it
199   m_vecList->Clear();
200   if (pList)
201     m_vecList->Copy(*pList);
202 }
203
204 int CGUIDialogSelect::GetSelectedLabel() const
205 {
206   return m_iSelected;
207 }
208
209 const CFileItemPtr CGUIDialogSelect::GetSelectedItem()
210 {
211   return m_selectedItems->Size() > 0 ? m_selectedItems->Get(0) : CFileItemPtr(new CFileItem);
212 }
213
214 const CStdString& CGUIDialogSelect::GetSelectedLabelText()
215 {
216   return GetSelectedItem()->GetLabel();
217 }
218
219 const CFileItemList& CGUIDialogSelect::GetSelectedItems() const
220 {
221   return *m_selectedItems;
222 }
223
224 void CGUIDialogSelect::EnableButton(bool enable, int string)
225 {
226   m_bButtonEnabled = enable;
227   m_buttonString = string;
228
229   if (IsActive())
230     SetupButton();
231 }
232
233 bool CGUIDialogSelect::IsButtonPressed()
234 {
235   return m_bButtonPressed;
236 }
237
238 void CGUIDialogSelect::Sort(bool bSortOrder /*=true*/)
239 {
240   m_vecList->Sort(SortByLabel, bSortOrder ? SortOrderAscending : SortOrderDescending);
241 }
242
243 void CGUIDialogSelect::SetSelected(int iSelected)
244 {
245   if (iSelected < 0 || iSelected >= (int)m_vecList->Size() ||
246       m_vecList->Get(iSelected).get() == NULL) 
247     return;
248
249   // only set m_iSelected if there is no multi-select
250   // or if it doesn't have a valid value yet
251   // or if the current value is bigger than the new one
252   // so that we always focus the item nearest to the beginning of the list
253   if (!m_multiSelection || m_iSelected < 0 || m_iSelected > iSelected)
254     m_iSelected = iSelected;
255   m_vecList->Get(iSelected)->Select(true);
256   m_selectedItems->Add(m_vecList->Get(iSelected));
257 }
258
259 void CGUIDialogSelect::SetSelected(const CStdString &strSelectedLabel)
260 {
261   if (strSelectedLabel.empty())
262     return;
263
264   for (int index = 0; index < m_vecList->Size(); index++)
265   {
266     if (strSelectedLabel.Equals(m_vecList->Get(index)->GetLabel()))
267     {
268       SetSelected(index);
269       return;
270     }
271   }
272 }
273
274 void CGUIDialogSelect::SetSelected(std::vector<int> selectedIndexes)
275 {
276   if (selectedIndexes.empty())
277     return;
278
279   for (std::vector<int>::const_iterator it = selectedIndexes.begin(); it != selectedIndexes.end(); it++)
280     SetSelected(*it);
281 }
282
283 void CGUIDialogSelect::SetSelected(const std::vector<CStdString> &selectedLabels)
284 {
285   if (selectedLabels.empty())
286     return;
287
288   for (std::vector<CStdString>::const_iterator it = selectedLabels.begin(); it != selectedLabels.end(); it++)
289     SetSelected(*it);
290 }
291
292 void CGUIDialogSelect::SetUseDetails(bool useDetails)
293 {
294   m_useDetails = useDetails;
295 }
296
297 void CGUIDialogSelect::SetMultiSelection(bool multiSelection)
298 {
299   m_multiSelection = multiSelection;
300 }
301
302 CGUIControl *CGUIDialogSelect::GetFirstFocusableControl(int id)
303 {
304   if (m_viewControl.HasControl(id))
305     id = m_viewControl.GetCurrentControl();
306   return CGUIDialogBoxBase::GetFirstFocusableControl(id);
307 }
308
309 void CGUIDialogSelect::OnWindowLoaded()
310 {
311   CGUIDialogBoxBase::OnWindowLoaded();
312   m_viewControl.Reset();
313   m_viewControl.SetParentWindow(GetID());
314   m_viewControl.AddView(GetControl(CONTROL_LIST));
315   m_viewControl.AddView(GetControl(CONTROL_DETAILS));
316 }
317
318 void CGUIDialogSelect::OnInitWindow()
319 {
320   m_viewControl.SetItems(*m_vecList);
321   m_selectedItems->Clear();
322   if (m_iSelected == -1)
323   {
324     for(int i = 0 ; i < m_vecList->Size(); i++)
325     {
326       if (m_vecList->Get(i)->IsSelected())
327       {
328         m_iSelected = i;
329         break;
330       }
331     }
332   }
333   m_viewControl.SetCurrentView(m_useDetails ? CONTROL_DETAILS : CONTROL_LIST);
334
335   CStdString items = StringUtils::Format("%i %s", m_vecList->Size(), g_localizeStrings.Get(127).c_str());
336   SET_CONTROL_LABEL(CONTROL_NUMBEROFFILES, items);
337   
338   if (m_multiSelection)
339     EnableButton(true, 186);
340
341   SetupButton();
342   CGUIDialogBoxBase::OnInitWindow();
343
344   // if m_iSelected < 0 focus first item
345   m_viewControl.SetSelectedItem(std::max(m_iSelected, 0));
346 }
347
348 void CGUIDialogSelect::OnWindowUnload()
349 {
350   CGUIDialog::OnWindowUnload();
351   m_viewControl.Reset();
352 }
353
354 void CGUIDialogSelect::SetupButton()
355 {
356   if (m_bButtonEnabled)
357   {
358     SET_CONTROL_LABEL(CONTROL_BUTTON, g_localizeStrings.Get(m_buttonString));
359     SET_CONTROL_VISIBLE(CONTROL_BUTTON);
360   }
361   else
362     SET_CONTROL_HIDDEN(CONTROL_BUTTON);
363 }