set foregroundcolor of non tuneable services in servicelist to gray (for linked tuner...
[vuplus_dvbapp] / 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/dvb/epgcache.h>
5 #include <lib/dvb/pmt.h>
6
7 void eListboxServiceContent::setRoot(const eServiceReference &root)
8 {
9         m_list.clear();
10         m_root = root;
11         
12         assert(m_service_center);
13         
14         ePtr<iListableService> lst;
15         if (m_service_center->list(m_root, lst))
16                 eDebug("no list available!");
17         else
18                 if (lst->getContent(m_list))
19                         eDebug("getContent failed");
20
21         m_size = m_list.size();
22         cursorHome();
23         
24         if (m_listbox)
25                 m_listbox->entryReset();
26 }
27
28 void eListboxServiceContent::setCurrent(const eServiceReference &ref)
29 {
30         int index=0;
31         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
32                 if ( *i == ref )
33                 {
34                         m_cursor = i;
35                         m_cursor_number = index;
36                         break;
37                 }
38 }
39
40 void eListboxServiceContent::getCurrent(eServiceReference &ref)
41 {
42         if (cursorValid())
43                 ref = *m_cursor;
44         else
45                 ref = eServiceReference();
46 }
47
48 int eListboxServiceContent::getNextBeginningWithChar(char c)
49 {
50 //      printf("Char: %c\n", c);
51         int index=0;
52         for (list::iterator i(m_list.begin()); i != m_list.end(); ++i, ++index)
53         {
54                 std::string text;
55                 ePtr<iStaticServiceInformation> service_info;
56                 m_service_center->info(*i, service_info);
57                 service_info->getName(*i, text);
58 //              printf("%c\n", text.c_str()[0]);
59                 int idx=0;
60                 int len=text.length();
61                 while ( idx <= len )
62                 {
63                         char cc = text[idx++];
64                         if ( cc >= 33 && cc < 127)
65                         {
66                                 if (cc == c)
67                                         return index;
68                                 break;
69                         }
70                 }
71         }
72         return 0;
73 }
74
75 void eListboxServiceContent::initMarked()
76 {
77         m_marked.clear();
78 }
79
80 void eListboxServiceContent::addMarked(const eServiceReference &ref)
81 {
82         m_marked.insert(ref);
83         if (m_listbox)
84                 m_listbox->entryChanged(lookupService(ref));
85 }
86
87 void eListboxServiceContent::removeMarked(const eServiceReference &ref)
88 {
89         m_marked.erase(ref);
90         if (m_listbox)
91                 m_listbox->entryChanged(lookupService(ref));
92 }
93
94 int eListboxServiceContent::isMarked(const eServiceReference &ref)
95 {
96         return m_marked.find(ref) != m_marked.end();
97 }
98
99 void eListboxServiceContent::markedQueryStart()
100 {
101         m_marked_iterator = m_marked.begin();
102 }
103
104 int eListboxServiceContent::markedQueryNext(eServiceReference &ref)
105 {
106         if (m_marked_iterator == m_marked.end())
107                 return -1;
108         ref = *m_marked_iterator++;
109         return 0;
110 }
111
112 int eListboxServiceContent::lookupService(const eServiceReference &ref)
113 {
114                 /* shortcut for cursor */
115         if (ref == *m_cursor)
116                 return m_cursor_number;
117                 /* otherwise, search in the list.. */
118         int index = 0;
119         for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
120         
121                 /* this is ok even when the index was not found. */
122         return index;
123 }
124
125 void eListboxServiceContent::setVisualMode(int mode)
126 {
127         m_visual_mode = mode;
128         
129         if (m_visual_mode == visModeSimple)
130         {
131                 m_element_position[celServiceName] = eRect(ePoint(0, 0), m_itemsize);
132                 m_element_font[celServiceName] = new gFont("Arial", 23);
133                 m_element_position[celServiceNumber] = eRect();
134                 m_element_font[celServiceNumber] = 0;
135                 m_element_position[celIcon] = eRect();
136                 m_element_position[celServiceInfo] = eRect();
137                 m_element_font[celServiceInfo] = 0;
138         }
139 }
140
141 void eListboxServiceContent::setElementPosition(int element, eRect where)
142 {
143         if ((element >= 0) && (element < celElements))
144                 m_element_position[element] = where;
145 }
146
147 void eListboxServiceContent::setElementFont(int element, gFont *font)
148 {
149         if ((element >= 0) && (element < celElements))
150                 m_element_font[element] = font;
151 }
152
153 void eListboxServiceContent::sort()
154 {
155         ePtr<iListableService> lst;
156         if (!m_service_center->list(m_root, lst))
157         {
158                 m_list.sort(iListableServiceCompare(lst));
159                         /* FIXME: is this really required or can we somehow keep the current entry? */
160                 cursorHome();
161                 if (m_listbox)
162                         m_listbox->entryReset();
163         }
164 }
165
166 DEFINE_REF(eListboxServiceContent);
167
168 eListboxServiceContent::eListboxServiceContent()
169         :m_epgcache(eEPGCache::getInstance()), m_visual_mode(visModeSimple), m_size(0), m_current_marked(false), m_numberoffset(0)
170 {
171         cursorHome();
172         eServiceCenter::getInstance(m_service_center);
173         if (eDVBResourceManager::getInstance(m_res_mgr))
174                 eDebug("no resource manager");
175 }
176
177 void eListboxServiceContent::cursorHome()
178 {
179         if (m_current_marked && m_saved_cursor == m_list.end())
180         {
181                 while (m_cursor_number)
182                 {
183                         std::iter_swap(m_cursor--, m_cursor);
184                         --m_cursor_number;
185                         if (m_listbox && m_cursor_number)
186                                 m_listbox->entryChanged(m_cursor_number);
187                 }
188         }
189         else
190         {
191                 m_cursor = m_list.begin();
192                 m_cursor_number = 0;
193         }
194 }
195
196 void eListboxServiceContent::cursorEnd()
197 {
198         if (m_current_marked && m_saved_cursor == m_list.end())
199         {
200                 while (m_cursor != m_list.end())
201                 {
202                         list::iterator prev = m_cursor++;
203                         ++m_cursor_number;
204                         if ( prev != m_list.end() && m_cursor != m_list.end() )
205                         {
206                                 std::iter_swap(m_cursor, prev);
207                                 if ( m_listbox )
208                                         m_listbox->entryChanged(m_cursor_number);
209                         }
210                 }
211         }
212         else
213         {
214                 m_cursor = m_list.end();
215                 m_cursor_number = m_size;
216         }
217 }
218
219 int eListboxServiceContent::setCurrentMarked(bool state)
220 {
221         bool prev = m_current_marked;
222         m_current_marked = state;
223
224         if (state != prev && m_listbox)
225         {
226                 m_listbox->entryChanged(m_cursor_number);
227                 if (!state)
228                 {
229                         ePtr<iListableService> lst;
230                         if (m_service_center->list(m_root, lst))
231                                 eDebug("no list available!");
232                         else
233                         {
234                                 ePtr<iMutableServiceList> list;
235                                 if (lst->startEdit(list))
236                                         eDebug("no editable list");
237                                 else
238                                 {
239                                         eServiceReference ref;
240                                         getCurrent(ref);
241                                         if(!ref)
242                                                 eDebug("no valid service selected");
243                                         else
244                                         {
245                                                 int pos = cursorGet();
246                                                 eDebugNoNewLine("move %s to %d ", ref.toString().c_str(), pos);
247                                                 if (list->moveService(ref, cursorGet()))
248                                                         eDebug("failed");
249                                                 else
250                                                         eDebug("ok");
251                                         }
252                                 }
253                         }
254                 }
255         }
256
257         return 0;
258 }
259
260 int eListboxServiceContent::cursorMove(int count)
261 {
262         int prev = m_cursor_number, last = m_cursor_number + count;
263         if (count > 0)
264         {
265                 while(count && m_cursor != m_list.end())
266                 {
267                         list::iterator prev_it = m_cursor++;
268                         if ( m_current_marked && m_cursor != m_list.end() && m_saved_cursor == m_list.end() )
269                         {
270                                 std::iter_swap(prev_it, m_cursor);
271                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
272                                         m_listbox->entryChanged(m_cursor_number);
273                         }
274                         ++m_cursor_number;
275                         --count;
276         }
277         } else if (count < 0)
278         {
279                 while (count && m_cursor != m_list.begin())
280                 {
281                         list::iterator prev_it = m_cursor--;
282                         if ( m_current_marked && m_cursor != m_list.end() && prev_it != m_list.end() && m_saved_cursor == m_list.end() )
283                         {
284                                 std::iter_swap(prev_it, m_cursor);
285                                 if ( m_listbox && prev != m_cursor_number && last != m_cursor_number )
286                                         m_listbox->entryChanged(m_cursor_number);
287                         }
288                         --m_cursor_number;
289                         ++count;
290                 }
291         }
292         return 0;
293 }
294
295 int eListboxServiceContent::cursorValid()
296 {
297         return m_cursor != m_list.end();
298 }
299
300 int eListboxServiceContent::cursorSet(int n)
301 {
302         cursorHome();
303         cursorMove(n);
304         return 0;
305 }
306
307 int eListboxServiceContent::cursorGet()
308 {
309         return m_cursor_number;
310 }
311
312 void eListboxServiceContent::cursorSave()
313 {
314         m_saved_cursor = m_cursor;
315         m_saved_cursor_number = m_cursor_number;
316 }
317
318 void eListboxServiceContent::cursorRestore()
319 {
320         m_cursor = m_saved_cursor;
321         m_cursor_number = m_saved_cursor_number;
322         m_saved_cursor = m_list.end();
323 }
324
325 int eListboxServiceContent::size()
326 {
327         return m_size;
328 }
329         
330 void eListboxServiceContent::setSize(const eSize &size)
331 {
332         m_itemsize = size;
333         setVisualMode(m_visual_mode);
334 }
335
336 void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
337 {
338         painter.clip(eRect(offset, m_itemsize));
339
340         bool tuneable=true;
341
342         if (m_res_mgr && cursorValid() && !((m_cursor->flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory))
343         {
344                 if ( eDVBServicePMTHandler::getCount() > 1 )
345                 {
346                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) *m_cursor;
347                         eUsePtr<iDVBChannel> channel;
348                         eDVBChannelID chid;
349                         ref.getChannelID(chid);
350                         tuneable = !m_res_mgr->allocateChannel(chid, channel, true);  // no real allocate channel..just fake
351                 }
352         }
353
354         if (m_current_marked && selected)
355                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
356         else if (cursorValid() && isMarked(*m_cursor))
357                 style.setStyle(painter, eWindowStyle::styleListboxMarked);
358         else
359         {
360                 style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
361                 if (!tuneable)
362                         painter.setForegroundColor(gRGB(0xbbbbbb));
363         }
364         painter.clear();
365         
366         if (cursorValid())
367         {
368                         /* get service information */
369                 ePtr<iStaticServiceInformation> service_info;
370                 m_service_center->info(*m_cursor, service_info);
371                 
372                 for (int e = 0; e < celElements; ++e)
373                 {
374                         if (!m_element_font[e])
375                                 continue;
376                         int flags=gPainter::RT_VALIGN_CENTER;
377
378                         eRect area = m_element_position[e];
379
380                         std::string text = "<n/a>";
381
382                         switch (e)
383                         {
384                         case celIcon:
385                                 // render icon here...
386                                 continue;
387                         case celServiceNumber:
388                         {
389                                 char bla[10];
390                                 sprintf(bla, "%d", m_numberoffset + m_cursor_number + 1);
391                                 text = bla;
392                                 flags|=gPainter::RT_HALIGN_RIGHT;
393                                 break;
394                         }
395                         case celServiceName:
396                         {
397                                 if (service_info)
398                                         service_info->getName(*m_cursor, text);
399                                 break;
400                         }
401                         case celServiceInfo:
402                         {
403                                 ePtr<eServiceEvent> evt;
404                                 time_t t=-1;
405                                 if ( !m_epgcache->lookupEventTime(*m_cursor, t, evt) )
406                                         text = '(' + evt->getEventName() + ')';
407                                 else
408                                         continue;
409                                 break;
410                         }
411                         }
412
413                         eTextPara *para = new eTextPara(area);
414
415                         para->setFont(m_element_font[e]);
416                         para->renderString(text);
417
418                         if (e == celServiceName)
419                         {
420                                 eRect bbox = para->getBoundBox();
421                                 int name_width = bbox.width()+10;
422                                 m_element_position[celServiceInfo].setLeft(area.left()+name_width);
423                                 m_element_position[celServiceInfo].setTop(area.top());
424                                 m_element_position[celServiceInfo].setWidth(area.width()-name_width);
425                                 m_element_position[celServiceInfo].setHeight(area.height());
426                         }
427
428                         if (flags & gPainter::RT_HALIGN_RIGHT)
429                                 para->realign(eTextPara::dirRight);
430                         else if (flags & gPainter::RT_HALIGN_CENTER)
431                                 para->realign(eTextPara::dirCenter);
432                         else if (flags & gPainter::RT_HALIGN_BLOCK)
433                                 para->realign(eTextPara::dirBlock);
434
435                         ePoint offs = offset;
436
437                         if (flags & gPainter::RT_VALIGN_CENTER)
438                         {
439                                 eRect bbox = para->getBoundBox();
440                                 int vcentered_top = (area.height() - bbox.height()) / 2;
441                                 int correction = vcentered_top - bbox.top();
442                                 offs += ePoint(0, correction);
443                         }
444
445                         painter.renderPara(para, offs);
446                 }
447                 
448                 if (selected)
449                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
450         }
451         
452         painter.clippop();
453 }
454