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 int eListboxServiceContent::getNextBeginningWithChar(char c)
135 // printf("Char: %c\n", c);
137 for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
140 ePtr<iStaticServiceInformation> service_info;
141 m_service_center->info(*i, service_info);
142 service_info->getName(*i, text);
143 // printf("%c\n", text.c_str()[0]);
145 int len=text.length();
148 char cc = text[idx++];
149 if ( cc >= 33 && cc < 127)
160 int eListboxServiceContent::getPrevMarkerPos()
164 list::iterator i(m_cursor);
165 int index = m_cursor_number;
170 if (i->flags & eServiceReference::isMarker)
176 int eListboxServiceContent::getNextMarkerPos()
180 list::iterator i(m_cursor);
181 int index = m_cursor_number;
182 while (index < (m_size-1))
186 if (i->flags & eServiceReference::isMarker)
192 void eListboxServiceContent::initMarked()
197 void eListboxServiceContent::addMarked(const eServiceReference &ref)
199 m_marked.insert(ref);
201 m_listbox->entryChanged(lookupService(ref));
204 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
208 m_listbox->entryChanged(lookupService(ref));
211 int eListboxServiceContent::isMarked(const eServiceReference &ref)
213 return m_marked.find(ref) != m_marked.end();
216 void eListboxServiceContent::markedQueryStart()
218 m_marked_iterator = m_marked.begin();
221 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
223 if (m_marked_iterator == m_marked.end())
225 ref = *m_marked_iterator++;
229 int eListboxServiceContent::lookupService(const eServiceReference &ref)
231 /* shortcut for cursor */
232 if (ref == *m_cursor)
233 return m_cursor_number;
234 /* otherwise, search in the list.. */
236 for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
238 /* this is ok even when the index was not found. */
242 void eListboxServiceContent::setVisualMode(int mode)
244 for (int i=0; i < celElements; ++i)
246 m_element_position[i] = eRect();
247 m_element_font[i] = 0;
250 m_visual_mode = mode;
252 if (m_visual_mode == visModeSimple)
254 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
255 m_element_font[celServiceName] = new gFont("Regular", 23);
259 void eListboxServiceContent::setElementPosition(int element, eRect where)
261 if ((element >= 0) && (element < celElements))
262 m_element_position[element] = where;
265 void eListboxServiceContent::setElementFont(int element, gFont *font)
267 if ((element >= 0) && (element < celElements))
268 m_element_font[element] = font;
271 void eListboxServiceContent::setPixmap(int type, ePtr<gPixmap> &pic)
273 if ((type >=0) && (type < picElements))
274 m_pixmaps[type] = pic;
277 void eListboxServiceContent::sort()
280 m_service_center->list(m_root, m_lst);
283 m_list.sort(iListableServiceCompare(m_lst));
284 /* FIXME: is this really required or can we somehow keep the current entry? */
287 m_listbox->entryReset();
291 DEFINE_REF(eListboxServiceContent);
293 eListboxServiceContent::eListboxServiceContent()
294 :m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_numberoffset(0), m_itemheight(25)
296 memset(m_color_set, 0, sizeof(m_color_set));
298 eServiceCenter::getInstance(m_service_center);
301 void eListboxServiceContent::setColor(int color, gRGB &col)
303 if ((color >= 0) && (color < colorElements))
305 m_color_set[color] = true;
306 m_color[color] = col;
310 void eListboxServiceContent::cursorHome()
312 if (m_current_marked && m_saved_cursor == m_list.end())
314 if (m_cursor_number >= m_size)
316 m_cursor_number = m_size-1;
319 while (m_cursor_number)
321 std::iter_swap(m_cursor--, m_cursor);
323 if (m_listbox && m_cursor_number)
324 m_listbox->entryChanged(m_cursor_number);
329 m_cursor = m_list.begin();
334 void eListboxServiceContent::cursorEnd()
336 if (m_current_marked && m_saved_cursor == m_list.end())
338 while (m_cursor != m_list.end())
340 list::iterator prev = m_cursor++;
342 if ( prev != m_list.end() && m_cursor != m_list.end() )
344 std::iter_swap(m_cursor, prev);
346 m_listbox->entryChanged(m_cursor_number);
352 m_cursor = m_list.end();
353 m_cursor_number = m_size;
357 int eListboxServiceContent::setCurrentMarked(bool state)
359 bool prev = m_current_marked;
360 m_current_marked = state;
362 if (state != prev && m_listbox)
364 m_listbox->entryChanged(m_cursor_number);
368 m_service_center->list(m_root, m_lst);
371 ePtr<iMutableServiceList> list;
372 if (m_lst->startEdit(list))
373 eDebug("no editable list");
376 eServiceReference ref;
379 eDebug("no valid service selected");
382 int pos = cursorGet();
383 eDebugNoNewLine("move %s to %d ", ref.toString().c_str(), pos);
384 if (list->moveService(ref, cursorGet()))
392 eDebug("no list available!");
399 int eListboxServiceContent::cursorMove(int count)
401 int prev = m_cursor_number, last = m_cursor_number + count;
404 while(count && m_cursor != m_list.end())
406 list::iterator prev_it = m_cursor++;
407 if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
409 std::iter_swap(prev_it, m_cursor);
410 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
411 m_listbox->entryChanged(m_cursor_number);
416 } else if (count < 0)
418 while (count && m_cursor != m_list.begin())
420 list::iterator prev_it = m_cursor--;
421 if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
423 std::iter_swap(prev_it, m_cursor);
424 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
425 m_listbox->entryChanged(m_cursor_number);
434 int eListboxServiceContent::cursorValid()
436 return m_cursor != m_list.end();
439 int eListboxServiceContent::cursorSet(int n)
446 int eListboxServiceContent::cursorGet()
448 return m_cursor_number;
451 void eListboxServiceContent::cursorSave()
453 m_saved_cursor = m_cursor;
454 m_saved_cursor_number = m_cursor_number;
457 void eListboxServiceContent::cursorRestore()
459 m_cursor = m_saved_cursor;
460 m_cursor_number = m_saved_cursor_number;
461 m_saved_cursor = m_list.end();
464 int eListboxServiceContent::size()
469 void eListboxServiceContent::setSize(const eSize &size)
472 if (m_visual_mode == visModeSimple)
473 setVisualMode(m_visual_mode);
476 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
478 painter.clip(eRect(offset, m_itemsize));
482 if (m_current_marked && selected)
484 else if (cursorValid() && isMarked(*m_cursor))
492 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
494 eListboxStyle *local_style = 0;
496 /* get local listbox style, if present */
498 local_style = m_listbox->getLocalStyle();
500 if (marked == 1) // marked
502 style.setStyle(painter, eWindowStyle::styleListboxMarked);
503 if (m_color_set[markedForeground])
504 painter.setForegroundColor(m_color[markedForeground]);
505 if (m_color_set[markedBackground])
506 painter.setBackgroundColor(m_color[markedBackground]);
508 else if (marked == 2) // marked and selected
510 style.setStyle(painter, eWindowStyle::styleListboxMarkedAndSelected);
511 if (m_color_set[markedForegroundSelected])
512 painter.setForegroundColor(m_color[markedForegroundSelected]);
513 if (m_color_set[markedBackgroundSelected])
514 painter.setBackgroundColor(m_color[markedBackgroundSelected]);
516 else if (local_style)
520 /* if we have a local background color set, use that. */
521 if (local_style->m_background_color_selected_set)
522 painter.setBackgroundColor(local_style->m_background_color_selected);
523 /* same for foreground */
524 if (local_style->m_foreground_color_selected_set)
525 painter.setForegroundColor(local_style->m_foreground_color_selected);
529 /* if we have a local background color set, use that. */
530 if (local_style->m_background_color_set)
531 painter.setBackgroundColor(local_style->m_background_color);
532 /* same for foreground */
533 if (local_style->m_foreground_color_set)
534 painter.setForegroundColor(local_style->m_foreground_color);
538 if (!local_style || !local_style->m_transparent_background)
539 /* if we have no transparent background */
541 /* blit background picture, if available (otherwise, clear only) */
542 if (local_style && local_style->m_background)
543 painter.blit(local_style->m_background, offset, eRect(), 0);
548 if (local_style->m_background)
549 painter.blit(local_style->m_background, offset, eRect(), gPainter::BT_ALPHATEST);
550 else if (selected && !local_style->m_selection)
556 /* get service information */
557 ePtr<iStaticServiceInformation> service_info;
558 m_service_center->info(*m_cursor, service_info);
559 eServiceReference ref = *m_cursor;
560 bool isMarker = ref.flags & eServiceReference::isMarker;
561 bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker);
562 bool paintProgress = false;
563 ePtr<eServiceEvent> evt;
565 bool serviceAvail = true;
567 if (!marked && isPlayable && service_info && m_is_playable_ignore.valid() && !service_info->isPlayable(*m_cursor, m_is_playable_ignore))
569 if (m_color_set[serviceNotAvail])
570 painter.setForegroundColor(m_color[serviceNotAvail]);
572 painter.setForegroundColor(gRGB(0xbbbbbb));
573 serviceAvail = false;
576 if (selected && local_style && local_style->m_selection)
577 painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
579 int xoffset=0; // used as offset when painting the folder/marker symbol or the serviceevent progress
581 for (int e = 0; e < celElements; ++e)
583 if (m_element_font[e])
585 int flags=gPainter::RT_VALIGN_CENTER,
588 eRect &area = m_element_position[e];
589 std::string text = "<n/a>";
594 case celServiceNumber:
596 if (m_cursor->flags & eServiceReference::isMarker)
599 /* how we can do this better? :) */
600 int markers_before=0;
602 list::iterator tmp=m_cursor;
603 while(tmp != m_list.begin())
606 if (tmp->flags & eServiceReference::isMarker)
610 sprintf(bla, "%d", m_numberoffset + m_cursor_number + 1 - markers_before);
612 flags|=gPainter::RT_HALIGN_RIGHT;
618 service_info->getName(*m_cursor, text);
623 if ( isPlayable && !service_info->getEvent(*m_cursor, evt) )
625 std::string name = evt->getEventName();
628 text = '(' + evt->getEventName() + ')';
631 if (!selected && m_color_set[serviceDescriptionColor])
632 painter.setForegroundColor(m_color[serviceDescriptionColor]);
633 else if (selected && m_color_set[serviceDescriptionColorSelected])
634 painter.setForegroundColor(m_color[serviceDescriptionColorSelected]);
644 tmp.setWidth(tmp.width()-xoffs);
646 eTextPara *para = new eTextPara(tmp);
647 para->setFont(m_element_font[e]);
648 para->renderString(text.c_str());
650 if (e == celServiceName)
652 eRect bbox = para->getBoundBox();
653 int name_width = bbox.width()+8;
654 m_element_position[celServiceInfo].setLeft(area.left()+name_width+xoffs);
655 m_element_position[celServiceInfo].setTop(area.top());
656 m_element_position[celServiceInfo].setWidth(area.width()-(name_width+xoffs));
657 m_element_position[celServiceInfo].setHeight(area.height());
660 if (flags & gPainter::RT_HALIGN_RIGHT)
661 para->realign(eTextPara::dirRight);
662 else if (flags & gPainter::RT_HALIGN_CENTER)
663 para->realign(eTextPara::dirCenter);
664 else if (flags & gPainter::RT_HALIGN_BLOCK)
665 para->realign(eTextPara::dirBlock);
667 if (flags & gPainter::RT_VALIGN_CENTER)
669 eRect bbox = para->getBoundBox();
670 int vcentered_top = (area.height() - bbox.height()) / 2;
671 yoffs = vcentered_top - bbox.top();
674 painter.renderPara(para, offset+ePoint(xoffs, yoffs));
676 else if (e == celServiceTypePixmap || e == celFolderPixmap || e == celMarkerPixmap)
678 int orbpos = m_cursor->getUnsignedData(4) >> 16;
679 ePtr<gPixmap> &pixmap =
680 (e == celFolderPixmap) ? m_pixmaps[picFolder] :
681 (e == celMarkerPixmap) ? m_pixmaps[picMarker] :
682 (m_cursor->flags & eServiceReference::isGroup) ? m_pixmaps[picServiceGroup] :
683 (orbpos == 0xFFFF) ? m_pixmaps[picDVB_C] :
684 (orbpos == 0xEEEE) ? m_pixmaps[picDVB_T] : m_pixmaps[picDVB_S];
687 eSize pixmap_size = pixmap->size();
688 int p = celServiceInfo;
689 if (e == celFolderPixmap)
691 else if (e == celMarkerPixmap)
692 p = celServiceNumber;
693 eRect area = m_element_position[p];
694 int correction = (area.height() - pixmap_size.height()) / 2;
698 if (e != celServiceTypePixmap)
700 m_element_position[celServiceInfo] = area;
701 m_element_position[celServiceInfo].setLeft(area.left() + pixmap_size.width() + 8);
702 m_element_position[celServiceInfo].setWidth(area.width() - pixmap_size.width() - 8);
704 else if (m_cursor->flags & eServiceReference::isDirectory)
706 if (e != celFolderPixmap)
708 xoffset = pixmap_size.width() + 8;
710 else if (m_cursor->flags & eServiceReference::isMarker)
712 if (e != celMarkerPixmap)
716 eFatal("unknown service type in listboxservice");
720 painter.blit(pixmap, offset+ePoint(area.left(), correction), area, gPainter::BT_ALPHATEST);
724 else if (e == celServiceEventProgressbar)
726 eRect area = m_element_position[celServiceEventProgressbar];
727 if (area.width() > 0 && (isPlayable || isMarker))
729 // we schedule it to paint it as last element.. so we dont need to reset fore/background color
730 paintProgress = isPlayable;
731 xoffset = area.width() + 10;
735 if (selected && (!local_style || !local_style->m_selection))
736 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
737 if (paintProgress && evt)
739 eRect area = m_element_position[celServiceEventProgressbar];
740 if (!selected && m_color_set[serviceEventProgressbarBorderColor])
741 painter.setForegroundColor(m_color[serviceEventProgressbarBorderColor]);
742 else if (selected && m_color_set[serviceEventProgressbarBorderColorSelected])
743 painter.setForegroundColor(m_color[serviceEventProgressbarBorderColorSelected]);
747 int progressX = area.left() + offset.x();
748 int progressW = area.width() - 2 * border;
749 int progressT = offset.y() + (m_itemsize.height() - progressH - 2*border) / 2;
751 // paint progressbar frame
752 painter.fill(eRect(progressX, progressT, area.width(), border));
753 painter.fill(eRect(progressX, progressT + border, border, progressH));
754 painter.fill(eRect(progressX, progressT + progressH + border, area.width(), border));
755 painter.fill(eRect(progressX + area.width() - border, progressT + border, border, progressH));
758 time_t now = time(0);
759 int value = progressW * (now - evt->getBeginTime()) / evt->getDuration();
761 eRect tmp = eRect(progressX + border, progressT + border, value, progressH);
762 ePtr<gPixmap> &pixmap = m_pixmaps[picServiceEventProgressbar];
767 painter.blit(pixmap, ePoint(progressX + border, progressT + border), tmp, gPainter::BT_ALPHATEST);
772 if (!selected && m_color_set[serviceEventProgressbarColor])
773 painter.setForegroundColor(m_color[serviceEventProgressbarColor]);
774 else if (selected && m_color_set[serviceEventProgressbarColorSelected])
775 painter.setForegroundColor(m_color[serviceEventProgressbarColorSelected]);
783 void eListboxServiceContent::setIgnoreService( const eServiceReference &service )
785 m_is_playable_ignore=service;
786 if (m_listbox && m_listbox->isVisible())
787 m_listbox->invalidate();
790 void eListboxServiceContent::setItemHeight(int height)
792 m_itemheight = height;
794 m_listbox->setItemHeight(height);