Closed mfrasca closed 8 years ago
pictures are now loaded using the gtk.gdk.pixbuf_new_from_file
function, which takes one string parameter, the local name of the image file.
A
gtk.gdk.PixbufLoader
provides a way for applications to drive the process of loading an image [...] it should be used when reading an image from a (potentially) slow network connection [...]
http://www.pygtk.org/pygtk2reference/class-gdkpixbufloader.html
so, yes, it does get a bit complicated, but it also solves a problem I have been ignoring: I should be reading the files asynchronously, so that the interface does not lock (as it does now) while reading the pictures from file. I cannot yet estimate the impact on the code.
just some working thoughts...
#!/usr/bin/env python
import gtk
import gtk.glade
import gtk.gdk
import urllib
import contextlib
import threading
import gobject
def read_in_chunks(file_object, chunk_size=1024):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data
class ImageLoader(threading.Thread):
def __init__(self, box, url, *args, **kwargs):
super(ImageLoader, self).__init__(*args, **kwargs)
self.box = box
self.url = url
self.is_global = (url.startswith('http://') or
url.startswith('https://'))
def callback(self):
print 'in callback',
self.image.set_from_pixbuf(self.loader.get_pixbuf())
self.image.show()
def loader_closed(self, pixbufloader):
print 'done-loading',
gobject.idle_add(self.callback)
def loader_area_prepared(self, pixbufloader):
print 'done-preparing',
gobject.idle_add(self.callback)
def run(self):
self.loader = gtk.gdk.PixbufLoader()
self.loader.connect("area-prepared", self.loader_area_prepared)
self.loader.connect("closed", self.loader_closed)
self.image = image = gtk.Image()
self.box.pack_start(image)
if self.is_global:
self.read_global_url()
else:
self.read_local_url()
self.loader.close()
def read_global_url(self):
with contextlib.closing(urllib.urlopen(self.url)) as f:
for piece in read_in_chunks(f, 128):
print '.',
self.loader.write(piece)
def read_local_url(self):
with open(self.url) as f:
for piece in read_in_chunks(f, 128):
print '.',
self.loader.write(piece)
class MainWindow:
def __init__(self):
xml = gtk.glade.XML('hw.glade')
self.window = xml.get_widget('window')
self.window.connect("delete_event", gtk.main_quit)
button = xml.get_widget('button')
button.connect("clicked", self.on_button_clicked)
self.box = xml.get_widget('vbox1')
self.poked = 0
self.window.show_all()
def on_button_clicked(self, w, *args):
w.set_label("you poked me" + ("!" * self.poked))
self.poked += 1
w.connect("clicked", gtk.main_quit)
w = MainWindow()
ImageLoader(w.box, 'https://developer.gnome.org/skin/'
'gnome-logo-devcenter.png').start()
ImageLoader(w.box, 'index.jpeg').start()
gtk.main()
todo:
The pictures
property works as it works now, that is it returns a list of gtk.Image
objects.
The difference that it also spawns a thread that will update the objects returned.
the image loading thread updates the image on area-prepared
and on closed
signals from the PixbufLoader
.
I see a possible problem in the fact that an Image
should be somewhere in the view before you can show it from the two above callbacks.
but it really does not need look much more complicated than:
for n in self.notes:
url = is_absolute(n.note) and n.note or os.path.join(pfolder, n.note)
im = gtk.Image()
ImageLoader(im, url).start()
result.append(im)
where the ImageLoader
could look like the thing in the previous comment.
I like this... I like how I can link in some images at species level from ALA or Wikipedia etc. that may be helpful for ID reasons (say a picture of the leaves and a picture of the bark, what have you) I don't need to host these locally and I can still have my local pictures at plant level. Great! Not sure how much I'll use it (time constraints wise). Might be useful for those I find hard to ID?
from comments in #245 @tmyersdn
@RoDuth
yes quite interesting.
what do you expect Bauble to do if you put a note containing a URL of a picture? like you enter —sorry if initially this has to be totally manual— a note with category
<picture>
and as text a URL and Bauble grabs it from the net and shows it as if it was a locally stored picture.