another fix for alignement left
[enigma2.git] / lib / gui / elistboxcontent.cpp
1 #include <lib/gui/elistbox.h>
2 #include <lib/gui/elistboxcontent.h>
3 #include <lib/gdi/font.h>
4 #include <Python.h>
5
6 /*
7     The basic idea is to have an interface which gives all relevant list
8     processing functions, and can be used by the listbox to browse trough
9     the list.
10     
11     The listbox directly uses the implemented cursor. It tries hard to avoid
12     iterating trough the (possibly very large) list, so it should be O(1),
13     i.e. the performance should not be influenced by the size of the list.
14     
15     The list interface knows how to draw the current entry to a specified 
16     offset. Different interfaces can be used to adapt different lists,
17     pre-filter lists on the fly etc.
18     
19                 cursorSave/Restore is used to avoid re-iterating the list on redraw.
20                 The current selection is always selected as cursor position, the
21     cursor is then positioned to the start, and then iterated. This gives
22     at most 2x m_items_per_page cursor movements per redraw, indepenent
23     of the size of the list.
24     
25     Although cursorSet is provided, it should be only used when there is no
26     other way, as it involves iterating trough the list.
27  */
28
29 iListboxContent::~iListboxContent()
30 {
31 }
32
33 iListboxContent::iListboxContent(): m_listbox(0)
34 {
35 }
36
37 void iListboxContent::setListbox(eListbox *lb)
38 {
39         m_listbox = lb;
40 }
41
42 DEFINE_REF(eListboxTestContent);
43
44 void eListboxTestContent::cursorHome()
45 {
46         m_cursor = 0;
47 }
48
49 void eListboxTestContent::cursorEnd()
50 {
51         m_cursor = size();
52 }
53
54 int eListboxTestContent::cursorMove(int count)
55 {
56         m_cursor += count;
57         
58         if (m_cursor < 0)
59                 cursorHome();
60         else if (m_cursor > size())
61                 cursorEnd();
62         return 0;
63 }
64
65 int eListboxTestContent::cursorValid()
66 {
67         return m_cursor < size();
68 }
69
70 int eListboxTestContent::cursorSet(int n)
71 {
72         m_cursor = n;
73         
74         if (m_cursor < 0)
75                 cursorHome();
76         else if (m_cursor > size())
77                 cursorEnd();
78         return 0;
79 }
80
81 int eListboxTestContent::cursorGet()
82 {
83         return m_cursor;
84 }
85
86 void eListboxTestContent::cursorSave()
87 {
88         m_saved_cursor = m_cursor;
89 }
90
91 void eListboxTestContent::cursorRestore()
92 {
93         m_cursor = m_saved_cursor;
94 }
95
96 int eListboxTestContent::size()
97 {
98         return 10;
99 }
100         
101 RESULT eListboxTestContent::connectItemChanged(const Slot0<void> &itemChanged, ePtr<eConnection> &connection)
102 {
103         return 0;
104 }
105
106 void eListboxTestContent::setSize(const eSize &size)
107 {
108         m_size = size;
109 }
110
111 void eListboxTestContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
112 {
113         ePtr<gFont> fnt = new gFont("Regular", 20);
114         painter.clip(eRect(offset, m_size));
115         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
116         painter.clear();
117
118         if (cursorValid())
119         {
120                 painter.setFont(fnt);
121                 char string[10];
122                 sprintf(string, "%d.)", m_cursor);
123                 
124                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
125                 
126                 painter.renderText(eRect(text_offset, m_size), string);
127                 
128                 if (selected)
129                         style.drawFrame(painter, eRect(offset, m_size), eWindowStyle::frameListboxEntry);
130         }
131         
132         painter.clippop();
133 }
134
135 //////////////////////////////////////
136
137 DEFINE_REF(eListboxStringContent);
138
139 eListboxStringContent::eListboxStringContent()
140 {
141         m_size = 0;
142         cursorHome();
143 }
144
145 void eListboxStringContent::cursorHome()
146 {
147         m_cursor = m_list.begin();
148         m_cursor_number = 0;
149 }
150
151 void eListboxStringContent::cursorEnd()
152 {
153         m_cursor = m_list.end();
154         m_cursor_number = m_size;
155 }
156
157 int eListboxStringContent::cursorMove(int count)
158 {
159         if (count > 0)
160         {
161                 while (count && (m_cursor != m_list.end()))
162                 {
163                         ++m_cursor;
164                         ++m_cursor_number;
165                         --count;
166                 }
167         } else if (count < 0)
168         {
169                 while (count && (m_cursor != m_list.begin()))
170                 {
171                         --m_cursor;
172                         --m_cursor_number;
173                         ++count;
174                 }
175         }
176         
177         return 0;
178 }
179
180 int eListboxStringContent::cursorValid()
181 {
182         return m_cursor != m_list.end();
183 }
184
185 int eListboxStringContent::cursorSet(int n)
186 {
187         cursorHome();
188         cursorMove(n);
189         
190         return 0;
191 }
192
193 int eListboxStringContent::cursorGet()
194 {
195         return m_cursor_number;
196 }
197
198 void eListboxStringContent::cursorSave()
199 {
200         m_saved_cursor = m_cursor;
201         m_saved_cursor_number = m_cursor_number;
202 }
203
204 void eListboxStringContent::cursorRestore()
205 {
206         m_cursor = m_saved_cursor;
207         m_cursor_number = m_saved_cursor_number;
208 }
209
210 int eListboxStringContent::size()
211 {
212         return m_size;
213 }
214         
215 void eListboxStringContent::setSize(const eSize &size)
216 {
217         m_itemsize = size;
218 }
219
220 void eListboxStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
221 {
222         ePtr<gFont> fnt = new gFont("Regular", 20);
223         painter.clip(eRect(offset, m_itemsize));
224         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
225         painter.clear();
226         
227         eDebug("item %d", m_cursor_number);
228         if (cursorValid())
229         {
230                 eDebug("is valid..");
231                 painter.setFont(fnt);
232                 
233                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
234                 
235                 painter.renderText(eRect(text_offset, m_itemsize), *m_cursor);
236                 
237                 if (selected)
238                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
239         }
240         
241         painter.clippop();
242 }
243
244 void eListboxStringContent::setList(std::list<std::string> &list)
245 {
246         m_list = list;
247         m_size = list.size();
248         cursorHome();
249         m_listbox->entryReset(false);
250 }
251
252 //////////////////////////////////////
253
254 DEFINE_REF(eListboxPythonStringContent);
255
256 eListboxPythonStringContent::eListboxPythonStringContent()
257 {
258         m_list = 0;
259 }
260
261 eListboxPythonStringContent::~eListboxPythonStringContent()
262 {
263         Py_XDECREF(m_list);
264 }
265
266 void eListboxPythonStringContent::cursorHome()
267 {
268         m_cursor = 0;
269 }
270
271 void eListboxPythonStringContent::cursorEnd()
272 {
273         m_cursor = size();
274 }
275
276 int eListboxPythonStringContent::cursorMove(int count)
277 {
278         m_cursor += count;
279         
280         if (m_cursor < 0)
281                 cursorHome();
282         else if (m_cursor > size())
283                 cursorEnd();
284         return 0;
285 }
286
287 int eListboxPythonStringContent::cursorValid()
288 {
289         return m_cursor < size();
290 }
291
292 int eListboxPythonStringContent::cursorSet(int n)
293 {
294         m_cursor = n;
295         
296         if (m_cursor < 0)
297                 cursorHome();
298         else if (m_cursor > size())
299                 cursorEnd();
300         return 0;
301 }
302
303 int eListboxPythonStringContent::cursorGet()
304 {
305         return m_cursor;
306 }
307
308 void eListboxPythonStringContent::cursorSave()
309 {
310         m_saved_cursor = m_cursor;
311 }
312
313 void eListboxPythonStringContent::cursorRestore()
314 {
315         m_cursor = m_saved_cursor;
316 }
317
318 int eListboxPythonStringContent::size()
319 {
320         if (!m_list)
321                 return 0;
322         return PyList_Size(m_list);
323 }
324         
325 void eListboxPythonStringContent::setSize(const eSize &size)
326 {
327         m_itemsize = size;
328 }
329
330 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
331 {
332         ePtr<gFont> fnt = new gFont("Regular", 20);
333         painter.clip(eRect(offset, m_itemsize));
334         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
335         painter.clear();
336
337         if (m_list && cursorValid())
338         {
339                 PyObject *item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
340                 painter.setFont(fnt);
341
342                         /* the user can supply tuples, in this case the first one will be displayed. */         
343                 if (PyTuple_Check(item))
344                         item = PyTuple_GET_ITEM(item, 0);
345                 
346                 const char *string = PyString_Check(item) ? PyString_AsString(item) : "<not-a-string>";
347                 
348                 ePoint text_offset = offset + (selected ? ePoint(2, 2) : ePoint(1, 1));
349                 
350                 painter.renderText(eRect(text_offset, m_itemsize), string);
351                 
352                 if (selected)
353                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
354         }
355         
356         painter.clippop();
357 }
358
359 void eListboxPythonStringContent::setList(PyObject *list)
360 {
361         Py_XDECREF(m_list);
362         if (!PyList_Check(list))
363         {
364                 m_list = 0;
365         } else
366         {
367                 m_list = list;
368                 Py_INCREF(m_list);
369         }
370
371         if (m_listbox)
372                 m_listbox->entryReset(false);
373 }
374
375 PyObject *eListboxPythonStringContent::getCurrentSelection()
376 {
377         if (!m_list)
378                 return 0;
379         if (!cursorValid())
380                 return 0;
381         PyObject *r = PyList_GET_ITEM(m_list, m_cursor);
382         Py_XINCREF(r);
383         return r;
384 }
385
386 void eListboxPythonStringContent::invalidateEntry(int index)
387 {
388         if (m_listbox)
389                 m_listbox->entryChanged(index);
390 }
391
392 void eListboxPythonStringContent::invalidate()
393 {
394         if (m_listbox)
395                 m_listbox->invalidate();
396 }
397
398 //////////////////////////////////////
399
400 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
401 {
402         ePtr<gFont> fnt = new gFont("Regular", 20);
403         ePtr<gFont> fnt2 = new gFont("Regular", 16);
404         eRect itemrect(offset, m_itemsize);
405         painter.clip(itemrect);
406         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
407         painter.clear();
408
409         if (m_list && cursorValid())
410         {
411                         /* get current list item */
412                 PyObject *item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
413                 PyObject *text = 0, *value = 0;
414                 painter.setFont(fnt);
415
416                         /* the first tuple element is a string for the left side.
417                            the second one will be called, and the result shall be an tuple.
418                            
419                            of this tuple,
420                            the first one is the type (string).
421                            the second one is the value. */
422                 if (PyTuple_Check(item))
423                 {
424                                 /* handle left part. get item from tuple, convert to string, display. */
425                                 
426                         text = PyTuple_GET_ITEM(item, 0);
427                         text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
428                         const char *string = (text && PyString_Check(text)) ? PyString_AsString(text) : "<not-a-string>";
429                         eSize item_left = eSize(m_seperation, m_itemsize.height());
430                         eSize item_right = eSize(m_itemsize.width() - m_seperation, m_itemsize.height());
431                         painter.renderText(eRect(offset, item_left), string, gPainter::RT_HALIGN_LEFT);
432                         Py_XDECREF(text);
433                         
434                                 /* when we have no label, align value to the left. (FIXME: 
435                                    don't we want to specifiy this individually?) */
436                         int value_alignment_left = !*string;
437                         
438                                 /* now, handle the value. get 2nd part from tuple*/
439                         value = PyTuple_GET_ITEM(item, 1);
440                         if (value)
441                         {
442                                 PyObject *args = PyTuple_New(1);
443                                 PyTuple_SET_ITEM(args, 0, PyInt_FromLong(selected));
444                                 
445                                         /* CallObject will call __call__ which should return the value tuple */
446                                 value = PyObject_CallObject(value, args);
447                                 
448                                 if (PyErr_Occurred())
449                                         PyErr_Print();
450
451                                 Py_DECREF(args);
452                                         /* the PyInt was stolen. */
453                         }
454                         
455                                 /*  check if this is really a tuple */
456                         if (value && PyTuple_Check(value))
457                         {
458                                         /* convert type to string */
459                                 PyObject *type = PyTuple_GET_ITEM(value, 0);
460                                 const char *atype = (type && PyString_Check(type)) ? PyString_AsString(type) : 0;
461                                 
462                                 if (atype)
463                                 {
464                                         if (!strcmp(atype, "text"))
465                                         {
466                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
467                                                 const char *value = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
468                                                 painter.setFont(fnt2);
469                                                 if (value_alignment_left)
470                                                         painter.renderText(eRect(offset, item_right), value, gPainter::RT_HALIGN_LEFT);
471                                                 else
472                                                         painter.renderText(eRect(offset + eSize(m_seperation, 0), item_right), value, gPainter::RT_HALIGN_RIGHT);
473
474                                                         /* pvalue is borrowed */
475                                         } else if (!strcmp(atype, "slider"))
476                                         {
477                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
478                                                 
479                                                         /* convert value to Long. fallback to -1 on error. */
480                                                 int value = (pvalue && PyInt_Check(pvalue)) ? PyInt_AsLong(pvalue) : -1;
481                                                 
482                                                         /* calc. slider length */
483                                                 int width = item_right.width() * value / 100;
484                                                 int height = item_right.height();
485                                                 
486                                                                                                 
487                                                         /* draw slider */
488                                                 //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
489                                                 //hack - make it customizable
490                                                 painter.fill(eRect(offset.x() + m_seperation, offset.y() + 5, width, height-10));
491                                                 
492                                                         /* pvalue is borrowed */
493                                         } else if (!strcmp(atype, "mtext"))
494                                         {
495                                                 PyObject *pvalue = PyTuple_GET_ITEM(value, 1);
496                                                 const char *text = (pvalue && PyString_Check(pvalue)) ? PyString_AsString(pvalue) : "<not-a-string>";
497                                                 int xoffs = value_alignment_left ? 0 : m_seperation;
498                                                 ePtr<eTextPara> para = new eTextPara(eRect(offset + eSize(xoffs, 0), item_right));
499                                                 para->setFont(fnt2);
500                                                 para->renderString(text, 0);
501                                                 para->realign(value_alignment_left ? eTextPara::dirLeft : eTextPara::dirRight);
502                                                 int glyphs = para->size();
503                                                 
504                                                 PyObject *plist = 0;
505                                                 
506                                                 if (PyTuple_Size(value) >= 3)
507                                                         plist = PyTuple_GET_ITEM(value, 2);
508                                                 
509                                                 int entries = 0;
510
511                                                 if (plist && PyList_Check(plist))
512                                                         entries = PyList_Size(plist);
513                                                 
514                                                 for (int i = 0; i < entries; ++i)
515                                                 {
516                                                         PyObject *entry = PyList_GET_ITEM(plist, i);
517                                                         int num = PyInt_Check(entry) ? PyInt_AsLong(entry) : -1;
518                                                         
519                                                         if ((num < 0) || (num >= glyphs))
520                                                                 eWarning("glyph index %d in PythonConfigList out of bounds!");
521                                                         else
522                                                         {
523                                                                 para->setGlyphFlag(num, GS_INVERT);
524                                                                 eRect bbox;
525                                                                 bbox = para->getGlyphBBox(num);
526                                                                 bbox = eRect(bbox.left(), offset.y(), bbox.width(), m_itemsize.height());
527                                                                 painter.fill(bbox);
528                                                         }
529                                                                 /* entry is borrowed */
530                                                 }
531                                                 
532                                                 painter.renderPara(para, ePoint(0, 0));
533                                                         /* pvalue is borrowed */
534                                                         /* plist is 0 or borrowed */
535                                         }
536                                 }
537                                         /* type is borrowed */
538                         } else
539                                 eWarning("eListboxPythonConfigContent: second value of tuple is not a tuple.");
540                                 /* value is borrowed */
541                 }
542
543                 if (selected)
544                         style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
545         }
546         
547         painter.clippop();
548 }
549
550 //////////////////////////////////////
551
552         /* todo: make a real infrastructure here! */
553 RESULT SwigFromPython(ePtr<gPixmap> &res, PyObject *obj);
554
555 void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
556 {
557         eRect itemrect(offset, m_itemsize);
558         painter.clip(itemrect);
559         style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
560         painter.clear();
561
562         if (m_list && cursorValid())
563         {
564                 PyObject *items = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
565                 
566                 if (!items)
567                 {
568                         eDebug("eListboxPythonMultiContent: error getting item %d", m_cursor);
569                         goto error_out;
570                 }
571                 
572                 if (!PyList_Check(items))
573                 {
574                         eDebug("eListboxPythonMultiContent: list entry %d is not a list", m_cursor);
575                         goto error_out;
576                 }
577                 
578                 int size = PyList_Size(items);
579                 for (int i = 1; i < size; ++i)
580                 {
581                         PyObject *item = PyList_GET_ITEM(items, i); // borrowed reference!
582                         
583                         if (!item)
584                         {
585                                 eDebug("eListboxPythonMultiContent: ?");
586                                 goto error_out;
587                         }
588                         
589                         PyObject *px = 0, *py = 0, *pwidth = 0, *pheight = 0, *pfnt = 0, *pstring = 0, *pflags = 0;
590                 
591                         /*
592                                 we have a list of tuples:
593                                 
594                                 (0, x, y, width, height, fnt, flags, "bla" ),
595
596                                 or, for a progress:
597                                 (1, x, y, width, height, filled_percent )
598
599                                 or, for a pixmap:
600                                 
601                                 (2, x, y, width, height, pixmap )
602                                 
603                          */
604                         
605                         if (!PyTuple_Check(item))
606                         {
607                                 eDebug("eListboxPythonMultiContent did not receive a tuple.");
608                                 goto error_out;
609                         }
610
611                         int size = PyTuple_Size(item);
612
613                         if (!size)
614                         {
615                                 eDebug("eListboxPythonMultiContent receive empty tuple.");
616                                 goto error_out;
617                         }
618
619                         int type = PyInt_AsLong(PyTuple_GET_ITEM(item, 0));
620
621                         if (size > 5)
622                         {
623                                 px = PyTuple_GET_ITEM(item, 1);
624                                 py = PyTuple_GET_ITEM(item, 2);
625                                 pwidth = PyTuple_GET_ITEM(item, 3);
626                                 pheight = PyTuple_GET_ITEM(item, 4);
627                                 pfnt = PyTuple_GET_ITEM(item, 5); /* could also be an pixmap or an int (progress filled percent) */
628                                 if (size > 7)
629                                 {
630                                         pflags = PyTuple_GET_ITEM(item, 6);
631                                         pstring = PyTuple_GET_ITEM(item, 7);
632                                 }
633                         }
634                         
635                         switch (type)
636                         {
637                         case TYPE_TEXT: // text
638                         {
639                                 if (!(px && py && pwidth && pheight && pfnt && pstring))
640                                 {
641                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_TEXT, x, y, width, height, fnt, flags, string[, ...])");
642                                         goto error_out;
643                                 }
644                                 
645                                 const char *string = (PyString_Check(pstring)) ? PyString_AsString(pstring) : "<not-a-string>";
646                                 int x = PyInt_AsLong(px);
647                                 int y = PyInt_AsLong(py);
648                                 int width = PyInt_AsLong(pwidth);
649                                 int height = PyInt_AsLong(pheight);
650                                 int flags = PyInt_AsLong(pflags);
651                                 int fnt = PyInt_AsLong(pfnt);
652                                 
653                                 if (m_font.find(fnt) == m_font.end())
654                                 {
655                                         eDebug("eListboxPythonMultiContent: specified font %d was not found!", fnt);
656                                         goto error_out;
657                                 }
658                                 
659                                 eRect r = eRect(x, y, width, height);
660                                 r.moveBy(offset);
661                                 r &= itemrect;
662                                 
663                                 painter.setFont(m_font[fnt]);
664                                 
665                                 painter.clip(r);
666                                 painter.renderText(r, string, flags);
667                                 painter.clippop();
668                                 break;
669                         }
670                         case TYPE_PROGRESS: // Progress
671                         {
672                                 if (!(px && py && pwidth && pheight && pfnt))
673                                 {
674                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent))");
675                                         goto error_out;
676                                 }
677                                 int x = PyInt_AsLong(px);
678                                 int y = PyInt_AsLong(py);
679                                 int width = PyInt_AsLong(pwidth);
680                                 int height = PyInt_AsLong(pheight);
681                                 int filled = PyInt_AsLong(pfnt);
682
683                                 eRect r = eRect(x, y, width, height);
684                                 r.moveBy(offset);
685                                 r &= itemrect;
686
687                                 painter.clip(r);
688                                 int bwidth=2;  // borderwidth hardcoded yet
689
690                                 // border
691                                 eRect rc = eRect(x, y, width, bwidth);
692                                 rc.moveBy(offset);
693                                 painter.fill(rc);
694
695                                 rc = eRect(x, y+bwidth, bwidth, height-bwidth);
696                                 rc.moveBy(offset);
697                                 painter.fill(rc);
698
699                                 rc = eRect(x+bwidth, y+height-bwidth, width-bwidth, bwidth);
700                                 rc.moveBy(offset);
701                                 painter.fill(rc);
702
703                                 rc = eRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
704                                 rc.moveBy(offset);
705                                 painter.fill(rc);
706
707                                 // progress
708                                 rc = eRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
709                                 rc.moveBy(offset);
710                                 painter.fill(rc);
711
712                                 painter.clippop();
713
714                                 break;
715                         }
716                         case TYPE_PIXMAP: // pixmap
717                         {
718                                 if (!(px && py && pwidth && pheight && pfnt))
719                                 {
720                                         eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap))");
721                                         goto error_out;
722                                 }
723                                 int x = PyInt_AsLong(px);
724                                 int y = PyInt_AsLong(py);
725                                 int width = PyInt_AsLong(pwidth);
726                                 int height = PyInt_AsLong(pheight);
727                                 ePtr<gPixmap> pixmap;
728                                 if (SwigFromPython(pixmap, pfnt))
729                                 {
730                                         eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
731                                         goto error_out;
732                                 }
733
734                                 eRect r = eRect(x, y, width, height);
735                                 r.moveBy(offset);
736                                 r &= itemrect;
737                                 
738                                 painter.clip(r);
739                                 painter.blit(pixmap, r.topLeft(), r);
740                                 painter.clippop();
741
742                                 break;
743                         }
744                         default:
745                                 eWarning("eListboxPythonMultiContent received unknown type (%d)", type);
746                                 goto error_out;
747                         }
748                 }
749         }
750         
751         if (selected)
752                 style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
753
754 error_out:
755         painter.clippop();
756 }
757
758 void eListboxPythonMultiContent::setFont(int fnt, gFont *font)
759 {
760         if (font)
761                 m_font[fnt] = font;
762         else
763                 m_font.erase(fnt);
764 }