--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/flickr.py Sat Mar 29 05:23:36 2008 -0400
@@ -0,0 +1,98 @@
+import flickrapi
+import os, urllib2
+
+api_key = 'b323b13ee741f5c97bc8b94d2ad388fa'
+api_secret = '363b542a1a14fffa'
+
+flickr = flickrapi.FlickrAPI(api_key, api_secret)
+
+def authenticate(message):
+ (token, frob) = flickr.get_token_part_one(perms = 'write')
+ if not token: message('Please authorize this program in the browser, and then continue')
+ flickr.get_token_part_two((token,frob))
+
+# Get photosets (list their IDs, names, and URLs)
+def photosets(user = None):
+ sets = flickr.photosets_getList(user = user)
+ return [Set(s) for s in sets.photosets[0].photoset]
+
+# Get photos from the first set
+def photos(id):
+ pics = flickr.photosets_getPhotos(photoset_id = id)
+ return [Photo(p) for p in pics.photoset[0].photo]
+
+# Get all tags
+def tags():
+ rawtags = flickr.tags_getListUserRaw()
+ tags = {}
+ for t in rawtags.who[0].tags[0].tag:
+ tags[t['clean']] = t.raw[0].text
+ return tags
+
+def get_photo(working_path, url, filename, force):
+ path = os.path.join(working_path, filename)
+ if not os.path.exists(path) or force:
+ i = urllib2.urlopen(url)
+ o = file(path, 'wb')
+ o.write(i.read())
+ o.close()
+ return path
+
+class Set:
+ def __init__(self, xml):
+ self.xml = xml
+
+ def url(self):
+ return 'http://farm%s.static.flickr.com/%s/%s_%s_t.jpg' % \
+ (self.xml['farm'], self.xml['server'], self.xml['primary'], self.xml['secret'])
+
+ def filename(self):
+ return '%s_%s_t.jpg' % (self.xml['primary'], self.xml['secret'])
+
+ def id(self):
+ return self.xml['id']
+
+ def name(self):
+ return self.xml.title[0].text
+
+ def get_photo(self, working_path):
+ return get_photo(working_path, self.url(), self.filename(), False)
+
+
+class Photo:
+ def __init__(self, xml):
+ self.xml = xml
+ self.info = None
+
+ def url(self, size = 't'):
+ return 'http://farm%s.static.flickr.com/%s/%s' % \
+ (self.xml['farm'], self.xml['server'], self.filename(size))
+
+ def filename(self, size = ''):
+ if size != '': size = '_' + size
+ return '%s_%s%s.jpg' % (self.xml['id'], self.xml['secret'], size)
+
+ def get(self, working_path, size, force = False):
+ return get_photo(working_path, self.url(size), self.filename(size), force)
+
+ def get_info(self):
+ self.info = flickr.photos_getInfo(photo_id = self.xml['id'])
+
+ def tags(self):
+ if not self.info: self.get_info()
+ if not self.info.photo[0].tags[0].xml: return []
+ return [t['raw'] for t in self.info.photo[0].tags[0].tag]
+
+ def rotate(self):
+ res = flickr.photos_transform_rotate(photo_id = self.xml['id'], degrees = 90)
+ self.xml['secret'] = res.photoid[0]['secret']
+ self.xml['originalsecret'] = res.photoid[0]['originalsecret']
+
+
+if __name__ == "__main__":
+ authenticate(raw_input)
+ sets = photosets()
+ for s in sets: print "%s: %s" % (s.name(), s.url())
+ pics = photos(sets[0])
+ for p in pics:
+ print p.url()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mainwin.ui Sat Mar 29 05:23:36 2008 -0400
@@ -0,0 +1,36 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>582</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QTextBrowser" name="interfaceBrowser" />
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>29</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar" />
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pyqflickr.py Sat Mar 29 05:23:36 2008 -0400
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+
+import sys
+from PyQt4 import Qt, QtCore, QtGui
+
+from ui_mainwin import Ui_MainWindow
+import flickr, os
+
+
+working_path = os.path.expanduser('~/.pyqflickr')
+photo_size = '' # medium
+
+# Keyboard sensitive QLineEdit
+class LineEditWithShortcuts(QtGui.QLineEdit):
+ def event(self, event):
+ if event.type() == QtCore.QEvent.KeyPress:
+ if event.modifiers() & QtCore.Qt.ControlModifier:
+ self.emit(QtCore.SIGNAL("shortcutPressed"), event.key())
+ return True
+
+ return QtGui.QLineEdit.event(self, event)
+
+# Main window
+class PyQFlickr(QtGui.QMainWindow):
+ def shortcutPressed(self, key):
+ if self.photos == None: return
+ if key == QtCore.Qt.Key_Right:
+ self.photo = (self.photo + 1) % len(self.photos)
+ self.show_photo()
+ elif key == QtCore.Qt.Key_Left:
+ self.photo = (self.photo - 1) % len(self.photos)
+ self.show_photo()
+ elif key == QtCore.Qt.Key_Up:
+ self.photos = None
+ self.photo = None
+ self.show_sets()
+ elif key == QtCore.Qt.Key_R:
+ self.photos[self.photo].rotate()
+ self.show_photo(force = True)
+
+ def show_photo(self, force = False):
+ photo = self.photos[self.photo]
+ tags = photo.tags()
+ tags_txt = '<b>Tags</b>:<br>'
+ for t in tags:
+ tags_txt = tags_txt + t + '<br>'
+
+ txt = '''<center>
+ <table>
+ <tr>
+ <td margin="5" align="center">
+ <img src="%s">
+ </td>
+ <td bgcolor="#CCCCCC">%s</td>
+ </tr>
+ </table>
+ </center>''' % \
+ (photo.get(working_path, photo_size, force), tags_txt)
+ self.ui.interfaceBrowser.setHtml(txt)
+
+ def anchorClicked(self, url):
+ if self.photos == None: # In set mode
+ self.photos = flickr.photos(url.toString()) # url must be the setid
+ self.photo = 0
+ self.show_photo()
+
+ def message(self, msg):
+ QtGui.QMessageBox.warning(None, "Warning", msg)
+
+ def show_sets(self):
+ txt = '<table><tr>'
+ i = 1
+ for s in self.sets:
+ txt = txt + '<td width="120" align="center"><a href="%s"><img src="%s"><br>%s</a></td>' % \
+ (s.id(), s.get_photo(working_path), s.name())
+ if i % 8 == 0: txt = txt + '</tr><tr>'
+ i += 1
+ txt = txt + '</tr></table>'
+ self.ui.interfaceBrowser.setHtml(txt)
+
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+
+ # Setup ui
+ self.ui = Ui_MainWindow()
+ self.ui.setupUi(self)
+ self.ui.tagEdit = LineEditWithShortcuts(self.ui.centralwidget)
+ self.ui.tagEdit.setObjectName("tagEdit")
+ self.ui.vboxlayout.addWidget(self.ui.tagEdit)
+ self.ui.interfaceBrowser.setOpenLinks(False)
+
+ # Connect signals
+ self.connect(self.ui.tagEdit, QtCore.SIGNAL("shortcutPressed"), self.shortcutPressed)
+ self.connect(self.ui.interfaceBrowser, QtCore.SIGNAL("anchorClicked(const QUrl&)"), self.anchorClicked)
+
+ # Init member
+ self.sets = None
+ self.photos = None
+ self.photo = None
+
+ # Deal with Flickr
+ flickr.authenticate(self.message)
+ self.sets = flickr.photosets()
+ self.show_sets()
+
+if __name__ == "__main__":
+ app = QtGui.QApplication(sys.argv)
+ win = PyQFlickr()
+ win.show()
+ sys.exit(app.exec_())