Initial commit
authorDmitriy Morozov <morozov@cs.duke.edu>
Sat, 29 Mar 2008 05:23:36 -0400
changeset 0 544081ddbb13
child 1 0683f22a97d5
Initial commit
flickr.py
mainwin.ui
pyqflickr.py
--- /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_())