"""
Flickr photo search for Deskbar
Copyright (C) 2007 Fabio Corneti
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
A full copy of the GPL can be found at this URL:
http://www.fsf.org/licensing/licenses/gpl.txt
Initial ideas and stucture for this plugin provided by desklicious, included in the standard Deskbar plugins.
"""
import os, cgi, os.path, deskbar, deskbar.Match, deskbar.Handler, deskbar.Utils
import gnomevfs, gtk, gconf
from gettext import gettext as _
import xml.dom.minidom, urllib
VERSION='0.1.1'
FLICKR_REQUEST_TEMPLATE = 'http://api.flickr.com/services/feeds/photos_public.gne?tags=%s&format=rss_200'
GCONF_MAX_RESULTS = deskbar.GCONF_DIR + '/flickr/maxresults'
QUERY_DELAY = 1
THUMBNAIL_WIDTH = 75
MAX_RESULTS_RANGE_MAX = 64;
_debug=True
if _debug:
import traceback
def _check_requirements():
return (deskbar.Handler.HANDLER_IS_CONFIGURABLE, _("You can set the maximum number of results to return."), _on_config_account)
HANDLERS = {
"FlickrHandler" : {
"name": _("Flickr photo search"),
"description": _("Search photos on Flickr."),
"requirements" : _check_requirements,
"version": VERSION,
}
}
class ThumbnailsCache():
def __init__(self):
self._cache = {}
def put(self, url, pixbuf):
self._cache[url] = pixbuf
def get(self, url):
return self._cache.get(url, None)
def has_key(self, key):
return key in self._cache.keys()
def purge(self):
self._cache = {}
thumbnailsCache = ThumbnailsCache()
def _on_config_account(dialog):
dialog = gtk.Dialog(_("Flickr photo search preferences"), dialog,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
table = gtk.Table(rows=2, columns=2)
table.attach(gtk.Label(_("Enter the maximum number of search results")), 0, 2, 0, 1)
maxResultsAdjustment = gtk.Adjustment(value=0, lower=0, upper=MAX_RESULTS_RANGE_MAX, step_incr=1, page_incr=10, page_size=0)
maxResultsSpinButton = gtk.SpinButton(adjustment=maxResultsAdjustment)
maxResults = deskbar.GCONF_CLIENT.get_int(GCONF_MAX_RESULTS)
maxResultsSpinButton.set_value(maxResults)
table.attach(gtk.Label(_("Max results: ")), 0, 1, 1, 2)
table.attach(maxResultsSpinButton, 1, 2, 1, 2)
table.show_all()
dialog.vbox.add(table)
response = dialog.run()
dialog.destroy()
try:
maxResults = int(maxResultsSpinButton.get_value())
except:
maxResults = 0
if response == gtk.RESPONSE_ACCEPT:
deskbar.GCONF_CLIENT.set_int(GCONF_MAX_RESULTS, maxResults)
class FlickrMatch(deskbar.Match.Match):
def __init__(self, handler, url=None, tags=None, author=None, thumbnail=None, **args):
deskbar.Match.Match.__init__ (self, handler, **args)
self.url = url
self.tags = tags
self.author = author
self.thumbnail = thumbnail
def get_verb(self):
return "%(name)s\n%(author)s\n%(tags)s"
def get_name(self, text=None):
return {
"name": cgi.escape(self.name),
"thumbnail" : self.thumbnail,
"author" : self.author,
"tags": cgi.escape(' '.join(self.tags)),
}
def action(self, text=None):
deskbar.Utils.url_show(self.url)
def get_category(self):
return "web"
def get_hash(self, text=None):
return self.url
def get_icon(self):
if thumbnailsCache.has_key(self.thumbnail):
return thumbnailsCache.get(self.thumbnail)
else:
thumb = urllib.urlopen(self.thumbnail, proxies=deskbar.Utils.get_proxy())
data = thumb.read()
pixbufLoader = gtk.gdk.PixbufLoader()
pixbufLoader.write(data)
pixbuf = pixbufLoader.get_pixbuf()
pixbufLoader.close()
if pixbuf.get_width() > 1:
w = h = THUMBNAIL_WIDTH
#TODO: implement scaling
thumbnailsCache.put(self.thumbnail, pixbuf);
return pixbuf
else:
return deskbar.Match.Match.get_icon(self)
class FlickrHandler(deskbar.Handler.AsyncHandler):
def __init__(self):
deskbar.Handler.AsyncHandler.__init__ (self, "yahoo.png")
self._flickrClient = FlickrClient(self)
def query(self, tag):
thumbnailsCache.purge()
self.check_query_changed (timeout=QUERY_DELAY)
self.check_query_changed ()
images = self._flickrClient.getPhotosByTag(tag)
self.check_query_changed (timeout=QUERY_DELAY)
return images
class FlickrClient:
def __init__(self, handler):
self.handler = handler
def getPhotosByTag(self, tag):
maxResults = deskbar.GCONF_CLIENT.get_int(GCONF_MAX_RESULTS)
photos=[]
url = "http://api.flickr.com/services/feeds/photos_public.gne?tags=%s&format=rss_200" % urllib.quote_plus(tag)
stream = urllib.urlopen(url, proxies=deskbar.Utils.get_proxy())
dom = xml.dom.minidom.parse(stream)
stream.close()
resultsCount = 0
for item in dom.getElementsByTagName("item"):
if maxResults > 0 and resultsCount == maxResults:
break
photos.append(
FlickrMatch(self.handler,
name=item.getElementsByTagName("title")[0].firstChild.nodeValue,
url=item.getElementsByTagName("link")[0].firstChild.nodeValue,
tags=item.getElementsByTagName("media:category")[0].firstChild.nodeValue.split(" "),
author=item.getElementsByTagName("author")[0].firstChild.nodeValue,
thumbnail=item.getElementsByTagName("media:thumbnail")[0].attributes["url"].nodeValue))
resultsCount = resultsCount + 1
return photos