~cosmin.lupu/+junk/penguintv

« back to all changes in this revision

Viewing changes to penguintv/html/PTVGtkHtml.py

  • Committer: cosmin.lupu at gmail
  • Date: 2010-04-27 16:47:43 UTC
  • Revision ID: cosmin.lupu@gmail.com-20100427164743-ds8xrqonipp5ovdf
initial packaging

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# class template for various html widgets
 
2
import threading
 
3
import os, os.path
 
4
import re
 
5
import time
 
6
import logging
 
7
 
 
8
import gobject
 
9
import gtk
 
10
 
 
11
import utils
 
12
import PTVhtml
 
13
import ThreadPool
 
14
import SimpleImageCache
 
15
 
 
16
IMG_REGEX = re.compile("<img.*?src=[\",\'](.*?)[\",\'].*?>", re.IGNORECASE|re.DOTALL)
 
17
 
 
18
class PTVGtkHtml(PTVhtml.PTVhtml):
 
19
        def __init__(self, view, home, share_path):
 
20
                PTVhtml.PTVhtml.__init__(self, view, home, share_path)
 
21
                self._htmlview = None
 
22
                self._document_lock = threading.Lock()
 
23
                self._image_cache = SimpleImageCache.SimpleImageCache()
 
24
                self._css = ""
 
25
                self._last_link_time = 0
 
26
                
 
27
                self._view = view
 
28
                
 
29
                f = open(os.path.join(share_path, "gtkhtml.css"))
 
30
                for l in f.readlines(): self._css += l
 
31
                f.close()
 
32
                self._image_pool = ThreadPool.ThreadPool(5, "PlanetView")
 
33
                self._dl_total = 0
 
34
                self._dl_count = 0
 
35
                
 
36
        def finish(self):
 
37
                self._image_pool.joinAll(False, False)
 
38
                del self._image_pool
 
39
                
 
40
        def is_ajax_ok(self):
 
41
                return False
 
42
                
 
43
        def post_show_init(self, widget):
 
44
                import gtkhtml2
 
45
                import SimpleImageCache
 
46
                import threading
 
47
                
 
48
                htmlview = gtkhtml2.View()
 
49
                self._document = gtkhtml2.Document()
 
50
                self._document.connect("link-clicked", self._link_clicked)
 
51
                htmlview.connect("on_url", self._on_url)
 
52
                self._document.connect("request-url", self._request_url)
 
53
                htmlview.get_vadjustment().set_value(0)
 
54
                htmlview.get_hadjustment().set_value(0)
 
55
                
 
56
                self._document.clear()
 
57
                htmlview.set_document(self._document)
 
58
                self._htmlview = htmlview
 
59
                
 
60
                widget.set_property("shadow-type",gtk.SHADOW_IN)
 
61
                widget.set_hadjustment(self._htmlview.get_hadjustment())
 
62
                widget.set_vadjustment(self._htmlview.get_vadjustment())
 
63
                widget.add(self._htmlview)
 
64
                self._scrolled_window = widget
 
65
                
 
66
        def build_header(self, html=""):
 
67
                header = ["""<html><head>
 
68
                            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 
69
<style type="text/css">
 
70
%s
 
71
</style>
 
72
                            <title>title</title>""" % self._css] 
 
73
                header.append(html)
 
74
                header.append("""</head>""")
 
75
                return "\n".join(header)        
 
76
                        
 
77
        def render(self, html, stream_url="file:///", display_id=None):
 
78
                self._document_lock.acquire()
 
79
                imgs = IMG_REGEX.findall(html)
 
80
                uncached=0
 
81
                for url in imgs:
 
82
                        if not self._image_cache.is_cached(url):
 
83
                                uncached+=1
 
84
                                
 
85
                if uncached > 0:
 
86
                        self._document.clear()
 
87
                        self._document.open_stream("text/html")
 
88
                        d = {   "background_color": self._view.get_bg_color(),
 
89
                                        "loading": _("Loading images...")}
 
90
                        self._document.write_stream("""<html><style type="text/css">
 
91
                body { background-color: %(background_color)s; }</style><body><i>%(loading)s</i></body></html>""" % d) 
 
