add isTimeshiftActive, activateTimeshift functions
[enigma2.git] / lib / service / listboxservice.cpp
1 #include <lib/service/listboxservice.h>
2 #include <lib/service/service.h>
3 #include <lib/gdi/font.h>
4 #include <lib/dvb/epgcache.h>
5 #include <lib/dvb/pmt.h>
6 #include <lib/python/connections.h>
7
8 void eListboxServiceContent::addService(const eServiceReference &service)
9 {
10         m_list.push_back(service);
11 }
12
13 void eListboxServiceContent::FillFinished()
14 {
15         m_size = m_list.size();
16         cursorHome();
17
18         if (m_listbox)
19                 m_listbox->entryReset();
20 }
21
22 void eListboxServiceContent::setRoot(const eServiceReference &root, bool justSet)
23 {
24         m_list.clear();
25         m_root = root;
26
27         if (justSet)
28                 return;
29         assert(m_service_center);
30         
31         ePtr<iListableService> lst;
32         if (m_service_center->list(m_root, lst))
33                 eDebug("no list available!");
34         else
35                 if (lst->getContent(m_list))
36                         eDebug("getContent failed");
37
38         FillFinished();
39 }
40
41 void eListboxServiceContent::setCurrent(const eServiceReference &ref)
42 {
43         int index=0;
44         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
45                 if ( *i == ref )
46                 {
47                         m_cursor = i;
48                         m_cursor_number = index;
49                         break;
50                 }
51         if (m_listbox)
52                 m_listbox->moveSelectionTo(index);
53 }
54
55 void eListboxServiceContent::getCurrent(eServiceReference &ref)
56 {
57         if (cursorValid())
58                 ref = *m_cursor;
59         else
60                 ref = eServiceReference();
61 }
62
63 int eListboxServiceContent::getNextBeginningWithChar(char c)
64 {
65 //      printf("Char: %c\n", c);
66         int index=0;
67         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
68         {
69                 std::string text;
70                 ePtr<iStaticServiceInformation> service_info;
71                 m_service_center->info(*i, service_info);
72                 service_info->getName(*i, text);
73 //              printf("%c\n", text.c_str()[0]);
74                 int idx=0;
75                 int len=text.length();
76                 while ( idx <= len )
77                 {
78                         char cc = text[idx++];
79                         if ( cc >= 33 && cc < 127)
80                         {
81                                 if (cc == c)
82                                         return index;
83                                 break;
84                         }
85                 }
86         }
87         return 0;
88 }
89
90 void eListboxServiceContent::initMarked()
91 {
92         m_marked.clear();
93 }
94
95 void eListboxServiceContent::addMarked(const eServiceReference &ref)
96 {
97         m_marked.insert(ref);
98         if (m_listbox)
99                 m_listbox->entryChanged(lookupService(ref));
100 }
101
102 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
103 {
104         m_marked.erase(ref);
105         if (m_listbox)
106                 m_listbox->entryChanged(lookupService(ref));
107 }
108
109 int eListboxServiceContent::isMarked(const eServiceReference &ref)
110 {
111         return m_marked.find(ref) != m_marked.end();
112 }
113
114 void eListboxServiceContent::markedQueryStart()
115 {
116         m_marked_iterator = m_marked.begin();
117 }
118
119 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
120 {
121         if (m_marked_iterator == m_marked.end())
122                 return -1;
123         ref = *m_marked_iterator++;
124         return 0;
125 }
126
127 int eListboxServiceContent::lookupService(const eServiceReference &ref)
128 {
129                 /* shortcut for cursor */
130         if (ref == *m_cursor)
131                 return m_cursor_number;
132                 /* otherwise, search in the list.. */
133         int index = 0;
134         for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
135         
136                 /* this is ok even when the index was not found. */
137         return index;
138 }
139
140 void eListboxServiceContent::setVisualMode(int mode)
141 {
142         m_visual_mode = mode;
143         
144         if (m_visual_mode == visModeSimple)
145         {
146                 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
147                 m_element_font[celServiceName] = new gFont("Regular", 23);
148                 m_element_position[celServiceNumber] = eRect();
149                 m_element_font[celServiceNumber] = 0;
150                 m_element_position[celIcon] = eRect();
151                 m_element_position[celServiceInfo] = eRect();
152                 m_element_font[celServiceInfo] = 0;
153         }
154 }
155
156 void eListboxServiceContent::setElementPosition(int element, eRect where)
157 {
158         if ((element >= 0) && (element < celElements))
159                 m_element_position[element] = where;
160 }
161
162 void eListboxServiceContent::setElementFont(int element, gFont *font)
163 {
164         if ((element >= 0) && (element < celElements))
165                 m_element_font[element] = font;
166 }
167
168 void eListboxServiceContent::sort()
169 {
170         ePtr<iListableService> lst;
171         if (!m_service_center->list(m_root, lst))
172         {
173                 m_list.sort(iListableServiceCompare(lst));
174                         /* FIXME: is this really required or can we somehow keep the current entry? */
175                 cursorHome();
176                 if (m_listbox)
177                         m_listbox->entryReset();
178         }
179 }
180
181 DEFINE_REF(eListboxServiceContent);
182
183 eListboxServiceContent::eListboxServiceContent()
184         :m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_numberoffset(0)
185 {
186         cursorHome();
187         eServiceCenter::getInstance(m_service_center);
188 }
189
190 void eListboxServiceContent::cursorHome()
191 {
192         if (m_current_marked && m_saved_cursor == m_list.end())
193         {
194                 while (m_cursor_number)
195                 {
196                         std::iter_swap(m_cursor--, m_cursor);
197                         --m_cursor_number;
198                         if (m_listbox && m_cursor_number)
199                                 m_listbox->entryChanged(m_cursor_number);
200                 }
201         }
202         else
203         {
204                 m_cursor = m_list.begin();
205                 m_cursor_number = 0;
206         }
207 }
208
209 void eListboxServiceContent::cursorEnd()
210 {
211         if (m_current_marked && m_saved_cursor == m_list.end())
212         {
213                 while (m_cursor != m_list.end())
214                 {
215                         list::iterator prev = m_cursor++;
216                         ++m_cursor_number;
217                         if ( prev != m_list.end() && m_cursor != m_list.end() )
218                         {
219                                 std::iter_swap(m_cursor, prev);
220                                 if ( m_listbox )
221                                         m_listbox->entryChanged(m_cursor_number);
222                         }
223                 }
224         }
225         else
226         {
227                 m_cursor = m_list.end();
228                 m_cursor_number = m_size;
229         }
230 }
231
232 int eListboxServiceContent::setCurrentMarked(bool state)
233 {
234         bool prev = m_current_marked;
235         m_current_marked = state;
236
237         if (state != prev && m_listbox)
238         {
239                 m_listbox->entryChanged(m_cursor_number);
240                 if (!state)
241                 {
242                         ePtr<iListableService> lst;
243                         if (m_service_center->list(m_root, lst))
244                                 eDebug("no list available!");
245                         else
246                         {
247                                 ePtr<iMutableServiceList> list;
248                                 if (lst->startEdit(list))
249                                         eDebug("no editable list");
250                                 else
251                                 {
252                                         eServiceReference ref;
253                                         getCurrent(ref);
254                                         if(!ref)
255                                                 eDebug("no valid service selected");
256                                         else
257                                         {
258                                                 int pos = cursorGet();
259                                                 eDebugNoNewLine("move %s to %d ", ref.toString().c_str(), pos);
260                                                 if (list->moveService(ref, cursorGet()))
261                                                         eDebug("failed");
262                                                 else
263                                                         eDebug("ok");
264                                         }
265                                 }
266                         }
267                 }
268         }
269
270         return 0;
271 }
272
273 int eListboxServiceContent::cursorMove(int count)
274 {
275         int prev = m_cursor_number, last = m_cursor_number + count;
276         if (count > 0)
277         {
278                 while(count && m_cursor != m_list.end())
279                 {
280                         list::iterator prev_it = m_cursor++;
281                         if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
282                         {
283                                 std::iter_swap(prev_it, m_cursor);
284                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
285                                         m_listbox->entryChanged(m_cursor_number);
286                         }
287                         ++m_cursor_number;
288                         --count;
289         }
290         } else if (count < 0)
291         {
292                 while (count && m_cursor != m_list.begin())
293                 {
294                         list::iterator prev_it = m_cursor--;
295                         if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
296                         {
297                                 std::iter_swap(prev_it, m_cursor);
298                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
299                                         m_listbox->entryChanged(m_cursor_number);
300                         }
301                         --m_cursor_number;
302                         ++count;
303                 }
304         }
305         return 0;
306 }
307
308 int eListboxServiceContent::cursorValid()
309 {
310         return m_cursor != m_list.end();
311 }
312
313 int eListboxServiceContent::cursorSet(int n)
314 {
315         cursorHome();
316         cursorMove(n);
317         return 0;
318 }
319
320 int eListboxServiceContent::cursorGet()
321 {
322         return m_cursor_number;
323 }
324
325 void eListboxServiceContent::cursorSave()
326 {
327         m_saved_cursor = m_cursor;
328         m_saved_cursor_number = m_cursor_number;
329 }
330
331 void eListboxServiceContent::cursorRestore()
332 {
333         m_cursor = m_saved_cursor;
334         m_cursor_number = m_saved_cursor_number;
335         m_saved_cursor = m_list.end();
336 }
337
338 int eListboxServiceContent::size()
339 {
340         return m_size;
341 }
342         
343 void eListboxServiceContent::setSize(const eSize &size)
344 {
345         m_itemsize = size;
346         setVisualMode(m_visual_mode);
347 }
348
349 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
350 {
351         painter.clip(eRect(offset, m_itemsize));
352
353         if (m_current_marked && selected)
354                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
355         else if (cursorValid() && isMarked(*m_cursor))
356                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
357         else
358                 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
359         painter.clear();
360         
361         if (cursorValid())
362         {
363                         /* get service information */
364                 ePtr<iStaticServiceInformation> service_info;
365                 m_service_center->info(*m_cursor, service_info);
366
367                 if (m_is_playable_ignore.valid() && !service_info->isPlayable(*m_cursor, m_is_playable_ignore))
368                         painter.setForegroundColor(gRGB(0xbbbbbb));
369
370                 for (int e = 0; e < celElements; ++e)
371                 {
372                         if (!m_element_font[e])
373                                 continue;
374                         int flags=gPainter::RT_VALIGN_CENTER;
375
376                         eRect area = m_element_position[e];
377
378                         std::string text = "<n/a>";
379
380                         switch (e)
381                         {
382                         case celIcon:
383                                 // render icon here...
384                                 continue;
385                         case celServiceNumber:
386                         {
387                                 char bla[10];
388                                 sprintf(bla, "%d", m_numberoffset + m_cursor_number + 1);
389                                 text = bla;
390                                 flags|=gPainter::RT_HALIGN_RIGHT;
391                                 break;
392                         }
393                         case celServiceName:
394                         {
395                                 if (service_info)
396                                         service_info->getName(*m_cursor, text);
397                                 break;
398                         }
399                         case celServiceInfo:
400                         {
401                                 ePtr<eServiceEvent> evt;
402                                 if ( !service_info->getEvent(*m_cursor, evt) )
403                                         text = '(' + evt->getEventName() + ')';
404                                 else
405                                         continue;
406                                 break;
407                         }
408                         }
409
410                         eTextPara *para = new eTextPara(area);
411
412                         para->setFont(m_element_font[e]);
413                         para->renderString(text);
414
415                         if (e == celServiceName)
416                         {
417                                 eRect bbox = para->getBoundBox();
418                                 int name_width = bbox.width()+10;
419                                 m_element_position[celServiceInfo].setLeft(area.left()+name_width);
420                                 m_element_position[celServiceInfo].setTop(area.top());
421                                 m_element_position[celServiceInfo].setWidth(area.width()-name_width);
422                                 m_element_position[celServiceInfo].setHeight(area.height());
423                         }
424
425                         if (flags & gPainter::RT_HALIGN_RIGHT)
426                                 para->realign(eTextPara::dirRight);
427                         else if (flags & gPainter::RT_HALIGN_CENTER)
428                                 para->realign(eTextPara::dirCenter);
429                         else if (flags & gPainter::RT_HALIGN_BLOCK)
430                                 para->realign(eTextPara::dirBlock);
431
432                         ePoint offs = offset;
433
434                         if (flags & gPainter::RT_VALIGN_CENTER)
435                         {
436                                 eRect bbox = para->getBoundBox();
437                                 int vcentered_top = (area.height() - bbox.height()) / 2;
438                                 int correction = vcentered_top - bbox.top();
439                                 offs += ePoint(0, correction);
440                         }
441
442                         painter.renderPara(para, offs);
443                 }
444                 
445                 if (selected)
446                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
447         }
448         
449         painter.clippop();
450 }
451
452 void eListboxServiceContent::setIgnoreService( const eServiceReference &service )
453 {
454         m_is_playable_ignore=service;
455 }