Codebase list sugar-read-activity / 563347f
fix EOL spaces Signed-off-by: Sascha Silbe <sascha-pgp@silbe.org> Sascha Silbe authored 13 years ago Gonzalo Odiard committed 13 years ago
16 changed file(s) with 295 addition(s) and 295 deletion(s). Raw diff Collapse all Expand all
33 ]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="activity-read">
44 <path d="M27.904,11.023h-0.002 c0-0.002-1.71-2.053-9.376-2.504C10.86,8.07,6.843,10.121,6.84,10.122c-1.898,0.619-3.495,1.735-3.495,3.494v27.702 c0,2.025,1.235,3.494,3.495,3.494c0.003,0,4.41-1.35,10.004-1.35c5.589-0.001,11.061,2.253,11.061,2.253" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-linejoin="round" stroke-width="3.5"/>
55 <path d="M27.898,11.023 L27.898,11.023c0-0.002,1.715-2.053,9.377-2.504c7.668-0.449,11.686,1.602,11.688,1.603c1.897,0.619,3.494,1.735,3.494,3.494 v27.702c0,2.025-1.233,3.494-3.494,3.494c-0.003,0-4.409-1.35-10.004-1.35c-5.589-0.001-11.062,2.253-11.062,2.253" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-linejoin="round" stroke-width="3.5"/>
6
6
77 <line display="inline" fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" x1="27.898" x2="27.9" y1="11.023" y2="45.717"/>
88 <path d=" M32.566,44.275c0,0-0.031,2.906-4.666,2.906c-4.632,0-4.663-2.906-4.663-2.906" display="inline" fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/>
99 </g></svg>
2323
2424 def set_current_page(self, n):
2525 # When the book is being loaded, calling this does not help
26 # In such a situation, we go into a loop and try to load the
26 # In such a situation, we go into a loop and try to load the
2727 # supplied page when the book has loaded completely
2828 n += 1
2929 if self._ready:
2020
2121 from epub import _Epub as Epub
2222 from epubview import _View as EpubView
23 from jobs import _JobFind as JobFind
23 from jobs import _JobFind as JobFind
3131 self._ncxpath = None
3232 self._basepath = None
3333 self._tempdir = tempfile.mkdtemp()
34
34
3535 if not self._verify():
3636 print 'Warning: This does not seem to be a valid epub file'
37
37
3838 self._get_opf()
3939 self._get_ncx()
40
40
4141 ncxfile = self._zobject.open(self._ncxpath)
42 opffile = self._zobject.open(self._opfpath)
42 opffile = self._zobject.open(self._opfpath)
4343 self._navmap = navmap.NavMap(opffile, ncxfile, self._basepath)
44
44
4545 opffile = self._zobject.open(self._opfpath)
46 self._info = epubinfo.EpubInfo(opffile)
47
46 self._info = epubinfo.EpubInfo(opffile)
47
4848 self._unzip()
49
49
5050 def _unzip(self):
5151 #self._zobject.extractall(path = self._tempdir) # This is broken upto python 2.7
5252 orig_cwd = os.getcwd()
6060 self._zobject.extract(name)
6161 os.chdir(orig_cwd)
6262
63
63
6464 def _get_opf(self):
6565 containerfile = self._zobject.open('META-INF/container.xml')
66
66
6767 tree = etree.parse(containerfile)
6868 root = tree.getroot()
69
69
7070 for element in root.iterfind('.//{urn:oasis:names:tc:opendocument:xmlns:container}rootfile'):
7171 if element.get('media-type') == 'application/oebps-package+xml':
7272 self._opfpath = element.get('full-path')
73
74 if self._opfpath.rpartition('/')[0]:
73
74 if self._opfpath.rpartition('/')[0]:
7575 self._basepath = self._opfpath.rpartition('/')[0] + '/'
7676 else:
7777 self._basepath = ''
78
78
7979 containerfile.close()
8080
8181
8282 def _get_ncx(self):
8383 opffile = self._zobject.open(self._opfpath)
84
84
8585 tree = etree.parse(opffile)
8686 root = tree.getroot()
8787
9191 for element in root.iterfind('.//{http://www.idpf.org/2007/opf}item'):
9292 if element.get('id') == tocid:
9393 self._ncxpath = self._basepath + element.get('href')
94
94
9595 opffile.close()
9696
9797 def _verify(self):
9898 '''
99 Method to crudely check to verify that what we
99 Method to crudely check to verify that what we
100100 are dealing with is a epub file or not
101101 '''
102102 if not os.path.exists(self._filepath):
103103 return False
104
104
105105 self._zobject = zipfile.ZipFile(self._filepath)
106
106
107107 if not 'mimetype' in self._zobject.namelist():
108108 return False
109
109
110110 mtypefile = self._zobject.open('mimetype')
111111 mimetype = mtypefile.readline()
112
112
113113 if not mimetype.startswith('application/epub+zip'): # Some files seem to have trailing characters
114114 return False
115
115
116116 return True
117
117
118118 def get_toc_model(self):
119119 '''
120120 Returns a GtkTreeModel representation of the
121121 Epub table of contents
122 '''
122 '''
123123 return self._navmap.get_gtktreestore()
124
124
125125 def get_flattoc(self):
126126 '''
127127 Returns a flat (linear) list of files to be
128128 rendered.
129 '''
129 '''
130130 return self._navmap.get_flattoc()
131
131
132132 def get_basedir(self):
133133 '''
134134 Returns the base directory where the contents of the
135135 epub has been unzipped
136136 '''
137137 return self._tempdir
138
138
139139 def get_info(self):
140140 '''
141141 Returns a EpubInfo object for the open Epub file
142 '''
142 '''
143143 return self._info
144
144
145145 def close(self):
146146 '''
147 Cleans up (closes open zip files and deletes uncompressed content of Epub.
148 Please call this when a file is being closed or during application exit.
149 '''
147 Cleans up (closes open zip files and deletes uncompressed content of Epub.
148 Please call this when a file is being closed or during application exit.
149 '''
150150 self._zobject.close()
151151 shutil.rmtree(self._tempdir)
66 self._tree = etree.parse(opffile)
77 self._root = self._tree.getroot()
88 self._e_metadata = self._root.find('{http://www.idpf.org/2007/opf}metadata')
9
9
1010 self.title = self._get_title()
1111 self.creator = self._get_creator()
1212 self.date = self._get_date()
1515 self.rights = self._get_rights()
1616 self.identifier = self._get_identifier()
1717 self.language = self._get_language()
18
19
18
19
2020 def _get_data(self, tagname):
2121 element = self._e_metadata.find(tagname)
2222 return element.text
23
23
2424 def _get_title(self):
2525 try:
2626 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}title')
2727 except AttributeError:
2828 return None
29
29
3030 return ret
31
31
3232 def _get_creator(self):
3333 try:
3434 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}creator')
3535 except AttributeError:
36 return None
36 return None
3737 return ret
38
38
3939 def _get_date(self):
4040 #TODO: iter
4141 try:
4242 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}date')
4343 except AttributeError:
4444 return None
45
45
4646 return ret
4747
4848 def _get_source(self):
5050 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}source')
5151 except AttributeError:
5252 return None
53
53
5454 return ret
5555
5656 def _get_rights(self):
5858 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}rights')
5959 except AttributeError:
6060 return None
61
61
6262 return ret
6363
6464 def _get_identifier(self):
6565 #TODO: iter
66 element = self._e_metadata.find('.//{http://purl.org/dc/elements/1.1/}identifier')
66 element = self._e_metadata.find('.//{http://purl.org/dc/elements/1.1/}identifier')
6767
6868 if element is not None:
6969 return {'id':element.get('id'), 'value':element.text}
7575 ret = self._get_data('.//{http://purl.org/dc/elements/1.1/}language')
7676 except AttributeError:
7777 return None
78
78
7979 return ret
8080
8181 def _get_subject(self):
8585 subjectlist.append(element.text)
8686 except AttributeError:
8787 return None
88
89 return subjectlist
88
89 return subjectlist
3636 __gproperties__ = {
3737 'has-selection' : (gobject.TYPE_BOOLEAN, 'whether has selection',
3838 'whether the widget has selection or not',
39 0, gobject.PARAM_READABLE),
39 0, gobject.PARAM_READABLE),
4040 'zoom' : (gobject.TYPE_FLOAT, 'the zoom level',
4141 'the zoom level of the widget',
4242 0.5, 4.0, 1.0, gobject.PARAM_READWRITE)
43 }
43 }
4444 __gsignals__ = {
4545 'page-changed': (gobject.SIGNAL_RUN_FIRST,
4646 gobject.TYPE_NONE,
4747 ([]))
48 }
48 }
4949 def __init__(self):
5050 gobject.threads_init()
5151 gtk.HBox.__init__(self)
52
52
5353 self.connect("destroy", self._destroy_cb)
5454
5555 self._ready = False
6767 self._findjob = None
6868 self.__in_search = False
6969 self.__search_fwd = True
70
70
7171 self._sw = gtk.ScrolledWindow()
7272 self._view = widgets._WebView()
7373 self._view.load_string(LOADING_HTML, 'text/html', 'utf-8', '/')
8181 self._view.connect('button-release-event', self._view_buttonrelease_event_cb)
8282 self._view.connect('selection-changed', self._view_selection_changed_cb)
8383 self._view.connect_after('populate-popup', self._view_populate_popup_cb)
84
84
8585 self._sw.add(self._view)
8686 self._sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
8787 self._v_vscrollbar = self._sw.get_vscrollbar()
9393 self._scrollbar_change_value_cb)
9494 self.pack_start(self._sw, expand = True, fill = True)
9595 self.pack_start(self._scrollbar, expand = False, fill = False)
96
97 self._view.set_flags(gtk.CAN_DEFAULT|gtk.CAN_FOCUS)
98
96
97 self._view.set_flags(gtk.CAN_DEFAULT|gtk.CAN_FOCUS)
98
9999 def set_document(self, epubdocumentinstance):
100100 '''
101101 Sets document (should be a Epub instance)
102 '''
102 '''
103103 self._epub = epubdocumentinstance
104104 gobject.idle_add(self._paginate)
105105
116116 self.__set_zoom(value)
117117 else:
118118 raise AttributeError, 'unknown property %s' % property.name
119
119
120120 def get_has_selection(self):
121121 '''
122122 Returns True if any part of the content is selected
123 '''
123 '''
124124 return self.get_property('has-selection')
125
125
126126 def get_zoom(self):
127127 '''
128128 Returns the current zoom level
129 '''
129 '''
130130 return self.get_property('zoom')
131
131
132132 def set_zoom(self, value):
133133 '''
134134 Sets the current zoom level
135 '''
135 '''
136136 self.set_property('zoom', value)
137
137
138138 def zoom_in(self):
139139 '''
140140 Zooms in (increases zoom level by 0.1)
141 '''
141 '''
142142 if self.can_zoom_in():
143143 self.set_zoom(self.get_zoom() + 0.1)
144144 return True
148148 def zoom_out(self):
149149 '''
150150 Zooms out (decreases zoom level by 0.1)
151 '''
151 '''
152152 if self.can_zoom_out():
153153 self.set_zoom(self.get_zoom() - 0.1)
154154 return True
155155 else:
156156 return False
157
157
158158 def can_zoom_in(self):
159159 '''
160160 Returns True if it is possible to zoom in further
161 '''
161 '''
162162 if self.zoom < 4:
163163 return True
164164 else:
167167 def can_zoom_out(self):
168168 '''
169169 Returns True if it is possible to zoom out further
170 '''
170 '''
171171 if self.zoom > 0.5:
172172 return True
173173 else:
174174 return False
175
175
176176 def get_current_page(self):
177177 '''
178178 Returns the currently loaded page
179 '''
179 '''
180180 return self._loaded_page
181
181
182182 def get_current_file(self):
183183 '''
184184 Returns the currently loaded XML file
185 '''
185 '''
186186 #return self._loaded_filename
187 if self._paginator:
187 if self._paginator:
188188 return self._paginator.get_file_for_pageno(self._loaded_page)
189189 else:
190190 return None
191
191
192192 def get_pagecount(self):
193193 '''
194194 Returns the pagecount of the loaded file
195 '''
195 '''
196196 return self._pagecount
197
197
198198 def set_current_page(self, n):
199199 '''
200200 Loads page number n
201 '''
201 '''
202202 if n < 1 or n > self._pagecount:
203203 return False
204204 self._load_page(n)
205205 return True
206
206
207207 def next_page(self):
208208 '''
209209 Loads next page if possible
210210 Returns True if transition to next page is possible and done
211 '''
211 '''
212212 if self._loaded_page == self._pagecount:
213213 return False
214214 self._load_next_page()
215215 return True
216
216
217217 def previous_page(self):
218218 '''
219219 Loads previous page if possible
220220 Returns True if transition to previous page is possible and done
221 '''
221 '''
222222 if self._loaded_page == 1:
223223 return False
224224 self._load_prev_page()
228228 '''
229229 Scrolls through the pages.
230230 Scrolling is horizontal if horizontal is set to True
231 Valid scrolltypes are: gtk.SCROLL_PAGE_BACKWARD and gtk.SCROLL_PAGE_FORWARD
232 '''
231 Valid scrolltypes are: gtk.SCROLL_PAGE_BACKWARD and gtk.SCROLL_PAGE_FORWARD
232 '''
233233 if scrolltype == gtk.SCROLL_PAGE_BACKWARD:
234234 self.__going_back = True
235235 self.__going_fwd = False
242242 self._view.move_cursor(gtk.MOVEMENT_PAGES, 1)
243243 else:
244244 print ('Got unsupported scrolltype %s' % str(scrolltype))
245
245
246246 def copy(self):
247247 '''
248248 Copies the current selection to clipboard.
249 '''
249 '''
250250 self._view.copy_clipboard()
251
251
252252 def find_next(self):
253253 '''
254254 Highlights the next matching item for current search
255 '''
255 '''
256256 self._view.grab_focus()
257257 self._view.grab_default()
258258
264264 self.__in_search = True
265265 self.__search_fwd = True
266266 self._load_file(path)
267
267
268268 def find_previous(self):
269269 '''
270270 Highlights the previous matching item for current search
271 '''
271 '''
272272 self._view.grab_focus()
273273 self._view.grab_default()
274274
288288 #self._view.search_text(self._findjob.get_search_text(), \
289289 # self._findjob.get_case_sensitive(), True, False)
290290 self.find_next()
291
291
292292 def __set_zoom(self, value):
293293 self._view.set_zoom_level(value)
294294 self.zoom = value
295
295
296296 def __set_has_selection(self, value):
297297 if value != self.has_selection:
298298 self.has_selection = value
299299 self.notify('has-selection')
300
300
301301 def _view_populate_popup_cb(self, view, menu):
302302 menu.destroy() #HACK
303303 return
304
304
305305 def _view_selection_changed_cb(self, view):
306 # FIXME: This does not seem to be implemented in
306 # FIXME: This does not seem to be implemented in
307307 # webkitgtk yet
308308 print view.has_selection()
309
309
310310 def _view_buttonrelease_event_cb(self, view, event):
311311 # Ugly hack
312312 self.__set_has_selection(view.can_copy_clipboard() \
313313 | view.can_cut_clipboard())
314
314
315315 def _view_keypress_event_cb(self, view, event):
316316 name = gtk.gdk.keyval_name(event.keyval)
317 if name == 'Page_Down' or name == 'Down':
317 if name == 'Page_Down' or name == 'Down':
318318 self.__going_back = False
319319 self.__going_fwd = True
320320 elif name == 'Page_Up' or name == 'Up':
321321 self.__going_back = True
322322 self.__going_fwd = False
323
323
324324 self._do_page_transition()
325325
326326 def _view_scroll_event_cb(self, view, event):
331331 self.__going_back = True
332332 self.__going_fwd = False
333333
334 self._do_page_transition()
335
334 self._do_page_transition()
335
336336 def _do_page_transition(self):
337337 if self.__going_fwd:
338338 if self._v_vscrollbar.get_value() >= \
344344 if self._v_vscrollbar.get_value() == self._v_vscrollbar.props.adjustment.props.lower:
345345 self._load_prev_file()
346346 return True
347
347
348348 return False
349
349
350350 def _view_load_finished_cb(self, v, frame):
351
352 # Normally the line below would not be required - ugly workaround for
351
352 # Normally the line below would not be required - ugly workaround for
353353 # possible Webkit bug. See : https://bugs.launchpad.net/bugs/483231
354354 self._sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
355
355
356356 filename = self._view.props.uri.replace('file://', '')
357357 if os.path.exists(filename.replace('xhtml', 'xml')):
358358 filename = filename.replace('xhtml', 'xml') # Hack for making javascript work
359
359
360360 filename = filename.split('#')[0] # Get rid of anchors
361
361
362362 if self._loaded_page < 1 or filename == None:
363363 return False
364
364
365365 self._loaded_filename = filename
366
366
367367 remfactor = self._paginator.get_remfactor_for_file(filename)
368368 pages = self._paginator.get_pagecount_for_file(filename)
369369 extra = int(math.ceil(remfactor * self._view.get_page_height()/(pages-remfactor)))
370370 if extra > 0:
371371 self._view.add_bottom_padding(extra)
372
372
373373 if self.__in_search:
374374 self._view.search_text(self._findjob.get_search_text(), \
375375 self._findjob.get_case_sensitive(), \
381381 self._scroll_page_end()
382382 else:
383383 self._scroll_page()
384
384
385385 base_pageno = self._paginator.get_base_pageno_for_file(filename)
386386 scrollval = self._v_vscrollbar.get_value()
387387 scroll_upper = self._v_vscrollbar.props.adjustment.props.upper
391391 else:
392392 offset = (scrollval/scroll_upper) * self._paginator.get_pagecount_for_file(filename)
393393 pageno = math.floor(base_pageno + offset)
394
394
395395 if pageno != self._loaded_page:
396396 self._on_page_changed(int(pageno))
397
397
398398
399399 def _scroll_page_end(self):
400400 v_upper = self._v_vscrollbar.props.adjustment.props.upper
401401 v_page_size = self._v_vscrollbar.props.adjustment.props.page_size
402402 self._v_vscrollbar.set_value(v_upper)
403
403
404404 def _scroll_page(self):
405405 pageno = self._loaded_page
406
406
407407 v_upper = self._v_vscrollbar.props.adjustment.props.upper
408408 v_page_size = self._v_vscrollbar.props.adjustment.props.page_size
409
409
410410 scrollfactor = self._paginator.get_scrollfactor_pos_for_pageno(pageno)
411411 self._v_vscrollbar.set_value((v_upper - v_page_size) * scrollfactor)
412
412
413413 def _paginate(self):
414414 filelist = []
415415 for i in self._epub._navmap.get_flattoc():
416416 filelist.append(os.path.join(self._epub._tempdir, i))
417
417
418418 self._paginator = _Paginator(filelist)
419419 self._paginator.connect('paginated', self._paginated_cb)
420
420
421421 def _load_next_page(self):
422422 self._load_page(self._loaded_page + 1)
423423
424424 def _load_prev_page(self):
425425 self._load_page(self._loaded_page - 1)
426
426
427427 def _v_scrollbar_value_changed_cb(self, scrollbar):
428428 if self._loaded_page < 1:
429429 return
456456
457457 if scrollfactor <= scrollfactor_cur:
458458 self._on_page_changed(self._loaded_page - 1)
459
459
460460 def _on_page_changed(self, pageno):
461461 self.__page_changed = True
462462 self._loaded_page = pageno
464464 self._scrollbar.set_value(pageno)
465465 self._scrollbar.handler_unblock(self._scrollbar_change_value_cb_id)
466466 self.emit('page-changed')
467
467
468468 def _load_page(self, pageno):
469469 if pageno > self._pagecount or pageno < 1:
470470 #TODO: Cause an exception
482482 self._view.open(filename)
483483 else:
484484 self._scroll_page()
485
485
486486 def _load_next_file(self):
487487 if self._loaded_page == self._pagecount:
488488 return
492492 pageno += 1
493493 if self._paginator.get_file_for_pageno(pageno) != cur_file:
494494 break
495
495
496496 self._load_page(pageno)
497497
498498 def _load_file(self, path):
512512 pageno -= 1
513513 if self._paginator.get_file_for_pageno(pageno) != cur_file:
514514 break
515
515
516516 self._load_page(pageno)
517517
518518 def _scrollbar_change_value_cb(self, range, scrolltype, value):
525525 self.__going_fwd = False
526526 self.__going_back = True
527527 if not self._do_page_transition():
528 self._view.move_cursor(gtk.MOVEMENT_DISPLAY_LINES, -1)
528 self._view.move_cursor(gtk.MOVEMENT_DISPLAY_LINES, -1)
529529 elif scrolltype == gtk.SCROLL_JUMP or \
530530 scrolltype == gtk.SCROLL_PAGE_FORWARD or \
531531 scrolltype == gtk.SCROLL_PAGE_BACKWARD:
535535 self._load_page(round(value))
536536 else:
537537 print 'Warning: unknown scrolltype %s with value %f' % (str(scrolltype), value)
538
538
539539 self._scrollbar.set_value(self._loaded_page) #FIXME: This should not be needed here
540
540
541541 if self.__page_changed == True:
542542 self.__page_changed = False
543543 return False
544544 else:
545545 return True
546
546
547547 def _paginated_cb(self, object):
548548 self._ready = True
549
549
550550 self._pagecount = self._paginator.get_total_pagecount()
551551 self._scrollbar.set_range(1.0, self._pagecount - 1.0)
552552 self._scrollbar.set_increments(1.0, 1.0)
554554 self._view.grab_default()
555555 if self._loaded_page < 1:
556556 self._load_page(1)
557
558
557
558
559559
560560 def _destroy_cb(self, widget):
561561 self._epub.close()
5656 if self._searchfile(f):
5757 self.obj._matchfilelist.append(entry)
5858 f.close()
59
59
6060 gtk.gdk.threads_enter()
61 self.obj._finished = True
61 self.obj._finished = True
6262 self.obj.emit('updated')
6363 gtk.gdk.threads_leave()
64
64
6565 return False
66
66
6767 def _searchfile(self, fileobj):
6868 soup = BeautifulSoup.BeautifulSoup(fileobj)
6969 body = soup.find('body')
7070 tags = body.findChildren(True)
7171 for tag in tags:
72 if not tag.string is None:
72 if not tag.string is None:
7373 if tag.string.find(self.obj._text) > -1:
7474 return True
75
75
7676 return False
7777
7878 def run (self):
7979 self._start_search()
80
80
8181 def stop(self):
8282 self.stopthread.set()
8383
8888 'paginated': (gobject.SIGNAL_RUN_FIRST,
8989 gobject.TYPE_NONE,
9090 ([]))
91 }
91 }
9292 def __init__(self, filelist):
9393 gobject.GObject.__init__(self)
94
94
9595 self._filelist = filelist
9696 self._filedict = {}
9797 self._pagemap = {}
98
98
9999 self._bookheight = 0
100100 self._count = 0
101101 self._pagecount = 0
102
102
103103 self._screen = gtk.gdk.screen_get_default()
104104 self._old_fontoptions = self._screen.get_font_options()
105105 options = cairo.FontOptions()
108108 options.set_subpixel_order(cairo.SUBPIXEL_ORDER_DEFAULT)
109109 options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
110110 self._screen.set_font_options(options)
111
111
112112 self._temp_win = gtk.Window()
113113 self._temp_view = widgets._WebView()
114114
123123 settings.props.default_font_size = 12
124124 settings.props.default_monospace_font_size = 10
125125 settings.props.default_encoding = 'utf-8'
126
126
127127 sw = gtk.ScrolledWindow()
128128 sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
129129 self._dpi = 96
131131 sw.add(self._temp_view)
132132 self._temp_win.add(sw)
133133 self._temp_view.connect('load-finished', self._page_load_finished_cb)
134
134
135135 self._temp_win.show_all()
136136 self._temp_win.unmap()
137
137
138138 self._temp_view.open(self._filelist[self._count])
139
139
140140 def _page_load_finished_cb(self, v, frame):
141141 f = v.get_main_frame()
142142 pageheight = v.get_page_height()
143
143
144144 if pageheight <= _mm_to_pixel(PAGE_HEIGHT, self._dpi):
145145 pages = 1
146146 else:
151151 else:
152152 pagelen = 1/pages
153153 self._pagemap[float(self._pagecount + i)] = (f.props.uri, (i-1)/math.ceil(pages), pagelen)
154
154
155155 self._pagecount += math.ceil(pages)
156156 self._filedict[f.props.uri.replace('file://', '')] = (math.ceil(pages), math.ceil(pages) - pages)
157157 self._bookheight += pageheight
158
158
159159 if self._count+1 >= len(self._filelist):
160160 self._temp_win.destroy()
161161 self._screen.set_font_options(self._old_fontoptions)
163163 else:
164164 self._count += 1
165165 self._temp_view.open(self._filelist[self._count])
166
167
166
167
168168 def get_file_for_pageno(self, pageno):
169169 '''
170170 Returns the file in which pageno occurs
171 '''
171 '''
172172 return self._pagemap[pageno][0]
173
173
174174 def get_scrollfactor_pos_for_pageno(self, pageno):
175175 '''
176176 Returns the position scrollfactor (fraction) for pageno
177 '''
177 '''
178178 return self._pagemap[pageno][1]
179179
180180 def get_scrollfactor_len_for_pageno(self, pageno):
181181 '''
182182 Returns the length scrollfactor (fraction) for pageno
183 '''
183 '''
184184 return self._pagemap[pageno][2]
185
185
186186 def get_pagecount_for_file(self, filename):
187187 '''
188188 Returns the number of pages in file
189 '''
189 '''
190190 return self._filedict[filename][0]
191191
192192 def get_base_pageno_for_file(self, filename):
193193 '''
194194 Returns the pageno which begins in filename
195 '''
195 '''
196196 for key in self._pagemap.keys():
197197 if self._pagemap[key][0].replace('file://', '') == filename:
198198 return key
199
199
200200 return None
201201
202202 def get_remfactor_for_file(self, filename):
203203 '''
204204 Returns the remainder factor (1 - fraction length of last page in file)
205 '''
205 '''
206206 return self._filedict[filename][1]
207
207
208208 def get_total_pagecount(self):
209209 '''
210210 Returns the total pagecount for the Epub file
214214 def get_total_height(self):
215215 '''
216216 Returns the total height of the Epub in pixels
217 '''
217 '''
218218 return self._bookheight
219219
220220
227227 def __init__(self, document, start_page, n_pages, text, case_sensitive=False):
228228 gobject.GObject.__init__(self)
229229 gtk.gdk.threads_init()
230
230
231231 self._finished = False
232232 self._document = document
233233 self._start_page = start_page
238238 self._matchfilelist = []
239239 self._current_file_index = 0
240240 self.threads = []
241
241
242242 s_thread = SearchThread(self)
243243 self.threads.append(s_thread)
244244 s_thread.start()
245
245
246246 def cancel(self):
247247 '''
248248 Cancels the search job
249 '''
249 '''
250250 for s_thread in self.threads:
251251 s_thread.stop()
252
252
253253 def is_finished(self):
254254 '''
255255 Returns True if the entire search job has been finished
256 '''
256 '''
257257 return self._finished
258
258
259259 def get_next_file(self):
260260 '''
261261 Returns the next file which has the search pattern
262 '''
262 '''
263263 self._current_file_index += 1
264264 try:
265265 path = self._matchfilelist[self._current_file_index]
266266 except IndexError:
267267 self._current_file_index = 0
268268 path = self._matchfilelist[self._current_file_index]
269
269
270270 return path
271271
272272 def get_prev_file(self):
273273 '''
274274 Returns the previous file which has the search pattern
275 '''
275 '''
276276 self._current_file_index -= 1
277277 try:
278278 path = self._matchfilelist[self._current_file_index]
279279 except IndexError:
280280 self._current_file_index = -1
281281 path = self._matchfilelist[self._current_file_index]
282
282
283283 return path
284284
285285 def get_search_text(self):
286286 '''
287287 Returns the search text
288 '''
288 '''
289289 return self._text
290
290
291291 def get_case_sensitive(self):
292292 '''
293293 Returns True if the search is case-sensitive
294 '''
294 '''
295295 return self._case_sensitive
44 def __init__(self, label, contentsrc, children = []):
55 self._label = label
66 self._contentsrc = contentsrc
7 self._children = children
8
7 self._children = children
8
99 def get_label(self):
1010 return self._label
11
11
1212 def get_contentsrc(self):
1313 return self._contentsrc
14
14
1515 def get_children(self):
1616 return self._children
1717
2424 self._root = self._tree.getroot()
2525 self._gtktreestore = gtk.TreeStore(str, str)
2626 self._flattoc = []
27
27
2828 self._populate_flattoc()
2929 self._populate_toc()
30
30
3131 def _populate_flattoc(self):
3232 tree = etree.parse(self._opffile)
3333 root = tree.getroot()
34
34
3535 itemmap = {}
3636 manifest = root.find('.//{http://www.idpf.org/2007/opf}manifest')
3737 for element in manifest.iterfind('{http://www.idpf.org/2007/opf}item'):
3838 itemmap[element.get('id')] = element
39
40 spine = root.find('.//{http://www.idpf.org/2007/opf}spine')
39
40 spine = root.find('.//{http://www.idpf.org/2007/opf}spine')
4141 for element in spine.iterfind('{http://www.idpf.org/2007/opf}itemref'):
4242 idref = element.get('idref')
4343 href = itemmap[idref].get('href')
4444 self._flattoc.append(self._basepath + href)
45
45
4646 self._opffile.close()
47
47
4848 def _populate_toc(self):
49 navmap = self._root.find('{http://www.daisy.org/z3986/2005/ncx/}navMap')
49 navmap = self._root.find('{http://www.daisy.org/z3986/2005/ncx/}navMap')
5050 for navpoint in navmap.iterfind('./{http://www.daisy.org/z3986/2005/ncx/}navPoint'):
5151 self._process_navpoint(navpoint)
52
52
5353 def _gettitle(self, navpoint):
5454 text = navpoint.find('./{http://www.daisy.org/z3986/2005/ncx/}navLabel/{http://www.daisy.org/z3986/2005/ncx/}text')
5555 return text.text
6161 def _process_navpoint(self, navpoint, parent = None):
6262 title = self._gettitle(navpoint)
6363 content = self._getcontent(navpoint)
64
64
6565 #print title, content
66
66
6767 iter = self._gtktreestore.append(parent, [title, content])
6868 #self._flattoc.append((title, content))
69
69
7070 childnavpointlist = list(navpoint.iterfind('./{http://www.daisy.org/z3986/2005/ncx/}navPoint'))
71
71
7272 if len(childnavpointlist):
7373 for childnavpoint in childnavpointlist:
74 self._process_navpoint(childnavpoint, parent = iter)
75 else:
74 self._process_navpoint(childnavpoint, parent = iter)
75 else:
7676 return
77
77
7878 def get_gtktreestore(self):
7979 '''
8080 Returns a GtkTreeModel representation of the
8181 Epub table of contents
82 '''
82 '''
8383 return self._gtktreestore
84
84
8585 def get_flattoc(self):
8686 '''
8787 Returns a flat (linear) list of files to be
8888 rendered.
89 '''
89 '''
9090 return self._flattoc
91
92 #t = TocParser('/home/sayamindu/Desktop/Test/OPS/fb.ncx')
91
92 #t = TocParser('/home/sayamindu/Desktop/Test/OPS/fb.ncx')
44 class _WebView(webkit.WebView):
55 def __init__(self):
66 webkit.WebView.__init__(self)
7
7
88 def get_page_height(self):
99 '''
1010 Gets height (in pixels) of loaded (X)HTML page.
1111 This is done via javascript at the moment
12 '''
12 '''
1313 #TODO: Need to check status of page load
1414 js = 'oldtitle=document.title;document.title=Math.max(document.body.scrollHeight, document.body.offsetHeight,document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);'
1515 self.execute_script(js)
1919 if ret is None:
2020 return 0
2121 return int(ret)
22
22
2323 def add_bottom_padding(self, incr):
2424 '''
2525 Adds incr pixels of padding to the end of the loaded (X)HTML page.
2626 This is done via javascript at the moment
27 '''
27 '''
2828 js = ('var newdiv = document.createElement("div");newdiv.style.height = "%dpx";document.body.appendChild(newdiv);' % incr)
2929 self.execute_script(js)
30
30
7171 return float(xft_dpi / 1024)
7272
7373 def get_md5(filename): #FIXME: Should be moved somewhere else
74 filename = filename.replace('file://', '') #XXX: hack
74 filename = filename.replace('file://', '') #XXX: hack
7575 fh = open(filename)
7676 digest = md5.new()
7777 while 1:
132132 if hasattr(evince, 'evince_embed_init'):
133133 # if we use evince-2.24
134134 evince.evince_embed_init()
135
135
136136 self._epub = False
137137 self._document = None
138138 self._fileserver = None
143143 self.connect('window-state-event', self._window_state_event_cb)
144144
145145 _logger.debug('Starting Read...')
146
146
147147 self._view = None
148
148
149149 self._sidebar = Sidebar()
150150 self._sidebar.show()
151151
228228 spacer.show()
229229
230230 bookmark_item = gtk.ToolItem()
231 self._bookmarker = self._create_bookmarker()
231 self._bookmarker = self._create_bookmarker()
232232 self._bookmarker_toggle_handler_id = self._bookmarker.connect( \
233233 'toggled', self.__bookmarker_toggled_cb)
234234 bookmark_item.add(self._bookmarker)
330330 back.props.sensitive = False
331331 palette = back.get_palette()
332332 previous_page = MenuItem(text_label= _("Previous page"))
333 palette.menu.append(previous_page)
334 previous_page.show_all()
333 palette.menu.append(previous_page)
334 previous_page.show_all()
335335 previous_bookmark = MenuItem(text_label= _("Previous bookmark"))
336 palette.menu.append(previous_bookmark)
336 palette.menu.append(previous_bookmark)
337337 previous_bookmark.show_all()
338338 back.connect('clicked', self.__go_back_cb)
339339 previous_page.connect('activate', self.__go_back_page_cb)
346346 forward.props.sensitive = False
347347 palette = forward.get_palette()
348348 next_page = MenuItem(text_label= _("Next page"))
349 palette.menu.append(next_page)
350 next_page.show_all()
349 palette.menu.append(next_page)
350 next_page.show_all()
351351 next_bookmark = MenuItem(text_label= _("Next bookmark"))
352 palette.menu.append(next_bookmark)
352 palette.menu.append(next_bookmark)
353353 next_bookmark.show_all()
354354 forward.connect('clicked', self.__go_forward_cb)
355355 next_page.connect('activate', self.__go_forward_page_cb)
372372
373373 label_attributes = pango.AttrList()
374374 label_attributes.insert(pango.AttrSize(14000, 0, -1))
375 label_attributes.insert(pango.AttrForeground(65535, 65535,
375 label_attributes.insert(pango.AttrForeground(65535, 65535,
376376 65535, 0, -1))
377377 total_page_label.set_attributes(label_attributes)
378378
379379 total_page_label.set_text(' / 0')
380380 return total_page_label
381
381
382382 def _create_navigator(self):
383383 navigator = gtk.ComboBox()
384384 navigator.set_add_tearoffs(True)
391391 def _create_bookmarker(self):
392392 bookmarker = ToggleToolButton('emblem-favorite')
393393 return bookmarker
394
394
395395 def __num_page_entry_insert_text_cb(self, entry, text, length, position):
396396 if not re.match('[0-9]', text):
397397 entry.emit_stop_by_name('insert-text')
411411
412412 self._document.get_page_cache().set_current_page(page)
413413 entry.props.text = str(page + 1)
414
414
415415 def __go_back_cb(self, button):
416416 self._view.scroll(gtk.SCROLL_PAGE_BACKWARD, False)
417417
420420
421421 def __go_back_page_cb(self, button):
422422 self._view.previous_page()
423
423
424424 def __go_forward_page_cb(self, button):
425425 self._view.next_page()
426426
427427 def __prev_bookmark_activate_cb(self, menuitem):
428428 page = self._document.get_page_cache().get_current_page()
429429 bookmarkmanager = self._sidebar.get_bookmarkmanager()
430
430
431431 prev_bookmark = bookmarkmanager.get_prev_bookmark_for_page(page)
432432 if prev_bookmark is not None:
433433 self._document.get_page_cache().set_current_page(prev_bookmark.page_no)
435435 def __next_bookmark_activate_cb(self, menuitem):
436436 page = self._document.get_page_cache().get_current_page()
437437 bookmarkmanager = self._sidebar.get_bookmarkmanager()
438
438
439439 next_bookmark = bookmarkmanager.get_next_bookmark_for_page(page)
440440 if next_bookmark is not None:
441441 self._document.get_page_cache().set_current_page(next_bookmark.page_no)
445445 if self._bookmarker.props.active:
446446 self._sidebar.add_bookmark(page)
447447 else:
448 self._sidebar.del_bookmark(page)
448 self._sidebar.del_bookmark(page)
449449
450450 def __page_changed_cb(self, page, proxy = None):
451451 self._update_nav_buttons()
452452 if hasattr(self._document, 'has_document_links'):
453453 if self._document.has_document_links():
454454 self._toc_select_active_page()
455
455
456456 self._sidebar.update_for_page(self._document.get_page_cache().get_current_page())
457457
458458 self._bookmarker.handler_block(self._bookmarker_toggle_handler_id)
459459 self._bookmarker.props.active = self._sidebar.is_showing_local_bookmark()
460460 self._bookmarker.handler_unblock(self._bookmarker_toggle_handler_id)
461
461
462462 def _update_nav_buttons(self):
463463 current_page = self._document.get_page_cache().get_current_page()
464464 self._back_button.props.sensitive = current_page > 0
465465 self._forward_button.props.sensitive = \
466466 current_page < self._document.get_n_pages() - 1
467
467
468468 self._num_page_entry.props.text = str(current_page + 1)
469469 self._total_page_label.props.label = \
470470 ' / ' + str(self._document.get_n_pages())
509509
510510 def _toc_select_active_page(self):
511511 iter = self._navigator.get_active_iter()
512
512
513513 current_link = self._toc_model.get(iter, 1)[0]
514514 current_page = self._document.get_page_cache().get_current_page()
515515
533533 """
534534 if not self._want_document:
535535 return
536 chooser = ObjectChooser(_('Choose document'), self,
537 gtk.DIALOG_MODAL |
536 chooser = ObjectChooser(_('Choose document'), self,
537 gtk.DIALOG_MODAL |
538538 gtk.DIALOG_DESTROY_WITH_PARENT,
539539 what_filter=mime.GENERIC_TYPE_TEXT)
540540 try:
541541 result = chooser.run()
542542 if result == gtk.RESPONSE_ACCEPT:
543 logging.debug('ObjectChooser: %r' %
543 logging.debug('ObjectChooser: %r' %
544544 chooser.get_selected_object())
545545 jobject = chooser.get_selected_object()
546546 if jobject and jobject.file_path:
599599
600600 def write_file(self, file_path):
601601 """Write into datastore for Keep.
602
602
603603 The document is saved by hardlinking from the temporary file we
604604 keep around instead of "saving".
605605
606606 The metadata is updated, including current page, view settings,
607607 search text.
608
608
609609 """
610610 if self._tempfile is None:
611611 # Workaround for closing Read with no document loaded
649649
650650 def can_close(self):
651651 """Prepare to cleanup on closing.
652
652
653653 Called from self.close()
654654 """
655655 self._close_requested = True
680680 # FIXME: Draw a progress bar
681681 if self._download_content_length > 0:
682682 _logger.debug("Downloaded %u of %u bytes from tube %u...",
683 bytes_downloaded, self._download_content_length,
683 bytes_downloaded, self._download_content_length,
684684 tube_id)
685685 else:
686686 _logger.debug("Downloaded %u bytes from tube %u...",
785785 """Load the specified document and set up the UI.
786786
787787 filepath -- string starting with file://
788
788
789789 """
790790 mimetype = mime.get_for_file(filepath)
791791 if mimetype == 'application/epub+zip':
815815
816816 self._update_nav_buttons()
817817 self._update_toc()
818
818
819819 page_cache = self._document.get_page_cache()
820820 page_cache.connect('page-changed', self.__page_changed_cb)
821821
2525 self.nick = data[4]
2626 self.color = data[5]
2727 self.local = data[6]
28
28
2929 def belongstopage(self, page_no):
30 return self.page_no == page_no
31
30 return self.page_no == page_no
31
3232 def is_local(self):
3333 return bool(self.local)
3434
4242 def get_note_body(self):
4343 if self.content == '' or self.content is None:
4444 return ''
45
45
4646 note = cjson.decode(self.content)
4747 return note['body']
48
4948
49
5050 #Situation 2: DB is outdated
5151 if not os.path.exists(dbpath) and os.path.exists(olddbpath):
5252 shutil.copy(olddbpath, dbpath)
53
53
5454 conn = sqlite3.connect(dbpath)
5555 conn.execute("CREATE TABLE temp_bookmarks AS SELECT md5, page, title 'content', timestamp, user, color, local FROM bookmarks")
5656 conn.execute("ALTER TABLE bookmarks RENAME TO bookmarks_old")
7575 self._conn = sqlite3.connect(dbpath)
7676 self._conn.text_factory = lambda x: unicode(x, "utf-8", "ignore")
7777
78
78
7979 self._bookmarks = []
8080 self._populate_bookmarks()
81
81
8282 def add_bookmark(self, page, content, local=1):
83 # locale = 0 means that this is a bookmark originally
83 # locale = 0 means that this is a bookmark originally
8484 # created by the person who originally shared the file
8585 timestamp = time.time()
8686 client = gconf.client_get_default()
9090 t = (self._filehash, page, content, timestamp, user, color, local)
9191 self._conn.execute('insert into bookmarks values (?, ?, ?, ?, ?, ?, ?)', t)
9292 self._conn.commit()
93
93
9494 self._resync_bookmark_cache()
95
95
9696 def del_bookmark(self, page):
9797 client = gconf.client_get_default()
9898 user = client.get_string("/desktop/sugar/user/nick")
9999
100100 # We delete only the locally made bookmark
101
101
102102 t = (self._filehash, page, user)
103103 self._conn.execute('delete from bookmarks where md5=? and page=? and user=?', t)
104104 self._conn.commit()
105
105
106106 self._resync_bookmark_cache()
107107
108108 def _populate_bookmarks(self):
111111
112112 for row in rows:
113113 self._bookmarks.append(Bookmark(row))
114
114
115115 def get_bookmarks_for_page(self, page):
116116 bookmarks = []
117117 for bookmark in self._bookmarks:
118118 if bookmark.belongstopage(page):
119119 bookmarks.append(bookmark)
120
120
121121 return bookmarks
122
122
123123 def _resync_bookmark_cache(self):
124124 # To be called when a new bookmark has been added/removed
125125 self._bookmarks = []
129129 def get_prev_bookmark_for_page(self, page, wrap = True):
130130 if not len(self._bookmarks):
131131 return None
132
132
133133 if page <= self._bookmarks[0].page_no and wrap:
134134 return self._bookmarks[-1]
135135 else:
137137 for bookmark in self._bookmarks:
138138 if bookmark.belongstopage(i):
139139 return bookmark
140
141 return None
140
141 return None
142142
143143
144144 def get_next_bookmark_for_page(self, page, wrap = True):
145145 if not len(self._bookmarks):
146146 return None
147
147
148148 if page >= self._bookmarks[-1].page_no and wrap:
149149 return self._bookmarks[0]
150150 else:
152152 for bookmark in self._bookmarks:
153153 if bookmark.belongstopage(i):
154154 return bookmark
155
156 return None
155
156 return None
22 # Stolen from the PyGTK demo module by Maik Hertha <maik.hertha@berlin.de>
33
44 import gtk
5 import gobject
5 import gobject
66
77 from sugar.graphics import style
88 from sugar.graphics.toolbutton import ToolButton
5555 accept.connect('clicked', self.accept_clicked_cb)
5656 accept.show()
5757 self.toolbar.insert(accept, -1)
58
58
5959 _vbox.pack_start(self.toolbar, expand=False)
6060 self.toolbar.show()
6161
164164 def accept_clicked_cb(self, widget):
165165 title = self._title_entry.get_text()
166166 details = self._content_entry.get_buffer().props.text
167 content = {'title' : unicode(title), 'body' : unicode(details)}
167 content = {'title' : unicode(title), 'body' : unicode(details)}
168168 self._sidebarinstance._real_add_bookmark(self._page, cjson.encode(content))
169169 self.destroy()
170170
175175 def accept_clicked_cb(self, widget):
176176 title = self._title_entry.get_text()
177177 details = self._content_entry.get_buffer().props.text
178 content = {'title' : unicode(title), 'body' : unicode(details)}
178 content = {'title' : unicode(title), 'body' : unicode(details)}
179179 self._sidebarinstance.del_bookmark(self._page)
180180 self._sidebarinstance._real_add_bookmark(self._page, cjson.encode(content))
181181 self.destroy()
4848
4949 self._box.show()
5050 self.show()
51
51
5252 self._bookmark_icon = None
5353 self._bookmark_manager = None
5454 self._is_showing_local_bookmark = False
7373
7474 if bookmark.is_local():
7575 self._is_showing_local_bookmark = True
76
76
7777 def __bookmark_icon_query_tooltip_cb(self, widget, x, y, keyboard_mode, tip, bookmark):
7878 tooltip_header = bookmark.get_note_title()
7979 tooltip_body = bookmark.get_note_body()
111111 tip.set_custom(vbox)
112112
113113 return True
114
114
115115 def __event_cb(self, widget, event, bookmark):
116116 if event.type == gtk.gdk.BUTTON_PRESS and \
117117 self._bookmark_icon is not None:
135135
136136 self._bookmark_icon.hide() #XXX: Is this needed??
137137 self._bookmark_icon.destroy()
138
138
139139 self._bookmark_icon = None
140
140
141141 self._is_showing_local_bookmark = False
142
142
143143 def set_bookmarkmanager(self, filehash):
144144 self._bookmark_manager = BookmarkManager(filehash)
145
145
146146 def get_bookmarkmanager(self):
147147 return (self._bookmark_manager)
148
148
149149 def update_for_page(self, page):
150150 self._clear_bookmarks()
151151 if self._bookmark_manager is None:
152152 return
153
153
154154 bookmarks = self._bookmark_manager.get_bookmarks_for_page(page)
155
155
156156 for bookmark in bookmarks:
157157 self._add_bookmark_icon(bookmark)
158
158
159159 def add_bookmark(self, page):
160160 bookmark_title = (_("%s's bookmark") % profile.get_nick_name())
161161 bookmark_content = (_("Bookmark for page %d") % page)
169169 def _real_add_bookmark(self, page, content):
170170 self._bookmark_manager.add_bookmark(page, unicode(content))
171171 self.update_for_page(page)
172
172
173173 def del_bookmark(self, page):
174174 self._bookmark_manager.del_bookmark(page)
175175 self.update_for_page(page)
176
176
177177 def is_showing_local_bookmark(self):
178178 return self._is_showing_local_bookmark
179179
140140 self._search_find_last()
141141 else:
142142 self._search_find_prev()
143
143
144144 def _find_next_cb(self, button):
145145 if self._search_entry_changed:
146146 self._search_find_first()
181181
182182 self._evince_view = None
183183 self._document = None
184
184
185185 self._zoom_out = ToolButton('zoom-out')
186186 self._zoom_out.set_tooltip(_('Zoom out'))
187187 self._zoom_out.connect('clicked', self._zoom_out_cb)
193193 self._zoom_in.connect('clicked', self._zoom_in_cb)
194194 self.insert(self._zoom_in, -1)
195195 self._zoom_in.show()
196
196
197197 self._zoom_to_width = ToolButton('zoom-best-fit')
198198 self._zoom_to_width.set_tooltip(_('Zoom to width'))
199199 self._zoom_to_width.connect('clicked', self._zoom_to_width_cb)
249249 self._view_notify_zoom_handler = self._evince_view.connect(
250250 'notify::zoom', self._view_notify_zoom_cb)
251251
252 self._update_zoom_buttons()
252 self._update_zoom_buttons()
253253
254254
255255 def _zoom_spin_notify_value_cb(self, zoom_spin, pspec):
286286 self._evince_view.props.sizing_mode = evince.SIZING_FREE
287287 self._evince_view.zoom_out()
288288 self._update_zoom_buttons()
289
289
290290 def _zoom_out_cb(self, button):
291291 self.zoom_out()
292292
4545
4646 def __init__(self, udi):
4747 gobject.GObject.__init__(self)
48
48
4949 bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM)
5050 proxy = bus.get_object('org.freedesktop.Hal', udi,
5151 follow_name_owner_changes=True)
9191
9292 def do_get_property(self, pspec):
9393 if pspec.name == 'level':
94 return self._level
94 return self._level
9595 if pspec.name == 'charging':
9696 return self._charging
9797 if pspec.name == 'discharging':
173173 if self._battery is not None:
174174 icon_name = get_icon_state(_ICON_NAME, self._battery.props.level, step=-5)
175175 self._icon = Icon(icon_name=icon_name)
176 self.pack_start(self._icon, expand = False, fill = False)
176 self.pack_start(self._icon, expand = False, fill = False)
177177
178178 def _battery_level_changed_cb(self, pspec, param):
179179 icon_name = get_icon_state(_ICON_NAME, self._battery.props.level, step=-5)
198198
199199 #TRANS: Translate this as Page i of m (eg: Page 4 of 334)
200200 self._progressbar.set_text(_("Page %i of %i") % (current_page, n_pages))
201
202
203
201
202
203