fixed possible nullpointer dereference in listboxservice.
[openblackhole/openblackhole-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/gdi/epng.h>
5 #include <lib/dvb/epgcache.h>
6 #include <lib/dvb/db.h>
7 #include <lib/dvb/pmt.h>
8 #include <lib/nav/core.h>
9 #include <lib/python/connections.h>
10 #include <lib/python/python.h>
11 #include <ctype.h>
12
13 ePyObject eListboxServiceContent::m_GetPiconNameFunc;
14
15 void eListboxServiceContent::addService(const eServiceReference &service, bool beforeCurrent)
16 {
17         if (beforeCurrent && m_size)
18                 m_list.insert(m_cursor, service);
19         else
20                 m_list.push_back(service);
21         if (m_size++)
22         {
23                 ++m_cursor_number;
24                 if (m_listbox)
25                         m_listbox->entryAdded(cursorResolve(m_cursor_number-1));
26         }
27         else
28         {
29                 m_cursor = m_list.begin();
30                 m_cursor_number=0;
31                 m_listbox->entryAdded(0);
32         }
33 }
34
35 void eListboxServiceContent::removeCurrent()
36 {
37         if (m_size && m_listbox)
38         {
39                 if (m_cursor_number == --m_size)
40                 {
41                         m_list.erase(m_cursor--);
42                         if (m_size)
43                         {
44                                 --m_cursor_number;
45                                 m_listbox->entryRemoved(cursorResolve(m_cursor_number+1));
46                         }
47                         else
48                                 m_listbox->entryRemoved(cursorResolve(m_cursor_number));
49                 }
50                 else
51                 {
52                         m_list.erase(m_cursor++);
53                         m_listbox->entryRemoved(cursorResolve(m_cursor_number));
54                 }
55         }
56 }
57
58 void eListboxServiceContent::FillFinished()
59 {
60         m_size = m_list.size();
61         cursorHome();
62
63         if (m_listbox)
64                 m_listbox->entryReset();
65 }
66
67 void eListboxServiceContent::setRoot(const eServiceReference &root, bool justSet)
68 {
69         m_list.clear();
70         m_cursor = m_list.end();
71         m_root = root;
72
73         if (justSet)
74         {
75                 m_lst=0;
76                 return;
77         }
78         ASSERT(m_service_center);
79
80         if (m_service_center->list(m_root, m_lst))
81                 eDebug("[eListboxServiceContent] no list available!");
82         else if (m_lst->getContent(m_list))
83                 eDebug("[eListboxServiceContent] getContent failed");
84
85         FillFinished();
86 }
87
88 bool eListboxServiceContent::setCurrent(const eServiceReference &ref)
89 {
90         int index=0;
91         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
92         {
93                 if ( *i == ref )
94                 {
95                         m_cursor = i;
96                         m_cursor_number = index;
97                         if (m_listbox)
98                         {
99                                 m_listbox->moveSelectionTo(cursorResolve(index));
100                                 return true;
101                         }
102                         break;
103                 }
104         }
105         return false;
106 }
107
108 void eListboxServiceContent::getCurrent(eServiceReference &ref)
109 {
110         if (cursorValid())
111                 ref = *m_cursor;
112         else
113                 ref = eServiceReference();
114 }
115
116 int eListboxServiceContent::getNextBeginningWithChar(char c)
117 {
118 //      printf("Char: %c\n", c);
119         int index=0;
120         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
121         {
122                 std::string text;
123                 ePtr<iStaticServiceInformation> service_info;
124                 m_service_center->info(*i, service_info);
125                 service_info->getName(*i, text);
126 //              printf("%c\n", text.c_str()[0]);
127                 int idx=0;
128                 int len=text.length();
129                 while ( idx <= len )
130                 {
131                         char cc = text[idx++];
132                         if (isprint(cc))
133                         {
134                                 if (cc == c)
135                                         return index;
136                                 break;
137                         }
138                 }
139         }
140         return 0;
141 }
142
143 int eListboxServiceContent::getPrevMarkerPos()
144 {
145         if (!m_listbox)
146                 return 0;
147         list::iterator i(m_cursor);
148         int index = m_cursor_number;
149         while (index) // Skip precending markers
150         {
151                 --i;
152                 --index;
153                 if (!(i->flags & eServiceReference::isMarker && !(i->flags & eServiceReference::isInvisible)))
154                         break;
155         }
156         while (index)
157         {
158                 --i;
159                 --index;
160                 if (i->flags & eServiceReference::isMarker && !(i->flags & eServiceReference::isInvisible))
161                         break;
162         }
163         return cursorResolve(index);
164 }
165
166 int eListboxServiceContent::getNextMarkerPos()
167 {
168         if (!m_listbox)
169                 return 0;
170         list::iterator i(m_cursor);
171         int index = m_cursor_number;
172         while (index < (m_size-1))
173         {
174                 ++i;
175                 ++index;
176                 if (i->flags & eServiceReference::isMarker && !(i->flags & eServiceReference::isInvisible))
177                         break;
178         }
179         return cursorResolve(index);
180 }
181
182 void eListboxServiceContent::initMarked()
183 {
184         m_marked.clear();
185 }
186
187 void eListboxServiceContent::addMarked(const eServiceReference &ref)
188 {
189         m_marked.insert(ref);
190         if (m_listbox)
191                 m_listbox->entryChanged(cursorResolve(lookupService(ref)));
192 }
193
194 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
195 {
196         m_marked.erase(ref);
197         if (m_listbox)
198                 m_listbox->entryChanged(cursorResolve(lookupService(ref)));
199 }
200
201 int eListboxServiceContent::isMarked(const eServiceReference &ref)
202 {
203         return m_marked.find(ref) != m_marked.end();
204 }
205
206 void eListboxServiceContent::markedQueryStart()
207 {
208         m_marked_iterator = m_marked.begin();
209 }
210
211 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
212 {
213         if (m_marked_iterator == m_marked.end())
214                 return -1;
215         ref = *m_marked_iterator++;
216         return 0;
217 }
218
219 int eListboxServiceContent::lookupService(const eServiceReference &ref)
220 {
221                 /* shortcut for cursor */
222         if (ref == *m_cursor)
223                 return m_cursor_number;
224                 /* otherwise, search in the list.. */
225         int index = 0;
226         for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
227
228                 /* this is ok even when the index was not found. */
229         return index;
230 }
231
232 void eListboxServiceContent::setVisualMode(int mode)
233 {
234         for (int i=0; i < celElements; ++i)
235         {
236                 m_element_position[i] = eRect();
237                 m_element_font[i] = 0;
238         }
239
240         m_visual_mode = mode;
241
242         if (m_visual_mode == visModeSimple)
243         {
244                 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
245                 m_element_font[celServiceName] = new gFont("Regular", 23);
246         }
247 }
248
249 void eListboxServiceContent::setElementPosition(int element, eRect where)
250 {
251         if ((element >= 0) && (element < celElements))
252                 m_element_position[element] = where;
253 }
254
255 void eListboxServiceContent::setElementFont(int element, gFont *font)
256 {
257         if ((element >= 0) && (element < celElements))
258                 m_element_font[element] = font;
259 }
260
261 void eListboxServiceContent::setPixmap(int type, ePtr<gPixmap> &pic)
262 {
263         if ((type >=0) && (type < picElements))
264                 m_pixmaps[type] = pic;
265 }
266
267 void eListboxServiceContent::sort()
268 {
269         if (!m_lst)
270                 m_service_center->list(m_root, m_lst);
271         if (m_lst)
272         {
273                 m_list.sort(iListableServiceCompare(m_lst));
274                         /* FIXME: is this really required or can we somehow keep the current entry? */
275                 cursorHome();
276                 if (m_listbox)
277                         m_listbox->entryReset();
278         }
279 }
280
281 DEFINE_REF(eListboxServiceContent);
282
283 eListboxServiceContent::eListboxServiceContent()
284         :m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_itemheight(25), m_hide_number_marker(false), m_servicetype_icon_mode(0), m_crypto_icon_mode(0), m_column_width(0), m_progressbar_height(6), m_progressbar_border_width(2), m_record_indicator_mode(0), m_nonplayable_margins(10), m_items_distances(8)
285 {
286         memset(m_color_set, 0, sizeof(m_color_set));
287         cursorHome();
288         eServiceCenter::getInstance(m_service_center);
289 }
290
291 void eListboxServiceContent::setColor(int color, gRGB &col)
292 {
293         if ((color >= 0) && (color < colorElements))
294         {
295                 m_color_set[color] = true;
296                 m_color[color] = col;
297         }
298 }
299
300 void eListboxServiceContent::swapServices(list::iterator a, list::iterator b)
301 {
302         std::iter_swap(a, b);
303         int temp = a->getChannelNum();
304         a->setChannelNum(b->getChannelNum());
305         b->setChannelNum(temp);
306 }
307
308 void eListboxServiceContent::cursorHome()
309 {
310         if (m_current_marked && m_saved_cursor == m_list.end())
311         {
312                 if (m_cursor_number >= m_size)
313                 {
314                         m_cursor_number = m_size-1;
315                         --m_cursor;
316                 }
317                 while (m_cursor_number)
318                 {
319                         swapServices(m_cursor--, m_cursor);
320                         --m_cursor_number;
321                         if (m_listbox && m_cursor_number)
322                                 m_listbox->entryChanged(cursorResolve(m_cursor_number));
323                 }
324         }
325         else
326         {
327                 m_cursor = m_list.begin();
328                 m_cursor_number = 0;
329                 while (m_cursor != m_list.end())
330                 {
331                         if (!((m_hide_number_marker && (m_cursor->flags & eServiceReference::isNumberedMarker)) || (m_cursor->flags & eServiceReference::isInvisible)))
332                                 break;
333                         m_cursor++;
334                         m_cursor_number++;
335                 }
336         }
337 }
338
339 void eListboxServiceContent::cursorEnd()
340 {
341         if (m_current_marked && m_saved_cursor == m_list.end())
342         {
343                 while (m_cursor != m_list.end())
344                 {
345                         list::iterator prev = m_cursor++;
346                         ++m_cursor_number;
347                         if ( prev != m_list.end() && m_cursor != m_list.end() )
348                         {
349                                 swapServices(m_cursor, prev);
350                                 if ( m_listbox )
351                                         m_listbox->entryChanged(cursorResolve(m_cursor_number));
352                         }
353                 }
354         }
355         else
356         {
357                 m_cursor = m_list.end();
358                 m_cursor_number = m_size;
359         }
360 }
361
362 int eListboxServiceContent::setCurrentMarked(bool state)
363 {
364         bool prev = m_current_marked;
365         m_current_marked = state;
366
367         if (state != prev && m_listbox)
368         {
369                 m_listbox->entryChanged(cursorResolve(m_cursor_number));
370                 if (!state)
371                 {
372                         if (!m_lst)
373                                 m_service_center->list(m_root, m_lst);
374                         if (m_lst)
375                         {
376                                 ePtr<iMutableServiceList> list;
377                                 if (m_lst->startEdit(list))
378                                         eDebug("[eListboxServiceContent] no editable list");
379                                 else
380                                 {
381                                         eServiceReference ref;
382                                         getCurrent(ref);
383                                         if(!ref)
384                                                 eDebug("[eListboxServiceContent] no valid service selected");
385                                         else
386                                         {
387                                                 int pos = cursorGet();
388                                                 eDebugNoNewLineStart("[eListboxServiceContent] move %s to %d ", ref.toString().c_str(), pos);
389                                                 if (list->moveService(ref, cursorGet()))
390                                                         eDebugNoNewLine("failed\n");
391                                                 else
392                                                         eDebugNoNewLine("ok\n");
393                                         }
394                                 }
395                         }
396                         else
397                                 eDebug("[eListboxServiceContent] no list available!");
398                 }
399         }
400
401         return 0;
402 }
403
404 int eListboxServiceContent::cursorMove(int count)
405 {
406         int prev = m_cursor_number, last = m_cursor_number + count;
407         if (count > 0)
408         {
409                 while(count && m_cursor != m_list.end())
410                 {
411                         list::iterator prev_it = m_cursor++;
412                         if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
413                         {
414                                 swapServices(prev_it, m_cursor);
415                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
416                                         m_listbox->entryChanged(cursorResolve(m_cursor_number));
417                         }
418                         ++m_cursor_number;
419                         if (!(m_hide_number_marker && m_cursor->flags & eServiceReference::isNumberedMarker) && !(m_cursor->flags & eServiceReference::isInvisible))
420                                 --count;
421                 }
422         }
423         else if (count < 0)
424         {
425                 while (count && m_cursor != m_list.begin())
426                 {
427                         list::iterator prev_it = m_cursor--;
428                         if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
429                         {
430                                 swapServices(prev_it, m_cursor);
431                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
432                                         m_listbox->entryChanged(cursorResolve(m_cursor_number));
433                         }
434                         --m_cursor_number;
435                         if (!(m_hide_number_marker && m_cursor->flags & eServiceReference::isNumberedMarker) && !(m_cursor->flags & eServiceReference::isInvisible))
436                                 ++count;
437                 }
438                 while (m_cursor != m_list.end())
439                 {
440                         if (!((m_hide_number_marker && (m_cursor->flags & eServiceReference::isNumberedMarker)) || (m_cursor->flags & eServiceReference::isInvisible)))
441                                 break;
442                         m_cursor++;
443                         m_cursor_number++;
444                 }
445         }
446         return 0;
447 }
448
449 int eListboxServiceContent::cursorValid()
450 {
451         return m_cursor != m_list.end();
452 }
453
454 int eListboxServiceContent::cursorSet(int n)
455 {
456         cursorHome();
457         cursorMove(n);
458         return 0;
459 }
460
461 int eListboxServiceContent::cursorResolve(int cursorPosition)
462 {
463         int strippedCursor = 0;
464         int count = 0;
465         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i)
466         {
467                 if (count == cursorPosition)
468                         break;
469                 count++;
470                 if ((m_hide_number_marker && (i->flags & eServiceReference::isNumberedMarker)) || (i->flags & eServiceReference::isInvisible))
471                         continue;
472                 strippedCursor++;
473         }
474         return strippedCursor;
475 }
476
477 int eListboxServiceContent::cursorGet()
478 {
479         return cursorResolve(m_cursor_number);
480 }
481
482 int eListboxServiceContent::currentCursorSelectable()
483 {
484         if (cursorValid())
485         {
486                 /* don't allow markers to be selected, unless we're in edit mode (because we want to provide some method to the user to remove a marker) */
487                 if (m_cursor->flags & eServiceReference::isMarker && m_marked.empty())
488                         return 0;
489                 else
490                         return 1;
491         }
492         return 0;
493 }
494
495 void eListboxServiceContent::cursorSave()
496 {
497         m_saved_cursor = m_cursor;
498         m_saved_cursor_number = m_cursor_number;
499 }
500
501 void eListboxServiceContent::cursorRestore()
502 {
503         m_cursor = m_saved_cursor;
504         m_cursor_number = m_saved_cursor_number;
505         m_saved_cursor = m_list.end();
506 }
507
508 int eListboxServiceContent::size()
509 {
510         int size = 0;
511         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i)
512         {
513                 if ((m_hide_number_marker && (i->flags & eServiceReference::isNumberedMarker)) || (i->flags & eServiceReference::isInvisible))
514                         continue;
515                 size++;
516         }
517
518         return size;
519 }
520
521 void eListboxServiceContent::setSize(const eSize &size)
522 {
523         m_itemsize = size;
524         if (m_visual_mode == visModeSimple)
525                 setVisualMode(m_visual_mode);
526 }
527
528 void eListboxServiceContent::setGetPiconNameFunc(ePyObject func)
529 {
530         if (m_GetPiconNameFunc)
531                 Py_DECREF(m_GetPiconNameFunc);
532         m_GetPiconNameFunc = func;
533         if (m_GetPiconNameFunc)
534                 Py_INCREF(m_GetPiconNameFunc);
535 }
536
537 void eListboxServiceContent::setIgnoreService( const eServiceReference &service )
538 {
539         m_is_playable_ignore=service;
540         if (m_listbox && m_listbox->isVisible())
541                 m_listbox->invalidate();
542 }
543
544 void eListboxServiceContent::setItemHeight(int height)
545 {
546         m_itemheight = height;
547         if (m_listbox)
548                 m_listbox->setItemHeight(height);
549 }
550
551 bool eListboxServiceContent::checkServiceIsRecorded(eServiceReference ref)
552 {
553         std::map<ePtr<iRecordableService>, eServiceReference, std::less<iRecordableService*> > recordedServices;
554         recordedServices = eNavigation::getInstance()->getRecordingsServices();
555         for (std::map<ePtr<iRecordableService>, eServiceReference >::iterator it = recordedServices.begin(); it != recordedServices.end(); ++it)
556         {
557                 if (ref.flags & eServiceReference::isGroup)
558                 {
559                         ePtr<iDVBChannelList> db;
560                         ePtr<eDVBResourceManager> res;
561                         eDVBResourceManager::getInstance(res);
562                         res->getChannelList(db);
563                         eBouquet *bouquet = NULL;
564                         if (!db->getBouquet(ref, bouquet))
565                         {
566                                 for (std::list<eServiceReference>::iterator i(bouquet->m_services.begin()); i != bouquet->m_services.end(); ++i)
567                                         if (*i == it->second)
568                                                 return true;
569                         }
570                 }
571                 else if (ref == it->second)
572                         return true;
573         }
574         return false;
575 }
576
577 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
578 {
579         painter.clip(eRect(offset, m_itemsize));
580
581         int marked = 0;
582
583         if (m_current_marked && selected)
584                 marked = 2;
585         else if (cursorValid() && isMarked(*m_cursor))
586         {
587                 if (selected)
588                         marked = 2;
589                 else
590                         marked = 1;
591         }
592         else
593                 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
594
595         eListboxStyle *local_style = 0;
596
597                 /* get local listbox style, if present */
598         if (m_listbox)
599                 local_style = m_listbox->getLocalStyle();
600
601         if (marked == 1)  // marked
602         {
603                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
604                 if (m_color_set[markedForeground])
605                         painter.setForegroundColor(m_color[markedForeground]);
606                 if (m_color_set[markedBackground])
607                         painter.setBackgroundColor(m_color[markedBackground]);
608         }
609         else if (marked == 2) // marked and selected
610         {
611                 style.setStyle(painter, eWindowStyle::styleListboxMarkedAndSelected);
612                 if (m_color_set[markedForegroundSelected])
613                         painter.setForegroundColor(m_color[markedForegroundSelected]);
614                 if (m_color_set[markedBackgroundSelected])
615                         painter.setBackgroundColor(m_color[markedBackgroundSelected]);
616         }
617         else if (local_style)
618         {
619                 if (selected)
620                 {
621                         /* if we have a local background color set, use that. */
622                         if (local_style->m_background_color_selected_set)
623                                 painter.setBackgroundColor(local_style->m_background_color_selected);
624                         /* same for foreground */
625                         if (local_style->m_foreground_color_selected_set)
626                                 painter.setForegroundColor(local_style->m_foreground_color_selected);
627                 }
628                 else
629                 {
630                         /* if we have a local background color set, use that. */
631                         if (local_style->m_background_color_set)
632                                 painter.setBackgroundColor(local_style->m_background_color);
633                         /* same for foreground */
634                         if (local_style->m_foreground_color_set)
635                                 painter.setForegroundColor(local_style->m_foreground_color);
636                 }
637         }
638
639         if (!local_style || !local_style->m_transparent_background)
640                 /* if we have no transparent background */
641         {
642                 /* blit background picture, if available (otherwise, clear only) */
643                 if (local_style && local_style->m_background)
644                         painter.blit(local_style->m_background, offset, eRect(), 0);
645                 else
646                         painter.clear();
647         } else
648         {
649                 if (local_style->m_background)
650                         painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
651                 else if (selected && !local_style->m_selection)
652                         painter.clear();
653         }
654
655         if (cursorValid())
656         {
657                 /* get service information */
658                 ePtr<iStaticServiceInformation> service_info;
659                 m_service_center->info(*m_cursor, service_info);
660                 eServiceReference ref = *m_cursor;
661                 bool isMarker = ref.flags & eServiceReference::isMarker;
662                 bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker);
663                 bool isRecorded = m_record_indicator_mode && isPlayable && checkServiceIsRecorded(ref);
664                 ePtr<eServiceEvent> evt;
665                 bool serviceAvail = true;
666                 bool serviceFallback = false;
667                 int isplayable_value;
668
669                 if (!marked && isPlayable && service_info && m_is_playable_ignore.valid())
670                 {
671                         isplayable_value = service_info->isPlayable(*m_cursor, m_is_playable_ignore);
672
673                         if (isplayable_value == 0) // service unavailable
674                         {
675                                 if (m_color_set[serviceNotAvail])
676                                         painter.setForegroundColor(m_color[serviceNotAvail]);
677                                 else
678                                         painter.setForegroundColor(gRGB(0xbbbbbb));
679                                 serviceAvail = false;
680                         }
681                         else
682                         {
683                                 if (isplayable_value == 2) // fallback receiver service
684                                 {
685                                         if (m_color_set[serviceItemFallback])
686                                                 painter.setForegroundColor(m_color[serviceItemFallback]);
687                                         serviceFallback = true;
688                                 }
689                         }
690                 }
691                 if (m_record_indicator_mode == 3 && isRecorded)
692                 {
693                         if (m_color_set[serviceRecorded])
694                                 painter.setForegroundColor(m_color[serviceRecorded]);
695                         else
696                                 painter.setForegroundColor(gRGB(0xb40431));
697                 }
698
699                 if (selected && local_style && local_style->m_selection)
700                         painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
701
702                 int xoffset=0;  // used as offset when painting the folder/marker symbol or the serviceevent progress
703                 time_t now = time(0);
704
705                 for (int e = 0; e != celServiceTypePixmap; ++e)
706                 {
707                         if (m_element_font[e])
708                         {
709                                 int flags=gPainter::RT_VALIGN_CENTER;
710                                 int yoffs = 0;
711                                 eRect area = m_element_position[e];
712                                 std::string text = "<n/a>";
713                                 switch (e)
714                                 {
715                                 case celServiceNumber:
716                                 {
717                                         if (area.width() <= 0)
718                                                 continue; // no point in going on if we won't paint anything
719
720                                         if( m_cursor->getChannelNum() == 0 )
721                                                 continue;
722
723                                         char buffer[15];
724                                         snprintf(buffer, sizeof(buffer), "%d", m_cursor->getChannelNum() );
725                                         text = buffer;
726                                         flags|=gPainter::RT_HALIGN_RIGHT;
727                                         if (isPlayable && serviceFallback && selected && m_color_set[serviceSelectedFallback])
728                                                 painter.setForegroundColor(m_color[serviceSelectedFallback]);
729                                         break;
730                                 }
731                                 case celServiceName:
732                                 {
733                                         if (service_info)
734                                                 service_info->getName(*m_cursor, text);
735                                         if (!isPlayable)
736                                         {
737                                                 area.setWidth(area.width() + m_element_position[celServiceEventProgressbar].width() +  m_nonplayable_margins);
738                                                 if (m_element_position[celServiceEventProgressbar].left() == 0)
739                                                         area.setLeft(0);
740                                                 if (m_element_position[celServiceNumber].width() && m_element_position[celServiceEventProgressbar].left() == m_element_position[celServiceNumber].width() +  m_nonplayable_margins)
741                                                         area.setLeft(m_element_position[celServiceNumber].width() +  m_nonplayable_margins);
742                                         }
743                                         if (!(m_record_indicator_mode == 3 && isRecorded) && isPlayable && serviceFallback && selected && m_color_set[serviceSelectedFallback])
744                                                 painter.setForegroundColor(m_color[serviceSelectedFallback]);
745                                         break;
746                                 }
747                                 case celServiceInfo:
748                                 {
749                                         if ( isPlayable && service_info && !service_info->getEvent(*m_cursor, evt) )
750                                         {
751                                                 std::string name = evt->getEventName();
752                                                 if (name.empty())
753                                                         continue;
754                                                 text = evt->getEventName();
755                                                 if (serviceAvail)
756                                                 {
757                                                         if (!selected && m_color_set[eventForeground])
758                                                                 painter.setForegroundColor(m_color[eventForeground]);
759                                                         else if (selected && m_color_set[eventForegroundSelected])
760                                                                 painter.setForegroundColor(m_color[eventForegroundSelected]);
761                                                         else
762                                                                 painter.setForegroundColor(gRGB(0xe7b53f));
763
764                                                         if (serviceFallback && !selected && m_color_set[eventForegroundFallback]) // fallback receiver
765                                                                 painter.setForegroundColor(m_color[eventForegroundFallback]);
766                                                         else if (serviceFallback && selected && m_color_set[eventForegroundSelectedFallback])
767                                                                 painter.setForegroundColor(m_color[eventForegroundSelectedFallback]);
768
769                                                 }
770                                                 break;
771                                         }
772                                         continue;
773                                 }
774                                 case celServiceEventProgressbar:
775                                 {
776                                         if (area.width() > 0 && isPlayable && service_info && !service_info->getEvent(*m_cursor, evt))
777                                         {
778                                                 char buffer[15];
779                                                 snprintf(buffer, sizeof(buffer), "%d %%", (int)(100 * (now - evt->getBeginTime()) / evt->getDuration()));
780                                                 text = buffer;
781                                                 flags|=gPainter::RT_HALIGN_RIGHT;
782                                                 break;
783                                         }
784                                         continue;
785                                 }
786                                 }
787
788                                 eRect tmp = area;
789                                 int xoffs = 0;
790                                 ePtr<gPixmap> piconPixmap;
791
792                                 if (e == celServiceName)
793                                 {
794                                         //picon stuff
795                                         if (isPlayable && PyCallable_Check(m_GetPiconNameFunc))
796                                         {
797                                                 ePyObject pArgs = PyTuple_New(1);
798                                                 PyTuple_SET_ITEM(pArgs, 0, PyString_FromString(ref.toString().c_str()));
799                                                 ePyObject pRet = PyObject_CallObject(m_GetPiconNameFunc, pArgs);
800                                                 Py_DECREF(pArgs);
801                                                 if (pRet)
802                                                 {
803                                                         if (PyString_Check(pRet))
804                                                         {
805                                                                 std::string piconFilename = PyString_AS_STRING(pRet);
806                                                                 if (!piconFilename.empty())
807                                                                         loadPNG(piconPixmap, piconFilename.c_str());
808                                                         }
809                                                         Py_DECREF(pRet);
810                                                 }
811                                         }
812                                         xoffs = xoffset;
813                                         tmp.setWidth(((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? tmp.width() : m_column_width) - xoffs);
814                                 }
815
816                                 eTextPara *para = new eTextPara(tmp);
817                                 para->setFont(m_element_font[e]);
818                                 para->renderString(text.c_str());
819
820                                 if (e == celServiceName)
821                                 {
822                                         eRect bbox = para->getBoundBox();
823
824                                         int servicenameWidth = ((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? bbox.width() : m_column_width);
825                                         m_element_position[celServiceInfo].setLeft(area.left() + servicenameWidth + m_items_distances + xoffs);
826                                         m_element_position[celServiceInfo].setTop(area.top());
827                                         m_element_position[celServiceInfo].setWidth(area.width() - (servicenameWidth + m_items_distances + xoffs));
828                                         m_element_position[celServiceInfo].setHeight(area.height());
829
830                                         if (isPlayable)
831                                         {
832                                                 //picon stuff
833                                                 if (PyCallable_Check(m_GetPiconNameFunc) and (m_column_width || piconPixmap))
834                                                 {
835                                                         eRect area = m_element_position[celServiceInfo];
836                                                         /* PIcons are usually about 100:60. Make it a
837                                                          * bit wider in case the icons are diffently
838                                                          * shaped, and to add a bit of margin between
839                                                          * icon and text. */
840                                                         const int iconWidth = area.height() * 9 / 5;
841                                                         m_element_position[celServiceInfo].setLeft(area.left() + iconWidth);
842                                                         m_element_position[celServiceInfo].setWidth(area.width() - iconWidth);
843                                                         area = m_element_position[celServiceName];
844                                                         xoffs += iconWidth;
845                                                         if (piconPixmap)
846                                                         {
847                                                                 area.moveBy(offset);
848                                                                 painter.clip(area);
849                                                                 painter.blitScale(piconPixmap,
850                                                                         eRect(area.left(), area.top(), iconWidth, area.height()),
851                                                                         area,
852                                                                         gPainter::BT_ALPHABLEND | gPainter::BT_KEEP_ASPECT_RATIO);
853                                                                 painter.clippop();
854                                                         }
855                                                 }
856
857                                                 //service type marker stuff
858                                                 if (m_servicetype_icon_mode)
859                                                 {
860                                                         int orbpos = m_cursor->getUnsignedData(4) >> 16;
861                                                         const char *filename = ref.path.c_str();
862                                                         ePtr<gPixmap> &pixmap =
863                                                                 (m_cursor->flags & eServiceReference::isGroup) ? m_pixmaps[picServiceGroup] :
864                                                                 (strstr(filename, "://")) ? m_pixmaps[picStream] :
865                                                                 (orbpos == 0xFFFF) ? m_pixmaps[picDVB_C] :
866                                                                 (orbpos == 0xEEEE) ? m_pixmaps[picDVB_T] : m_pixmaps[picDVB_S];
867                                                         if (pixmap)
868                                                         {
869                                                                 eSize pixmap_size = pixmap->size();
870                                                                 eRect area = m_element_position[celServiceInfo];
871                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
872                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
873                                                                 int offs = 0;
874                                                                 if (m_servicetype_icon_mode == 1)
875                                                                 {
876                                                                         area = m_element_position[celServiceName];
877                                                                         offs = xoffs;
878                                                                         xoffs += pixmap_size.width() + m_items_distances;
879                                                                 }
880                                                                 else if (m_crypto_icon_mode == 1 && m_pixmaps[picCrypto])
881                                                                         offs = offs + m_pixmaps[picCrypto]->size().width() + m_items_distances;
882                                                                 int correction = (area.height() - pixmap_size.height()) / 2;
883                                                                 area.moveBy(offset);
884                                                                 painter.clip(area);
885                                                                 painter.blit(pixmap, ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
886                                                                 painter.clippop();
887                                                         }
888                                                 }
889
890                                                 //crypto icon stuff
891                                                 if (m_crypto_icon_mode && m_pixmaps[picCrypto])
892                                                 {
893                                                         eSize pixmap_size = m_pixmaps[picCrypto]->size();
894                                                         eRect area = m_element_position[celServiceInfo];
895                                                         int offs = 0;
896                                                         if (m_crypto_icon_mode == 1)
897                                                         {
898                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
899                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
900                                                                 area = m_element_position[celServiceName];
901                                                                 offs = xoffs;
902                                                                 xoffs += pixmap_size.width() + m_items_distances;
903                                                         }
904                                                         int correction = (area.height() - pixmap_size.height()) / 2;
905                                                         area.moveBy(offset);
906                                                         if (service_info->isCrypted())
907                                                         {
908                                                                 if (m_crypto_icon_mode == 2)
909                                                                 {
910                                                                         m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
911                                                                         m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
912                                                                 }
913                                                                 painter.clip(area);
914                                                                 painter.blit(m_pixmaps[picCrypto], ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
915                                                                 painter.clippop();
916                                                         }
917                                                 }
918
919                                                 //record icon stuff
920                                                 if (isRecorded && m_record_indicator_mode < 3 && m_pixmaps[picRecord])
921                                                 {
922                                                         eSize pixmap_size = m_pixmaps[picRecord]->size();
923                                                         eRect area = m_element_position[celServiceInfo];
924                                                         int offs = 0;
925                                                         if (m_record_indicator_mode == 1)
926                                                         {
927                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
928                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
929                                                                 area = m_element_position[celServiceName];
930                                                                 offs = xoffs;
931                                                                 xoffs += pixmap_size.width() + m_items_distances;
932                                                         }
933                                                         int correction = (area.height() - pixmap_size.height()) / 2;
934                                                         area.moveBy(offset);
935                                                         if (m_record_indicator_mode == 2)
936                                                         {
937                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
938                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
939                                                         }
940                                                         painter.clip(area);
941                                                         painter.blit(m_pixmaps[picRecord], ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
942                                                         painter.clippop();
943                                                 }
944                                         }
945                                 }
946
947                                 if (flags & gPainter::RT_HALIGN_RIGHT)
948                                         para->realign(eTextPara::dirRight);
949                                 else if (flags & gPainter::RT_HALIGN_CENTER)
950                                         para->realign(eTextPara::dirCenter);
951                                 else if (flags & gPainter::RT_HALIGN_BLOCK)
952                                         para->realign(eTextPara::dirBlock);
953
954                                 if (flags & gPainter::RT_VALIGN_CENTER)
955                                 {
956                                         eRect bbox = para->getBoundBox();
957                                         yoffs = (area.height() - bbox.height()) / 2 - bbox.top();
958                                 }
959
960                                 painter.renderPara(para, offset+ePoint(xoffs, yoffs));
961                         }
962                         else if ((e == celFolderPixmap && m_cursor->flags & eServiceReference::isDirectory) ||
963                                 (e == celMarkerPixmap && m_cursor->flags & eServiceReference::isMarker &&
964                                 !(m_cursor->flags & eServiceReference::isNumberedMarker)))
965                         {
966                                 ePtr<gPixmap> &pixmap =
967                                         (e == celFolderPixmap) ? m_pixmaps[picFolder] : m_pixmaps[picMarker];
968                                 if (pixmap)
969                                 {
970                                         eSize pixmap_size = pixmap->size();
971                                         eRect area;
972                                         if (e == celFolderPixmap || m_element_position[celServiceNumber].width() < pixmap_size.width())
973                                         {
974                                                 area = m_element_position[celServiceName];
975                                                 if (m_element_position[celServiceEventProgressbar].left() == 0)
976                                                         area.setLeft(0);
977                                                 xoffset = pixmap_size.width() + m_items_distances;                      
978                                         }
979                                         else
980                                                 area = m_element_position[celServiceNumber];
981                                         int correction = (area.height() - pixmap_size.height()) / 2;
982                                         area.moveBy(offset);
983                                         painter.clip(area);
984                                         painter.blit(pixmap, ePoint(area.left(), offset.y() + correction), area, gPainter::BT_ALPHATEST);
985                                         painter.clippop();
986                                 }
987                         }
988                 }
989                 if (selected && (!local_style || !local_style->m_selection))
990                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
991
992                 eRect area = m_element_position[celServiceEventProgressbar];
993                 if (area.width() > 0 && evt && !m_element_font[celServiceEventProgressbar])
994                 {
995                         int pb_xpos = area.left();
996                         int pb_ypos = offset.y() + (m_itemsize.height() - m_progressbar_height - 2 * m_progressbar_border_width) / 2;
997                         int pb_width = area.width()- 2 * m_progressbar_border_width;
998                         gRGB ProgressbarBorderColor = 0xdfdfdf;
999                         int evt_done = pb_width * (now - evt->getBeginTime()) / evt->getDuration();
1000
1001                         // the progress data...
1002                         eRect tmp = eRect(pb_xpos + m_progressbar_border_width, pb_ypos + m_progressbar_border_width, evt_done, m_progressbar_height);
1003                         ePtr<gPixmap> &pixmap = m_pixmaps[picServiceEventProgressbar];
1004                         if (pixmap) {
1005                                 painter.clip(tmp);
1006                                 painter.blit(pixmap, ePoint(pb_xpos + m_progressbar_border_width, pb_ypos + m_progressbar_border_width), tmp, gPainter::BT_ALPHATEST);
1007                                 painter.clippop();
1008                         }
1009                         else {
1010                                 if (!selected && m_color_set[serviceEventProgressbarColor])
1011                                         painter.setForegroundColor(m_color[serviceEventProgressbarColor]);
1012                                 else if (selected && m_color_set[serviceEventProgressbarColorSelected])
1013                                         painter.setForegroundColor(m_color[serviceEventProgressbarColorSelected]);
1014                                 painter.fill(tmp);
1015                         }
1016
1017                         // the progressbar border
1018                         if (!selected)  {
1019                                 if (m_color_set[serviceEventProgressbarBorderColor])
1020                                         ProgressbarBorderColor = m_color[serviceEventProgressbarBorderColor];
1021                                 else if (m_color_set[eventborderForeground])
1022                                         ProgressbarBorderColor = m_color[eventborderForeground];
1023                         }
1024                         else { /* !selected */
1025                                 if (m_color_set[serviceEventProgressbarBorderColorSelected])
1026                                         ProgressbarBorderColor = m_color[serviceEventProgressbarBorderColorSelected];
1027                                 else if (m_color_set[eventborderForegroundSelected])
1028                                         ProgressbarBorderColor = m_color[eventborderForegroundSelected];
1029                         }
1030                         painter.setForegroundColor(ProgressbarBorderColor);
1031
1032                         painter.fill(eRect(pb_xpos, pb_ypos, pb_width + 2 * m_progressbar_border_width,  m_progressbar_border_width));
1033                         painter.fill(eRect(pb_xpos, pb_ypos + m_progressbar_border_width + m_progressbar_height, pb_width + 2 * m_progressbar_border_width,  m_progressbar_border_width));
1034                         painter.fill(eRect(pb_xpos, pb_ypos + m_progressbar_border_width, m_progressbar_border_width, m_progressbar_height));
1035                         painter.fill(eRect(pb_xpos + m_progressbar_border_width + pb_width, pb_ypos + m_progressbar_border_width, m_progressbar_border_width, m_progressbar_height));
1036                 }
1037         }
1038         painter.clippop();
1039 }