def render_random(self, ctx, data): for randRow in randomSet(self.graph, 3): print 'randRow', randRow current = randRow['uri'] bindings = {"pic": current} tags = [[ T.a(href=['/set?tag=', row['tag']])[row['tag']], ' ' ] for row in self.graph.queryd("""SELECT DISTINCT ?tag WHERE { ?pic scot:hasTag [ rdfs:label ?tag ] }""", initBindings=bindings)] depicts = [[T.a(href=localSite(row['uri']))[row['label']], ' '] for row in self.graph.queryd(""" SELECT DISTINCT ?uri ?label WHERE { ?pic foaf:depicts ?uri . ?uri rdfs:label ?label . }""", initBindings=bindings)] # todo: description and tags would be good too, and some # other service should be rendering this whole section yield T.div(class_="randPick")[T.a(href=[ '/set?', urllib.urlencode(dict(date=randRow['date'], current=current)) ])[T.img(src=[localSite(current), '?size=medium']), ], T.div[tags], T.div[depicts], T.div[randRow['filename']. replace('/my/pic/', '')], ]
def render_pics(self, ctx, data): rows = [] d = URIRef(ctx.arg('dir')) for i, (pic, filename) in enumerate(sorted(picsInDirectory(self.graph, d))[:]): img = T.img(src=[localSite(pic), '?size=thumb'], # look these up in the graph width=75, height=56, onclick='javascript:photo.showLarge("%s")' % (localSite(pic) + "?size=large")) tableRow = T.table(class_="picRow")[T.tr[ T.td[T.a(href=localSite(pic))[filename]], T.td[img], T.td[ T.div["Depicts: ", T.input(type="text", class_="tags")], T.div["Comment: ", T.input(type="text")], ], ]] toCopy = "protoSectionSplitter" if i ==0: toCopy = "protoSectionBreak" rows.append([T.raw('<script type="text/javascript">document.write(document.getElementById("%s").innerHTML);</script>' % toCopy), tableRow]) return rows
def render_random(self, ctx, data): for randRow in randomSet(self.graph, 3): print 'randRow', randRow current = randRow['uri'] bindings = {"pic" : current} tags = [[T.a(href=['/set?tag=', row['tag']])[row['tag']], ' '] for row in self.graph.queryd( """SELECT DISTINCT ?tag WHERE { ?pic scot:hasTag [ rdfs:label ?tag ] }""", initBindings=bindings)] depicts = [[T.a(href=localSite(row['uri']))[row['label']], ' '] for row in self.graph.queryd(""" SELECT DISTINCT ?uri ?label WHERE { ?pic foaf:depicts ?uri . ?uri rdfs:label ?label . }""", initBindings=bindings)] # todo: description and tags would be good too, and some # other service should be rendering this whole section yield T.div(class_="randPick")[ T.a(href=['/set?', urllib.urlencode(dict(date=randRow['date'], current=current))])[ T.img(src=[localSite(current), '?size=medium']), ], T.div[tags], T.div[depicts], T.div[randRow['filename'].replace('/my/pic/','')], ]
def GET_links(request): """images and other things related to this one""" img = URIRef(request.args['uri'][0]) links = {} def relQuery(rel): rows = graph.queryd(""" SELECT DISTINCT ?d ?label WHERE { ?img ?rel ?d . OPTIONAL { ?d rdfs:label ?label } }""", initBindings={ Variable("rel"): rel, Variable("img"): img }) for r in rows: if 'label' not in r: r['label'] = r['d'] yield r def setUrl(**params): params['current'] = img return ('/set?' + urllib.urlencode(params)) for row in relQuery(FOAF.depicts): try: links.setdefault('depicting', []).append({ 'uri': localSite(row['d']), 'label': row['label'] }) except ValueError, e: log.warn("error in FOAF.depicts: %s %s" % (vars(), e)) pass
def GET(self): uri = URIRef(web.input()['uri']) r = MediaResource(graph, uri) size = r.getSize(sizes["screen"]) try: created = photoCreated(graph, uri) prettyDate = created.date().isoformat() except ValueError: prettyDate = "(unknown date)" tmpl = loader.load("sharesingle.html") stream = tmpl.generate( title="photo", prettyDate=prettyDate, bestJqueryLink=networking.jqueryLink( web.ctx.environ.get('HTTP_X_FORWARDED_FOR', '')), featuredImg=Markup('<img src="%s" width="%s" height="%s"/>' % (localSite(uri)+"?size=screen", size[0], size[1])), loginWidget=Markup(networking.getLoginBarSync( web.ctx.environ.get('HTTP_COOKIE', ''))), actionsAllowed=[], otherSizeLinks=[], link="l", allowedToWriteMeta=False, pageJson="", ) return (''.join(serializer(stream))).encode('utf8')
def sizeAttrs_by_http(foafUser, uri, sizeName): innerUri = localSite(uri) + '/size' site = restkit.Resource('http://bang:8086/') # restkit.get would hang in this twisted process return json.loads(site.get(path=innerUri, size=sizeName, headers={'x-foaf-agent' : foafUser} ).body_string())
def GET_links(request): """images and other things related to this one""" img = URIRef(request.args['uri'][0]) links = {} def relQuery(rel): rows = graph.queryd(""" SELECT DISTINCT ?d ?label WHERE { ?img ?rel ?d . OPTIONAL { ?d rdfs:label ?label } }""", initBindings={Variable("rel") : rel, Variable("img") : img}) for r in rows: if 'label' not in r: r['label'] = r['d'] yield r def setUrl(**params): params['current'] = img return ('/set?' + urllib.urlencode(params)) for row in relQuery(FOAF.depicts): try: links.setdefault('depicting', []).append( {'uri' : localSite(row['d']), 'label' : row['label']}) except ValueError, e: log.warn("error in FOAF.depicts: %s %s" % (vars(), e)) pass
def sizeAttrs_by_http(foafUser, uri, sizeName): innerUri = localSite(uri) + '/size' site = restkit.Resource('http://bang:8086/') # restkit.get would hang in this twisted process return json.loads( site.get(path=innerUri, size=sizeName, headers={ 'x-foaf-agent': foafUser }).body_string())
def photosInSet(self): desc = self.desc return [dict(thumb=dict( link=desc.otherImageUrl(p), uri=p, cls=(("current" if p == desc.currentPhoto() else "not-current") + (" video" if desc.isVideo(p) else '')), src="%s?size=thumb" % localSite(p), isVideo=desc.isVideo(p))) for p in desc.photos()]
def photosInSet(self): desc = self.desc return [ dict(thumb=dict(link=desc.otherImageUrl(p), uri=p, cls=(("current" if p == desc.currentPhoto() else "not-current") + (" video" if desc.isVideo(p) else '')), src="%s?size=thumb" % localSite(p), isVideo=desc.isVideo(p))) for p in desc.photos() ]
def nextImagePreload(self): _, nextImg = self.prevNext() if nextImg is None: return '' # must always return a string, for json encoding below preloadSize = "large" if nextImg.lower().endswith(videoExtensions): # sloppy; this should use the presence of "a pho:Video" in the graph. # also, i'm still stuffing this in an img tag, which may # or may not trigger a convert or load preloadSize = "video2" return localSite(nextImg) + "?size=" + preloadSize
def render_newestDirs(self, ctx, data): # todo- should use rdf and work over all dirs top = '/my/pic/digicam' times = [] for fn in os.listdir(top): fn = os.path.join(top, fn) + '/' if not os.path.isdir(fn): continue times.append((os.path.getmtime(fn), fn)) times.sort(reverse=True) for t, dirname in times[:10]: # todo: escaping yield T.div[T.a(href=[localSite('/set?dir='), photoUri(dirname)])[dirname]]
def render_table(self, ctx, data): if not ctx.arg('dir'): return [] d = URIRef(ctx.arg('dir')) # "http://photo.bigasterisk.com/digicam/dl-2008-09-25") rows = [] for i, (pic, filename) in enumerate(sorted( picsInDirectory(self.graph, d))[:]): img = T.img(src=[localSite(pic), '?size=thumb'], onclick='javascript:photo.showLarge("%s")' % (localSite(pic) + "?size=large")) picCols = [''] * self.brickColumns for fill in range(i, self.brickColumns): picCols[fill] = T.td picCols[i % self.brickColumns] = T.td(rowspan=self.brickColumns)[img] rows.append(T.tr(subj=pic)[ T.td[T.a(href=localSite(pic))[filename]], picCols, ]) return rows
def otherSizeLinks(self): if self.desc.currentPhoto() is None: return [] isVideo = self.desc.isVideo(self.desc.currentPhoto()) if isVideo: avail = ['video2', 'full'] else: avail = ['medium', 'large', 'screen', 'full'] return [ dict(href="%s?size=%s" % (localSite(self.desc.currentPhoto()), s), label={'video2' : '320 (webm)', 'full' : ('Original size and format' if isVideo else 'Original'), }.get(s, str(sizes[s]))) for s in avail]
def otherSizeLinks(self): if self.desc.currentPhoto() is None: return [] isVideo = self.desc.isVideo(self.desc.currentPhoto()) if isVideo: avail = ['video2', 'full'] else: avail = ['medium', 'large', 'screen', 'full'] return [ dict(href="%s?size=%s" % (localSite(self.desc.currentPhoto()), s), label={ 'video2': '320 (webm)', 'full': ('Original size and format' if isVideo else 'Original'), }.get(s, str(sizes[s]))) for s in avail ]
def featured(self): current = self.desc.currentPhoto() if current is None: return '' currentLocal = localSite(current) _, nextUri = self.prevNext() feat = MediaResource(self.graph, current) if feat.isVideo(): progress = feat.videoProgress() if progress is Done: w, h = feat.getSize(Video2) return dict(video=dict(sources=[ dict(src=currentLocal + "?size=video2", type='video/webm'), dict(src=currentLocal + "?size=video2&type=mp4", type='video/mp4') ], width=600, height=600 / w * h)) else: return dict(videoNotReady=dict(progress=progress, failed=isinstance( progress, FailedStatus))) else: try: size = feat.getSize(sizes["large"]) except (ValueError, IOError) as e: log.warn('current=%r', current) import traceback traceback.print_exc() size = (0, 0) marg = (602 - 2 - size[0]) // 2 return dict(image=dict( nextClick=self.desc.otherImageUrl(nextUri), src=currentLocal + "?size=large", w=size[0], h=size[1], marg=marg, alt=self.graph.label(current), ))
def featured(self): current = self.desc.currentPhoto() if current is None: return '' currentLocal = localSite(current) _, nextUri = self.prevNext() feat = MediaResource(self.graph, current) if feat.isVideo(): progress = feat.videoProgress() if progress is Done: w, h = feat.getSize(Video2) return dict( video=dict( sources=[ dict(src=currentLocal+"?size=video2", type='video/webm'), dict(src=currentLocal+"?size=video2&type=mp4", type='video/mp4') ], width=600, height=600 / w * h)) else: return dict(videoNotReady=dict( progress=progress, failed=isinstance(progress, FailedStatus))) else: try: size = feat.getSize(sizes["large"]) except (ValueError, IOError) as e: log.warn('current=%r', current) import traceback;traceback.print_exc() size = (0,0) marg = (602 - 2 - size[0]) // 2 return dict(image=dict( nextClick=self.desc.otherImageUrl(nextUri), src=currentLocal+"?size=large", w=size[0], h=size[1], marg=marg, alt=self.graph.label(current), ))
def render_topics(self, ctx, data): graph = self.graph byClass = {} for row in self.graph.queryd(""" SELECT DISTINCT ?topic ?cls WHERE { ?img a foaf:Image ; foaf:depicts ?topic . ?topic a ?cls . }"""): byClass.setdefault(row['cls'], set()).add(row['topic']) for cls, topics in byClass.items(): yield T.h2[graph.label(cls, default=cls)] rows = [] for topic in topics: try: localUrl = localSite(topic) except ValueError, e: log.warn("skipping topic %r: %s" % (topic, e)) continue lab = topicLabel(graph, topic) rows.append((lab.lower(), T.div[T.a(href=localUrl)[lab]])) rows.sort() yield [r[1] for r in rows]
class View(TemplateSpec): template_name = "imageSet" def __init__(self, graph, desc, params, cookie, agent, openidProxyHeader, forwardedFor): TemplateSpec.__init__(self) self.graph = graph self.desc = desc self.params, self.cookie, self.agent = params, cookie, agent self.openidProxyHeader = openidProxyHeader self.forwardedFor = forwardedFor def title(self): # why not setLabel? return self.desc.determineLabel(self.desc.graph, self.desc.topicDict) def bestJqueryLink(self): return networking.jqueryLink(self.forwardedFor) def setLabel(self): return self.desc.label() def storyModeUrl(self): # only works on topic?edit=1 urls, not stuff like # set?tag=foo. error message is poor. # need something on desc try: return self.desc.storyModeUrl() except ValueError: return None def intro(self): intro = self.graph.value(self.desc.topicDict['topic'], PHO['intro']) if intro is not None: intro = intro.replace(r'\n', '\n') # rdflib parse bug? return {'html': intro} else: return '' def currentLabel(self): if self.desc.currentPhoto() is None: return '' return self.graph.label( self.desc.currentPhoto(), # keep the title line taking up space # so the image doesn't bounce around # when there's no title default=None) def prevNextDateButtons(self): showingDate = self.params['date'] if showingDate is None: if self.desc.currentPhoto() is None: return None try: showingDate = photoDate(self.graph, self.desc.currentPhoto()) except ValueError: return None dtd = parse_date(showingDate) try: prev = dict(prevDate=date_isoformat( nextDateWithPics(self.graph, dtd, -datetime.timedelta( days=1)))) except ValueError: prev = None try: next = dict(nextDate=date_isoformat( nextDateWithPics(self.graph, dtd, datetime.timedelta(days=1)))) except ValueError: next = None return dict(prev=prev, next=next) def stepButtons(self): p, n = self.prevNext() return dict(p=self.desc.otherImageUrl(p), n=self.desc.otherImageUrl(n)) def featured(self): current = self.desc.currentPhoto() if current is None: return '' currentLocal = localSite(current) _, nextUri = self.prevNext() feat = MediaResource(self.graph, current) if feat.isVideo(): progress = feat.videoProgress() if progress is Done: w, h = feat.getSize(Video2) return dict(video=dict(sources=[ dict(src=currentLocal + "?size=video2", type='video/webm'), dict(src=currentLocal + "?size=video2&type=mp4", type='video/mp4') ], width=600, height=600 / w * h)) else: return dict(videoNotReady=dict(progress=progress, failed=isinstance( progress, FailedStatus))) else: try: size = feat.getSize(sizes["large"]) except (ValueError, IOError) as e: log.warn('current=%r', current) import traceback traceback.print_exc() size = (0, 0) marg = (602 - 2 - size[0]) // 2 return dict(image=dict( nextClick=self.desc.otherImageUrl(nextUri), src=currentLocal + "?size=large", w=size[0], h=size[1], marg=marg, alt=self.graph.label(current), )) def loginWidget(self): return networking.getLoginBarSync(self.cookie) def actionsAllowed(self): """should the actions section be displayed""" return self.agent is not None and self.agent in auth.superagents @print_timing def aclWidget(self): if not self.desc.currentPhoto(): return '' import access reload(access) return access.accessControlWidget(self.graph, self.agent, self.desc.currentPhoto()) @print_timing def setAclWidget(self): """ access for the whole displayed set """ try: setUri = self.desc.canonicalSetUri() except NoSetUri: return '' import access reload(access) return access.accessControlWidget(self.graph, self.agent, setUri) def uploadButton(self): if self.desc.currentPhoto() is None: return '' copy = self.graph.value(self.desc.currentPhoto(), PHO.flickrCopy) if copy is not None: return dict(copied=dict(uri=copy)) if self.openidProxyHeader is not None and URIRef( self.openidProxyHeader) in auth.superusers: return dict(mayCopy=dict(show=True)) return None @print_timing def publicShareButton(self): if self.desc.currentPhoto() is None: return None # not absoluteSite() here, since i didn't want to make # separate shortener entries for test sites and the real one target = self.desc.currentPhoto() + "/single" short = hasShortUrlSync(target) if short: if access.viewable(self.graph, self.desc.currentPhoto(), FOAF.Agent): return dict(hasLink=dict(short=short)) return dict(makeLink=dict(show=True)) def facts(self, p=None): try: js = serviceCallSync(self.agent, 'facts', p or self.desc.currentPhoto()) except ValueError: return {} return json.loads(js) def otherSizeLinks(self): if self.desc.currentPhoto() is None: return [] isVideo = self.desc.isVideo(self.desc.currentPhoto()) if isVideo: avail = ['video2', 'full'] else: avail = ['medium', 'large', 'screen', 'full'] return [ dict(href="%s?size=%s" % (localSite(self.desc.currentPhoto()), s), label={ 'video2': '320 (webm)', 'full': ('Original size and format' if isVideo else 'Original'), }.get(s, str(sizes[s]))) for s in avail ] def localPath(self): cur = self.desc.currentPhoto() if cur is None: return '(none)' return MediaResource(self.graph, cur).sourcePath() def link(self): current = self.desc.currentPhoto() if current is None: return None if self.graph.contains((current, RDF.type, PHO.Video)): return dict(video=dict(uri=current + '?size=video2')) # should put sizes in this link(s) return dict(image=dict(uri=current + '?size=large')) def allowedToWriteMeta(self): return (self.agent is not None and tagging.allowedToWrite(self.graph, self.agent)) def currentImgJson(self): p = self.desc.currentPhoto() obj = {'uri': p} if p else None return json.dumps(obj) def starLinkAll(self): if self.params['star'] is None: return '' else: return dict(href=self.desc.altUrl(star='all')) def starLinkOnly(self): if self.params['star'] == 'only': return '' else: return dict(href=self.desc.altUrl(star='only')) def recentLinks(self): raise NotImplementedError choices = [] for opt in [10, 50, 100]: href = self.desc.altUrl(recent=str(opt)) choices.append(T.a(href=href)[opt]) choices.append(T.a(href=self.desc.altUrl(recent=''))['all']) return [ 'show only the ', [[c, ' '] for c in choices], ' most recent of these' ] @print_timing def photosInSet(self): desc = self.desc return [ dict(thumb=dict(link=desc.otherImageUrl(p), uri=p, cls=(("current" if p == desc.currentPhoto() else "not-current") + (" video" if desc.isVideo(p) else '')), src="%s?size=thumb" % localSite(p), isVideo=desc.isVideo(p))) for p in desc.photos() ] def photosInSetPlus(self): """for use by other tools who want to draw some photos """ out = [] for p in self.desc.photos(): r = MediaResource(self.graph, p) try: s = r.getSize(sizes["thumb"]) thumbSize = {"thumbSize": dict(w=s[0], h=s[1])} except (ValueError, IOError, subprocess.CalledProcessError): thumbSize = {} out.append( dict(link=absoluteSite(self.desc.otherImageUrl(p)), uri=p, facts=self.facts(p), thumb="%s?size=thumb" % p, screen="%s?size=screen" % p, isVideo=self.desc.isVideo(p))) out[-1].update(thumbSize) return out def zipUrl(self): return "%s?archive=zip" % self.desc.topic def zipSizeWarning(self): mb = 17.3 / 9 * len(self.desc.photos()) secs = mb * 1024 / 40 return "(file will be roughly %d MB and take %d mins to download)" % ( mb, secs / 60) @print_timing def pageJson(self): prev, next = self.prevNext() return dict( picInfo=json.dumps(self.picInfoJson()), prev=json.dumps(self.desc.otherImageUrl(prev)), next=json.dumps(self.desc.otherImageUrl(next)), preloadImg=json.dumps(self.nextImagePreload()), tagHotkeys=json.dumps(auth.tagHotkeys), ) @print_timing def picInfoJson(self): # vars for the javascript side to use current = self.desc.currentPhoto() if current is None: return {} try: js = serviceCallSync(self.agent, 'tags', current) tags = json.loads(js) except restkit.RequestFailed, e: tags = {"error": str(e)} return dict(relCurrentPhotoUri=localSite(current), currentPhotoUri=current, tags=tags)