1 #include <lib/service/listboxservice.h>
2 #include <lib/service/service.h>
3 #include <lib/gdi/font.h>
4 #include <lib/dvb/epgcache.h>
5 #include <lib/dvb/pmt.h>
6 #include <lib/python/connections.h>
8 void eListboxServiceContent::addService(const eServiceReference &service, bool beforeCurrent)
10 if (beforeCurrent && m_size)
11 m_list.insert(m_cursor, service);
13 m_list.push_back(service);
18 m_listbox->entryAdded(m_cursor_number-1);
22 m_cursor = m_list.begin();
24 m_listbox->entryAdded(0);
28 void eListboxServiceContent::removeCurrent()
30 if (m_size && m_listbox)
32 if (m_cursor_number == --m_size)
34 m_list.erase(m_cursor--);
38 m_listbox->entryRemoved(m_cursor_number+1);
41 m_listbox->entryRemoved(m_cursor_number);
45 m_list.erase(m_cursor++);
46 m_listbox->entryRemoved(m_cursor_number);
51 void eListboxServiceContent::FillFinished()
53 m_size = m_list.size();
57 m_listbox->entryReset();
60 void eListboxServiceContent::setRoot(const eServiceReference &root, bool justSet)
70 ASSERT(m_service_center);
72 if (m_service_center->list(m_root, m_lst))
73 eDebug("no list available!");
74 else if (m_lst->getContent(m_list))
75 eDebug("getContent failed");
80 void eListboxServiceContent::setCurrent(const eServiceReference &ref)
83 for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
87 m_cursor_number = index;
91 m_listbox->moveSelectionTo(index);
94 void eListboxServiceContent::getCurrent(eServiceReference &ref)
99 ref = eServiceReference();
102 void eListboxServiceContent::getPrev(eServiceReference &ref)
106 list::iterator cursor(m_cursor);
107 if (cursor == m_list.begin())
109 cursor = m_list.end();
114 ref = eServiceReference();
117 void eListboxServiceContent::getNext(eServiceReference &ref)
121 list::iterator cursor(m_cursor);
123 if (cursor == m_list.end())
125 cursor = m_list.begin();
130 ref = eServiceReference();
133 PyObject *eListboxServiceContent::getList()
135 ePyObject result = PyList_New(m_list.size());
137 for (list::iterator it(m_list.begin()); it != m_list.end(); ++it)
139 PyList_SET_ITEM(result, pos++, NEW_eServiceReference(*it));
144 int eListboxServiceContent::getNextBeginningWithChar(char c)
146 // printf("Char: %c\n", c);
148 for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
151 ePtr<iStaticServiceInformation> service_info;
152 m_service_center->info(*i, service_info);
153 service_info->getName(*i, text);
154 // printf("%c\n", text.c_str()[0]);
156 int len=text.length();
159 char cc = text[idx++];
160 if ( cc >= 33 && cc < 127)
171 int eListboxServiceContent::getPrevMarkerPos()
175 list::iterator i(m_cursor);
176 int index = m_cursor_number;
181 if (i->flags & eServiceReference::isMarker)
187 int eListboxServiceContent::getNextMarkerPos()
191 list::iterator i(m_cursor);
192 int index = m_cursor_number;
193 while (index < (m_size-1))
197 if (i->flags & eServiceReference::isMarker)
203 void eListboxServiceContent::initMarked()
208 void eListboxServiceContent::addMarked(const eServiceReference &ref)
210 m_marked.insert(ref);
212 m_listbox->entryChanged(lookupService(ref));
215 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
219 m_listbox->entryChanged(lookupService(ref));
222 int eListboxServiceContent::isMarked(const eServiceReference &ref)
224 return m_marked.find(ref) != m_marked.end();
227 void eListboxServiceContent::markedQueryStart()
229 m_marked_iterator = m_marked.begin();
232 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
234 if (m_marked_iterator == m_marked.end())
236 ref = *m_marked_iterator++;
240 int eListboxServiceContent::lookupService(const eServiceReference &ref)
242 /* shortcut for cursor */
243 if (ref == *m_cursor)
244 return m_cursor_number;
245 /* otherwise, search in the list.. */
247 for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
249 /* this is ok even when the index was not found. */
253 void eListboxServiceContent::setVisualMode(int mode)
255 for (int i=0; i < celElements; ++i)
257 m_element_position[i] = eRect();
258 m_element_font[i] = 0;
261 m_visual_mode = mode;
263 if (m_visual_mode == visModeSimple)
265 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
266 m_element_font[celServiceName] = new gFont("Regular", 23);
270 void eListboxServiceContent::setElementPosition(int element, eRect where)
272 if ((element >= 0) && (element < celElements))
273 m_element_position[element] = where;
276 void eListboxServiceContent::setElementFont(int element, gFont *font)
278 if ((element >= 0) && (element < celElements))
279 m_element_font[element] = font;
282 void eListboxServiceContent::setPixmap(int type, ePtr<gPixmap> &pic)
284 if ((type >=0) && (type < picElements))
285 m_pixmaps[type] = pic;
288 void eListboxServiceContent::sort()
291 m_service_center->list(m_root, m_lst);
294 m_list.sort(iListableServiceCompare(m_lst));
295 /* FIXME: is this really required or can we somehow keep the current entry? */
298 m_listbox->entryReset();
302 DEFINE_REF(eListboxServiceContent);
304 eListboxServiceContent::eListboxServiceContent()
305 :m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_numberoffset(0), m_itemheight(25)
307 memset(m_color_set, 0, sizeof(m_color_set));
309 eServiceCenter::getInstance(m_service_center);
312 void eListboxServiceContent::setColor(int color, gRGB &col)
314 if ((color >= 0) && (color < colorElements))
316 m_color_set[color] = true;
317 m_color[color] = col;
321 void eListboxServiceContent::cursorHome()
323 if (m_current_marked && m_saved_cursor == m_list.end())
325 if (m_cursor_number >= m_size)
327 m_cursor_number = m_size-1;
330 while (m_cursor_number)
332 std::iter_swap(m_cursor--, m_cursor);
334 if (m_listbox && m_cursor_number)
335 m_listbox->entryChanged(m_cursor_number);
340 m_cursor = m_list.begin();
345 void eListboxServiceContent::cursorEnd()
347 if (m_current_marked && m_saved_cursor == m_list.end())
349 while (m_cursor != m_list.end())
351 list::iterator prev = m_cursor++;
353 if ( prev != m_list.end() && m_cursor != m_list.end() )
355 std::iter_swap(m_cursor, prev);
357 m_listbox->entryChanged(m_cursor_number);
363 m_cursor = m_list.end();
364 m_cursor_number = m_size;
368 int eListboxServiceContent::setCurrentMarked(bool state)
370 bool prev = m_current_marked;
371 m_current_marked = state;
373 if (state != prev && m_listbox)
375 m_listbox->entryChanged(m_cursor_number);
379 m_service_center->list(m_root, m_lst);
382 ePtr<iMutableServiceList> list;
383 if (m_lst->startEdit(list))
384 eDebug("no editable list");
387 eServiceReference ref;
390 eDebug("no valid service selected");
393 int pos = cursorGet();
394 eDebugNoNewLine("move %s to %d ", ref.toString().c_str(), pos);
395 if (list->moveService(ref, cursorGet()))
403 eDebug("no list available!");
410 int eListboxServiceContent::cursorMove(int count)
412 int prev = m_cursor_number, last = m_cursor_number + count;
415 while(count && m_cursor != m_list.end())
417 list::iterator prev_it = m_cursor++;
418 if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
420 std::iter_swap(prev_it, m_cursor);
421 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
422 m_listbox->entryChanged(m_cursor_number);
427 } else if (count < 0)
429 while (count && m_cursor != m_list.begin())
431 list::iterator prev_it = m_cursor--;
432 if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
434 std::iter_swap(prev_it, m_cursor);
435 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
436 m_listbox->entryChanged(m_cursor_number);
445 int eListboxServiceContent::cursorValid()
447 return m_cursor != m_list.end();
450 int eListboxServiceContent::cursorSet(int n)
457 int eListboxServiceContent::cursorGet()
459 return m_cursor_number;
462 void eListboxServiceContent::cursorSave()
464 m_saved_cursor = m_cursor;
465 m_saved_cursor_number = m_cursor_number;
468 void eListboxServiceContent::cursorRestore()
470 m_cursor = m_saved_cursor;
471 m_cursor_number = m_saved_cursor_number;
472 m_saved_cursor = m_list.end();
475 int eListboxServiceContent::size()
480 void eListboxServiceContent::setSize(const eSize &size)
483 if (m_visual_mode == visModeSimple)
484 setVisualMode(m_visual_mode);
487 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
489 painter.clip(eRect(offset, m_itemsize));
493 if (m_current_marked && selected)
495 else if (cursorValid() && isMarked(*m_cursor))
503 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
505 eListboxStyle *local_style = 0;
507 /* get local listbox style, if present */
509 local_style = m_listbox->getLocalStyle();
511 if (marked == 1) // marked
513 style.setStyle(painter, eWindowStyle::styleListboxMarked);
514 if (m_color_set[markedForeground])
515 painter.setForegroundColor(m_color[markedForeground]);
516 if (m_color_set[markedBackground])
517 painter.setBackgroundColor(m_color[markedBackground]);
519 else if (marked == 2) // marked and selected
521 style.setStyle(painter, eWindowStyle::styleListboxMarkedAndSelected);
522 if (m_color_set[markedForegroundSelected])
523 painter.setForegroundColor(m_color[markedForegroundSelected]);
524 if (m_color_set[markedBackgroundSelected])
525 painter.setBackgroundColor(m_color[markedBackgroundSelected]);
527 else if (local_style)
531 /* if we have a local background color set, use that. */
532 if (local_style->m_background_color_selected_set)
533 painter.setBackgroundColor(local_style->m_background_color_selected);
534 /* same for foreground */
535 if (local_style->m_foreground_color_selected_set)
536 painter.setForegroundColor(local_style->m_foreground_color_selected);
540 /* if we have a local background color set, use that. */
541 if (local_style->m_background_color_set)
542 painter.setBackgroundColor(local_style->m_background_color);
543 /* same for foreground */
544 if (local_style->m_foreground_color_set)
545 painter.setForegroundColor(local_style->m_foreground_color);
549 if (!local_style || !local_style->m_transparent_background)
550 /* if we have no transparent background */
552 /* blit background picture, if available (otherwise, clear only) */
553 if (local_style && local_style->m_background)
554 painter.blit(local_style->m_background, offset, eRect(), 0);
559 if (local_style->m_background)
560 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
561 else if (selected && !local_style->m_selection)
567 /* get service information */
568 ePtr<iStaticServiceInformation> service_info;
569 m_service_center->info(*m_cursor, service_info);
570 eServiceReference ref = *m_cursor;
571 bool isMarker = ref.flags & eServiceReference::isMarker;
572 bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker);
573 bool paintProgress = false;
574 ePtr<eServiceEvent> evt;
576 bool serviceAvail = true;
578 if (!marked && isPlayable && service_info && m_is_playable_ignore.valid() && !service_info->isPlayable(*m_cursor, m_is_playable_ignore))
580 if (m_color_set[serviceNotAvail])
581 painter.setForegroundColor(m_color[serviceNotAvail]);
583 painter.setForegroundColor(gRGB(0xbbbbbb));
584 serviceAvail = false;
587 if (selected && local_style && local_style->m_selection)
588 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
590 int xoffset=0; // used as offset when painting the folder/marker symbol or the serviceevent progress
592 for (int e = 0; e < celElements; ++e)
594 if (m_element_font[e])
596 int flags=gPainter::RT_VALIGN_CENTER,
599 eRect &area = m_element_position[e];
600 std::string text = "<n/a>";
605 case celServiceNumber:
607 if (m_cursor->flags & eServiceReference::isMarker)
610 /* how we can do this better? :) */
611 int markers_before=0;
613 list::iterator tmp=m_cursor;
614 while(tmp != m_list.begin())
617 if (tmp->flags & eServiceReference::isMarker)
621 sprintf(bla, "%d", m_numberoffset + m_cursor_number + 1 - markers_before);
623 flags|=gPainter::RT_HALIGN_RIGHT;
629 service_info->getName(*m_cursor, text);
630 #ifdef USE_LIBVUGLES2
631 painter.setFlush(text == "<n/a>");
637 if ( isPlayable && !service_info->getEvent(*m_cursor, evt) )
639 std::string name = evt->getEventName();
642 text = '(' + evt->getEventName() + ')';
645 if (!selected && m_color_set[serviceDescriptionColor])
646 painter.setForegroundColor(m_color[serviceDescriptionColor]);
647 else if (selected && m_color_set[serviceDescriptionColorSelected])
648 painter.setForegroundColor(m_color[serviceDescriptionColorSelected]);
658 tmp.setWidth(tmp.width()-xoffs);
660 eTextPara *para = new eTextPara(tmp);
661 para->setFont(m_element_font[e]);
662 para->renderString(text.c_str());
664 if (e == celServiceName)
666 eRect bbox = para->getBoundBox();
667 int name_width = bbox.width()+8;
668 m_element_position[celServiceInfo].setLeft(area.left()+name_width+xoffs);
669 m_element_position[celServiceInfo].setTop(area.top());
670 m_element_position[celServiceInfo].setWidth(area.width()-(name_width+xoffs));
671 m_element_position[celServiceInfo].setHeight(area.height());
674 if (flags & gPainter::RT_HALIGN_RIGHT)
675 para->realign(eTextPara::dirRight);
676 else if (flags & gPainter::RT_HALIGN_CENTER)
677 para->realign(eTextPara::dirCenter);
678 else if (flags & gPainter::RT_HALIGN_BLOCK)
679 para->realign(eTextPara::dirBlock);
681 if (flags & gPainter::RT_VALIGN_CENTER)
683 eRect bbox = para->getBoundBox();
684 int vcentered_top = (area.height() - bbox.height()) / 2;
685 yoffs = vcentered_top - bbox.top();
688 painter.renderPara(para, offset+ePoint(xoffs, yoffs));
690 else if (e == celServiceTypePixmap || e == celFolderPixmap || e == celMarkerPixmap)
692 int orbpos = m_cursor->getUnsignedData(4) >> 16;
693 ePtr<gPixmap> &pixmap =
694 (e == celFolderPixmap) ? m_pixmaps[picFolder] :
695 (e == celMarkerPixmap) ? m_pixmaps[picMarker] :
696 (m_cursor->flags & eServiceReference::isGroup) ? m_pixmaps[picServiceGroup] :
697 (orbpos == 0xFFFF) ? m_pixmaps[picDVB_C] :
698 (orbpos == 0xEEEE) ? m_pixmaps[picDVB_T] : m_pixmaps[picDVB_S];
701 eSize pixmap_size = pixmap->size();
702 int p = celServiceInfo;
703 if (e == celFolderPixmap)
705 else if (e == celMarkerPixmap)
706 p = celServiceNumber;
707 eRect area = m_element_position[p];
708 int correction = (area.height() - pixmap_size.height()) / 2;
712 if (e != celServiceTypePixmap)
714 m_element_position[celServiceInfo] = area;
715 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + 8);
716 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - 8);
718 else if (m_cursor->flags & eServiceReference::isDirectory)
720 if (e != celFolderPixmap)
722 xoffset = pixmap_size.width() + 8;
724 else if (m_cursor->flags & eServiceReference::isMarker)
726 if (e != celMarkerPixmap)
730 eFatal("unknown service type in listboxservice");
734 painter.blit(pixmap, offset+ePoint(area.left(), correction), area, gPainter::BT_ALPHATEST);
738 else if (e == celServiceEventProgressbar)
740 eRect area = m_element_position[celServiceEventProgressbar];
741 if (area.width() > 0 && (isPlayable || isMarker))
743 // we schedule it to paint it as last element.. so we dont need to reset fore/background color
744 paintProgress = isPlayable;
745 xoffset = area.width() + 10;
749 if (selected && (!local_style || !local_style->m_selection))
750 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
751 if (paintProgress && evt)
753 eRect area = m_element_position[celServiceEventProgressbar];
754 if (!selected && m_color_set[serviceEventProgressbarBorderColor])
755 painter.setForegroundColor(m_color[serviceEventProgressbarBorderColor]);
756 else if (selected && m_color_set[serviceEventProgressbarBorderColorSelected])
757 painter.setForegroundColor(m_color[serviceEventProgressbarBorderColorSelected]);
761 int progressX = area.left() + offset.x();
762 int progressW = area.width() - 2 * border;
763 int progressT = offset.y() + (m_itemsize.height() - progressH - 2*border) / 2;
765 // paint progressbar frame
766 painter.fill(eRect(progressX, progressT, area.width(), border));
767 painter.fill(eRect(progressX, progressT + border, border, progressH));
768 painter.fill(eRect(progressX, progressT + progressH + border, area.width(), border));
769 painter.fill(eRect(progressX + area.width() - border, progressT + border, border, progressH));
772 time_t now = time(0);
773 int value = progressW * (now - evt->getBeginTime()) / evt->getDuration();
775 eRect tmp = eRect(progressX + border, progressT + border, value, progressH);
776 ePtr<gPixmap> &pixmap = m_pixmaps[picServiceEventProgressbar];
781 painter.blit(pixmap, ePoint(progressX + border, progressT + border), tmp, gPainter::BT_ALPHATEST);
786 if (!selected && m_color_set[serviceEventProgressbarColor])
787 painter.setForegroundColor(m_color[serviceEventProgressbarColor]);
788 else if (selected && m_color_set[serviceEventProgressbarColorSelected])
789 painter.setForegroundColor(m_color[serviceEventProgressbarColorSelected]);
797 void eListboxServiceContent::setIgnoreService( const eServiceReference &service )
799 m_is_playable_ignore=service;
800 if (m_listbox && m_listbox->isVisible())
801 m_listbox->invalidate();
804 void eListboxServiceContent::setItemHeight(int height)
806 m_itemheight = height;
808 m_listbox->setItemHeight(height);