92
                        self._document.close_stream()
 
93
                        self._document_lock.release()
 
94
                        
 
95
                        self._dl_count = 0
 
96
                        self._dl_total = uncached
 
97
                        
 
98
                        for url in imgs:
 
99
                                if not self._image_cache.is_cached(url):
 
100
                                        self._image_pool.queueTask(self._do_download_image, (url, display_id), self._image_dl_cb)
 
101
                        self._image_pool.queueTask(self._download_done, (display_id, html))
 
102
                else:
 
103
                        self._scrolled_window.get_hadjustment().set_value(0)
 
104
                        self._scrolled_window.get_vadjustment().set_value(0)
 
105
                        self._document.clear()
 
106
                        self._document.open_stream("text/html")
 
107
                        self._document.write_stream(html)
 
108
                        self._document.close_stream()
 
109
                        self._document_lock.release()
 
110
                        
 
111
        def dl_interrupt(self):
 
112
                self._image_pool.joinAll(False, False)
 
113
                self._dl_count = 0
 
114
                self._dl_total = 0
 
115
                                
 
116
        def _do_download_image(self, args):
 
117
                url, display_id = args
 
118
                self._image_cache.get_image(url)
 
119
                #print "do download", display_id
 
120
                return display_id
 
121
                
 
122
        def _image_dl_cb(self, display_id):
 
123
                #print "dl_cb", display_id, self._view.get_display_id()
 
124
                if display_id == self._view.get_display_id():
 
125
                        self._dl_count += 1
 
126
                        
 
127
        def _download_done(self, args):
 
128
                display_id, html = args
 
129
                
 
130
                count = 0
 
131
                last_count = self._dl_count
 
132
                #print "dl_done", display_id, self._view.get_display_id()
 
133
                while display_id == self._view.get_display_id() and count < (10 * 2):
 
134
                        if last_count != self._dl_count:
 
135
                                #if downloads are still coming in, reset counter
 
136
                                last_count = self._dl_count
 
137
                                count = 0
 
138
                        if self._dl_count >= self._dl_total:
 
139
                                gobject.idle_add(self._images_loaded, display_id, html)
 
140
                                return
 
141
                        count += 1
 
142
                        time.sleep(0.5)
 
143
                gobject.idle_add(self._images_loaded, display_id, html)
 
144
 
 
145
                
 
146
        def _images_loaded(self, display_id, html):
 
147
                #if we're changing, nevermind.
 
148
                #also make sure entry is the same and that we shouldn't be blanks
 
149
                #print "loaded", display_id, self._view.get_display_id()
 
150
                if display_id == self._view.get_display_id():
 
151
                        va = self._scrolled_window.get_vadjustment()
 
152
                        ha = self._scrolled_window.get_hadjustment()
 
153
                        self._document_lock.acquire()
 
154
                        self._document.clear()
 
155
                        self._document.open_stream("text/html")
 
156
                        self._document.write_stream(html)
 
157
                        self._document.close_stream()
 
158
                        self._document_lock.release()
 
159
                return False
 
160
                
 
161
        def _request_url(self, document, url, stream):
 
162
                try:
 
163
                        image = self._image_cache.get_image(url)
 
164
                        stream.write(image)
 
165
                        stream.close()
 
166
                except Exception, ex:
 
167
                        stream.close()
 
168
                        
 
169
        def _link_clicked(self, document, link):
 
170
                if not utils.RUNNING_HILDON:
 
171
                        link = link.strip()
 
172
                        self.emit('open-uri', link)
 
173
        
 
174
        def _on_url(self, view, url):
 
175
                if utils.RUNNING_HILDON:
 
176
                        now = time.time()
 
177
                        #prevent double-clicks
 
178
                        print now - self._last_link_time
 
179
                        if now - self._last_link_time < 1.0:
 
180
                                logging.debug("detected double-click, ignoring")
 
181
                                return
 
182
                        self._last_link_time = now
 
183
                        if url is None:
 
184
                                return
 
185
                        link = url.strip()
 
186
                        self.emit('open-uri', link)
 
187
                else:
 
188
                        if url is None:
 
189
                                url = ""
 
190
                        self.emit('link-message', url)
 
191