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