f9afd2d79a9e3de0d2d413e75c6bf7130ddb27e9
[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=0;
564                         db->getBouquet(ref, bouquet);
565                         for (std::list<eServiceReference>::iterator i(bouquet->m_services.begin()); i != bouquet->m_services.end(); ++i)
566                                 if (*i == it->second)
567                                         return true;
568                 }
569                 else if (ref == it->second)
570                         return true;
571         }
572         return false;
573 }
574
575 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
576 {
577         painter.clip(eRect(offset, m_itemsize));
578
579         int marked = 0;
580
581         if (m_current_marked && selected)
582                 marked = 2;
583         else if (cursorValid() && isMarked(*m_cursor))
584         {
585                 if (selected)
586                         marked = 2;
587                 else
588                         marked = 1;
589         }
590         else
591                 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
592
593         eListboxStyle *local_style = 0;
594
595                 /* get local listbox style, if present */
596         if (m_listbox)
597                 local_style = m_listbox->getLocalStyle();
598
599         if (marked == 1)  // marked
600         {
601                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
602                 if (m_color_set[markedForeground])
603                         painter.setForegroundColor(m_color[markedForeground]);
604                 if (m_color_set[markedBackground])
605                         painter.setBackgroundColor(m_color[markedBackground]);
606         }
607         else if (marked == 2) // marked and selected
608         {
609                 style.setStyle(painter, eWindowStyle::styleListboxMarkedAndSelected);
610                 if (m_color_set[markedForegroundSelected])
611                         painter.setForegroundColor(m_color[markedForegroundSelected]);
612                 if (m_color_set[markedBackgroundSelected])
613                         painter.setBackgroundColor(m_color[markedBackgroundSelected]);
614         }
615         else if (local_style)
616         {
617                 if (selected)
618                 {
619                         /* if we have a local background color set, use that. */
620                         if (local_style->m_background_color_selected_set)
621                                 painter.setBackgroundColor(local_style->m_background_color_selected);
622                         /* same for foreground */
623                         if (local_style->m_foreground_color_selected_set)
624                                 painter.setForegroundColor(local_style->m_foreground_color_selected);
625                 }
626                 else
627                 {
628                         /* if we have a local background color set, use that. */
629                         if (local_style->m_background_color_set)
630                                 painter.setBackgroundColor(local_style->m_background_color);
631                         /* same for foreground */
632                         if (local_style->m_foreground_color_set)
633                                 painter.setForegroundColor(local_style->m_foreground_color);
634                 }
635         }
636
637         if (!local_style || !local_style->m_transparent_background)
638                 /* if we have no transparent background */
639         {
640                 /* blit background picture, if available (otherwise, clear only) */
641                 if (local_style && local_style->m_background)
642                         painter.blit(local_style->m_background, offset, eRect(), 0);
643                 else
644                         painter.clear();
645         } else
646         {
647                 if (local_style->m_background)
648                         painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
649                 else if (selected && !local_style->m_selection)
650                         painter.clear();
651         }
652
653         if (cursorValid())
654         {
655                 /* get service information */
656                 ePtr<iStaticServiceInformation> service_info;
657                 m_service_center->info(*m_cursor, service_info);
658                 eServiceReference ref = *m_cursor;
659                 bool isMarker = ref.flags & eServiceReference::isMarker;
660                 bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker);
661                 bool isRecorded = m_record_indicator_mode && isPlayable && checkServiceIsRecorded(ref);
662                 ePtr<eServiceEvent> evt;
663                 bool serviceAvail = true;
664                 bool serviceFallback = false;
665                 int isplayable_value;
666
667                 if (!marked && isPlayable && service_info && m_is_playable_ignore.valid())
668                 {
669                         isplayable_value = service_info->isPlayable(*m_cursor, m_is_playable_ignore);
670
671                         if (isplayable_value == 0) // service unavailable
672                         {
673                                 if (m_color_set[serviceNotAvail])
674                                         painter.setForegroundColor(m_color[serviceNotAvail]);
675                                 else
676                                         painter.setForegroundColor(gRGB(0xbbbbbb));
677                                 serviceAvail = false;
678                         }
679                         else
680                         {
681                                 if (isplayable_value == 2) // fallback receiver service
682                                 {
683                                         if (m_color_set[serviceItemFallback])
684                                                 painter.setForegroundColor(m_color[serviceItemFallback]);
685                                         serviceFallback = true;
686                                 }
687                         }
688                 }
689                 if (m_record_indicator_mode == 3 && isRecorded)
690                 {
691                         if (m_color_set[serviceRecorded])
692                                 painter.setForegroundColor(m_color[serviceRecorded]);
693                         else
694                                 painter.setForegroundColor(gRGB(0xb40431));
695                 }
696
697                 if (selected && local_style && local_style->m_selection)
698                         painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
699
700                 int xoffset=0;  // used as offset when painting the folder/marker symbol or the serviceevent progress
701                 time_t now = time(0);
702
703                 for (int e = 0; e != celServiceTypePixmap; ++e)
704                 {
705                         if (m_element_font[e])
706                         {
707                                 int flags=gPainter::RT_VALIGN_CENTER;
708                                 int yoffs = 0;
709                                 eRect area = m_element_position[e];
710                                 std::string text = "<n/a>";
711                                 switch (e)
712                                 {
713                                 case celServiceNumber:
714                                 {
715                                         if (area.width() <= 0)
716                                                 continue; // no point in going on if we won't paint anything
717
718                                         if( m_cursor->getChannelNum() == 0 )
719                                                 continue;
720
721                                         char buffer[15];
722                                         snprintf(buffer, sizeof(buffer), "%d", m_cursor->getChannelNum() );
723                                         text = buffer;
724                                         flags|=gPainter::RT_HALIGN_RIGHT;
725                                         if (isPlayable && serviceFallback && selected && m_color_set[serviceSelectedFallback])
726                                                 painter.setForegroundColor(m_color[serviceSelectedFallback]);
727                                         break;
728                                 }
729                                 case celServiceName:
730                                 {
731                                         if (service_info)
732                                                 service_info->getName(*m_cursor, text);
733                                         if (!isPlayable)
734                                         {
735                                                 area.setWidth(area.width() + m_element_position[celServiceEventProgressbar].width() +  m_nonplayable_margins);
736                                                 if (m_element_position[celServiceEventProgressbar].left() == 0)
737                                                         area.setLeft(0);
738                                                 if (m_element_position[celServiceNumber].width() && m_element_position[celServiceEventProgressbar].left() == m_element_position[celServiceNumber].width() +  m_nonplayable_margins)
739                                                         area.setLeft(m_element_position[celServiceNumber].width() +  m_nonplayable_margins);
740                                         }
741                                         if (!(m_record_indicator_mode == 3 && isRecorded) && isPlayable && serviceFallback && selected && m_color_set[serviceSelectedFallback])
742                                                 painter.setForegroundColor(m_color[serviceSelectedFallback]);
743                                         break;
744                                 }
745                                 case celServiceInfo:
746                                 {
747                                         if ( isPlayable && service_info && !service_info->getEvent(*m_cursor, evt) )
748                                         {
749                                                 std::string name = evt->getEventName();
750                                                 if (name.empty())
751                                                         continue;
752                                                 text = evt->getEventName();
753                                                 if (serviceAvail)
754                                                 {
755                                                         if (!selected && m_color_set[eventForeground])
756                                                                 painter.setForegroundColor(m_color[eventForeground]);
757                                                         else if (selected && m_color_set[eventForegroundSelected])
758                                                                 painter.setForegroundColor(m_color[eventForegroundSelected]);
759                                                         else
760                                                                 painter.setForegroundColor(gRGB(0xe7b53f));
761
762                                                         if (serviceFallback && !selected && m_color_set[eventForegroundFallback]) // fallback receiver
763                                                                 painter.setForegroundColor(m_color[eventForegroundFallback]);
764                                                         else if (serviceFallback && selected && m_color_set[eventForegroundSelectedFallback])
765                                                                 painter.setForegroundColor(m_color[eventForegroundSelectedFallback]);
766
767                                                 }
768                                                 break;
769                                         }
770                                         continue;
771                                 }
772                                 case celServiceEventProgressbar:
773                                 {
774                                         if (area.width() > 0 && isPlayable && service_info && !service_info->getEvent(*m_cursor, evt))
775                                         {
776                                                 char buffer[15];
777                                                 snprintf(buffer, sizeof(buffer), "%d %%", (int)(100 * (now - evt->getBeginTime()) / evt->getDuration()));
778                                                 text = buffer;
779                                                 flags|=gPainter::RT_HALIGN_RIGHT;
780                                                 break;
781                                         }
782                                         continue;
783                                 }
784                                 }
785
786                                 eRect tmp = area;
787                                 int xoffs = 0;
788                                 ePtr<gPixmap> piconPixmap;
789
790                                 if (e == celServiceName)
791                                 {
792                                         //picon stuff
793                                         if (isPlayable && PyCallable_Check(m_GetPiconNameFunc))
794                                         {
795                                                 ePyObject pArgs = PyTuple_New(1);
796                                                 PyTuple_SET_ITEM(pArgs, 0, PyString_FromString(ref.toString().c_str()));
797                                                 ePyObject pRet = PyObject_CallObject(m_GetPiconNameFunc, pArgs);
798                                                 Py_DECREF(pArgs);
799                                                 if (pRet)
800                                                 {
801                                                         if (PyString_Check(pRet))
802                                                         {
803                                                                 std::string piconFilename = PyString_AS_STRING(pRet);
804                                                                 if (!piconFilename.empty())
805                                                                         loadPNG(piconPixmap, piconFilename.c_str());
806                                                         }
807                                                         Py_DECREF(pRet);
808                                                 }
809                                         }
810                                         xoffs = xoffset;
811                                         tmp.setWidth(((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? tmp.width() : m_column_width) - xoffs);
812                                 }
813
814                                 eTextPara *para = new eTextPara(tmp);
815                                 para->setFont(m_element_font[e]);
816                                 para->renderString(text.c_str());
817
818                                 if (e == celServiceName)
819                                 {
820                                         eRect bbox = para->getBoundBox();
821
822                                         int servicenameWidth = ((!isPlayable || m_column_width == -1 || (!piconPixmap && !m_column_width)) ? bbox.width() : m_column_width);
823                                         m_element_position[celServiceInfo].setLeft(area.left() + servicenameWidth + m_items_distances + xoffs);
824                                         m_element_position[celServiceInfo].setTop(area.top());
825                                         m_element_position[celServiceInfo].setWidth(area.width() - (servicenameWidth + m_items_distances + xoffs));
826                                         m_element_position[celServiceInfo].setHeight(area.height());
827
828                                         if (isPlayable)
829                                         {
830                                                 //picon stuff
831                                                 if (PyCallable_Check(m_GetPiconNameFunc) and (m_column_width || piconPixmap))
832                                                 {
833                                                         eRect area = m_element_position[celServiceInfo];
834                                                         /* PIcons are usually about 100:60. Make it a
835                                                          * bit wider in case the icons are diffently
836                                                          * shaped, and to add a bit of margin between
837                                                          * icon and text. */
838                                                         const int iconWidth = area.height() * 9 / 5;
839                                                         m_element_position[celServiceInfo].setLeft(area.left() + iconWidth);
840                                                         m_element_position[celServiceInfo].setWidth(area.width() - iconWidth);
841                                                         area = m_element_position[celServiceName];
842                                                         xoffs += iconWidth;
843                                                         if (piconPixmap)
844                                                         {
845                                                                 area.moveBy(offset);
846                                                                 painter.clip(area);
847                                                                 painter.blitScale(piconPixmap,
848                                                                         eRect(area.left(), area.top(), iconWidth, area.height()),
849                                                                         area,
850                                                                         gPainter::BT_ALPHABLEND | gPainter::BT_KEEP_ASPECT_RATIO);
851                                                                 painter.clippop();
852                                                         }
853                                                 }
854
855                                                 //service type marker stuff
856                                                 if (m_servicetype_icon_mode)
857                                                 {
858                                                         int orbpos = m_cursor->getUnsignedData(4) >> 16;
859                                                         const char *filename = ref.path.c_str();
860                                                         ePtr<gPixmap> &pixmap =
861                                                                 (m_cursor->flags & eServiceReference::isGroup) ? m_pixmaps[picServiceGroup] :
862                                                                 (strstr(filename, "://")) ? m_pixmaps[picStream] :
863                                                                 (orbpos == 0xFFFF) ? m_pixmaps[picDVB_C] :
864                                                                 (orbpos == 0xEEEE) ? m_pixmaps[picDVB_T] : m_pixmaps[picDVB_S];
865                                                         if (pixmap)
866                                                         {
867                                                                 eSize pixmap_size = pixmap->size();
868                                                                 eRect area = m_element_position[celServiceInfo];
869                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
870                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
871                                                                 int offs = 0;
872                                                                 if (m_servicetype_icon_mode == 1)
873                                                                 {
874                                                                         area = m_element_position[celServiceName];
875                                                                         offs = xoffs;
876                                                                         xoffs += pixmap_size.width() + m_items_distances;
877                                                                 }
878                                                                 else if (m_crypto_icon_mode == 1 && m_pixmaps[picCrypto])
879                                                                         offs = offs + m_pixmaps[picCrypto]->size().width() + m_items_distances;
880                                                                 int correction = (area.height() - pixmap_size.height()) / 2;
881                                                                 area.moveBy(offset);
882                                                                 painter.clip(area);
883                                                                 painter.blit(pixmap, ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
884                                                                 painter.clippop();
885                                                         }
886                                                 }
887
888                                                 //crypto icon stuff
889                                                 if (m_crypto_icon_mode && m_pixmaps[picCrypto])
890                                                 {
891                                                         eSize pixmap_size = m_pixmaps[picCrypto]->size();
892                                                         eRect area = m_element_position[celServiceInfo];
893                                                         int offs = 0;
894                                                         if (m_crypto_icon_mode == 1)
895                                                         {
896                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
897                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
898                                                                 area = m_element_position[celServiceName];
899                                                                 offs = xoffs;
900                                                                 xoffs += pixmap_size.width() + m_items_distances;
901                                                         }
902                                                         int correction = (area.height() - pixmap_size.height()) / 2;
903                                                         area.moveBy(offset);
904                                                         if (service_info->isCrypted())
905                                                         {
906                                                                 if (m_crypto_icon_mode == 2)
907                                                                 {
908                                                                         m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
909                                                                         m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
910                                                                 }
911                                                                 painter.clip(area);
912                                                                 painter.blit(m_pixmaps[picCrypto], ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
913                                                                 painter.clippop();
914                                                         }
915                                                 }
916
917                                                 //record icon stuff
918                                                 if (isRecorded && m_record_indicator_mode < 3 && m_pixmaps[picRecord])
919                                                 {
920                                                         eSize pixmap_size = m_pixmaps[picRecord]->size();
921                                                         eRect area = m_element_position[celServiceInfo];
922                                                         int offs = 0;
923                                                         if (m_record_indicator_mode == 1)
924                                                         {
925                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
926                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
927                                                                 area = m_element_position[celServiceName];
928                                                                 offs = xoffs;
929                                                                 xoffs += pixmap_size.width() + m_items_distances;
930                                                         }
931                                                         int correction = (area.height() - pixmap_size.height()) / 2;
932                                                         area.moveBy(offset);
933                                                         if (m_record_indicator_mode == 2)
934                                                         {
935                                                                 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + m_items_distances);
936                                                                 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - m_items_distances);
937                                                         }
938                                                         painter.clip(area);
939                                                         painter.blit(m_pixmaps[picRecord], ePoint(area.left() + offs, offset.y() + correction), area, gPainter::BT_ALPHATEST);
940                                                         painter.clippop();
941                                                 }
942                                         }
943                                 }
944
945                                 if (flags & gPainter::RT_HALIGN_RIGHT)
946                                         para->realign(eTextPara::dirRight);
947                                 else if (flags & gPainter::RT_HALIGN_CENTER)
948                                         para->realign(eTextPara::dirCenter);
949                                 else if (flags & gPainter::RT_HALIGN_BLOCK)
950                                         para->realign(eTextPara::dirBlock);
951
952                                 if (flags & gPainter::RT_VALIGN_CENTER)
953                                 {
954                                         eRect bbox = para->getBoundBox();
955                                         yoffs = (area.height() - bbox.height()) / 2 - bbox.top();
956                                 }
957
958                                 painter.renderPara(para, offset+ePoint(xoffs, yoffs));
959                         }
960                         else if ((e == celFolderPixmap && m_cursor->flags & eServiceReference::isDirectory) ||
961                                 (e == celMarkerPixmap && m_cursor->flags & eServiceReference::isMarker &&
962                                 !(m_cursor->flags & eServiceReference::isNumberedMarker)))
963                         {
964                                 ePtr<gPixmap> &pixmap =
965                                         (e == celFolderPixmap) ? m_pixmaps[picFolder] : m_pixmaps[picMarker];
966                                 if (pixmap)
967                                 {
968                                         eSize pixmap_size = pixmap->size();
969                                         eRect area;
970                                         if (e == celFolderPixmap || m_element_position[celServiceNumber].width() < pixmap_size.width())
971                                         {
972                                                 area = m_element_position[celServiceName];
973                                                 if (m_element_position[celServiceEventProgressbar].left() == 0)
974                                                         area.setLeft(0);
975                                                 xoffset = pixmap_size.width() + m_items_distances;                      
976                                         }
977                                         else
978                                                 area = m_element_position[celServiceNumber];
979                                         int correction = (area.height() - pixmap_size.height()) / 2;
980                                         area.moveBy(offset);
981                                         painter.clip(area);
982                                         painter.blit(pixmap, ePoint(area.left(), offset.y() + correction), area, gPainter::BT_ALPHATEST);
983                                         painter.clippop();
984                                 }
985                         }
986                 }
987                 if (selected && (!local_style || !local_style->m_selection))
988                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
989
990                 eRect area = m_element_position[celServiceEventProgressbar];
991                 if (area.width() > 0 && evt && !m_element_font[celServiceEventProgressbar])
992                 {
993                         int pb_xpos = area.left();
994                         int pb_ypos = offset.y() + (m_itemsize.height() - m_progressbar_height - 2 * m_progressbar_border_width) / 2;
995                         int pb_width = area.width()- 2 * m_progressbar_border_width;
996                         gRGB ProgressbarBorderColor = 0xdfdfdf;
997                         int evt_done = pb_width * (now - evt->getBeginTime()) / evt->getDuration();
998
999                         // the progress data...
1000                         eRect tmp = eRect(pb_xpos + m_progressbar_border_width, pb_ypos + m_progressbar_border_width, evt_done, m_progressbar_height);
1001                         ePtr<gPixmap> &pixmap = m_pixmaps[picServiceEventProgressbar];
1002                         if (pixmap) {
1003                                 painter.clip(tmp);
1004                                 painter.blit(pixmap, ePoint(pb_xpos + m_progressbar_border_width, pb_ypos + m_progressbar_border_width), tmp, gPainter::BT_ALPHATEST);
1005                                 painter.clippop();
1006                         }
1007                         else {
1008                                 if (!selected && m_color_set[serviceEventProgressbarColor])
1009                                         painter.setForegroundColor(m_color[serviceEventProgressbarColor]);
1010                                 else if (selected && m_color_set[serviceEventProgressbarColorSelected])
1011                                         painter.setForegroundColor(m_color[serviceEventProgressbarColorSelected]);
1012                                 painter.fill(tmp);
1013                         }
1014
1015                         // the progressbar border
1016                         if (!selected)  {
1017                                 if (m_color_set[serviceEventProgressbarBorderColor])
1018                                         ProgressbarBorderColor = m_color[serviceEventProgressbarBorderColor];
1019                                 else if (m_color_set[eventborderForeground])
1020                                         ProgressbarBorderColor = m_color[eventborderForeground];
1021                         }
1022                         else { /* !selected */
1023                                 if (m_color_set[serviceEventProgressbarBorderColorSelected])
1024                                         ProgressbarBorderColor = m_color[serviceEventProgressbarBorderColorSelected];
1025                                 else if (m_color_set[eventborderForegroundSelected])
1026                                         ProgressbarBorderColor = m_color[eventborderForegroundSelected];
1027                         }
1028                         painter.setForegroundColor(ProgressbarBorderColor);
1029
1030                         painter.fill(eRect(pb_xpos, pb_ypos, pb_width + 2 * m_progressbar_border_width,  m_progressbar_border_width));
1031                         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));
1032                         painter.fill(eRect(pb_xpos, pb_ypos + m_progressbar_border_width, m_progressbar_border_width, m_progressbar_height));
1033                         painter.fill(eRect(pb_xpos + m_progressbar_border_width + pb_width, pb_ypos + m_progressbar_border_width, m_progressbar_border_width, m_progressbar_height));
1034                 }
1035         }
1036         painter.clippop();
1037 }