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