#!/usr/bin/python
import os
import sys
try:
import cElementTree as etree
except ImportError:
import elementtree.ElementTree as etree
# tool for manually extracting albums from kimdaba.
# For example,
# Src: ~/PIX/SL300RT/downcase/index.xml
# Dest: ~/metacarta/static/metacarta/
# Sizes: Full, 800x600
# Title: MetaCarta Pictures
# Desc: random pictures I've taken around the office
# Search: "work" in keywords
## consider a subalbum:
## "work" in keywords and "whiteboard" in keywords
## later, disambiguate "work"
# picture for keywords:
# /KimDaBa/config has interesting stuff, but isn't a picture
# /KimDaBa/options/option/value@value is interesting too
# /KimDaBa/member-groups/member@group-name, @category, @member
# is how we pre-cook groups, because otherwise we don't record them
# /KimDaBa/images/image@file
# /KimDaBa/images/image where
# /KimDaBa/images/image/options/option[@name="Keywords]/value[@value="work"]
# domgrep '/KimDaBa/images/image/options/option[@name="Keywords"]/value/@value' ~/PIX/SL300RT/downcase/index.xml
# seems to at least dump all keywords; @name="Persons" does likewise...
# domgrep '/KimDaBa/images/image/options/option[@name="Keywords"]/value[@value="pouncing"]/@value' ~/PIX/SL300RT/downcase/index.xml
# is kind of silly, in that it prints "pouncing" 40 times...
# domgrep '/KimDaBa/images/image/@file' ~/PIX/SL300RT/downcase/index.xml
# prints all the filenames, but doesn't filter...
# domgrep '/KimDaBa/images/image[options/option[@name="Keywords"]/value[@value="pouncing"]]/@file' ~/PIX/SL300RT/downcase/index.xml
# appears to filter filenames on pouncing, at least...
#
# in practice maybe we just pick up /KimDaBa/images/image/@md5sum, then
# key individual itmes with [md5sum=...]
# so:
## <image width="2048" monthFrom="10" dayFrom="25" hourFrom="20" height="1536" yearTo="0" monthTo="0" md5sum="a2753c7c48e7b13a8b1a4b26a2be2e6d" minuteFrom="2" file="100cxbox/kicx6354.jpg" label="kicx6354" angle="0" dayTo="0" secondFrom="28" yearFrom="2005" description="" >
## <options>
## <option name="Keywords" >
## <value value="whiteboard" />
## <value value="work" />
## </option>
## <option name="Locations" >
## <value value="MetaCarta" />
## </option>
## </options>
## </image>
#
# we want to pull out the keywords for a text label (dt)
# we want all the image attrs:
# width="2048"
# height="1536"
# yearFrom="2005"
# monthFrom="10"
# dayFrom="25"
# hourFrom="20"
# minuteFrom="2"
# secondFrom="28"
# yearTo="0"
# monthTo="0"
# dayTo="0"
# md5sum="a2753c7c48e7b13a8b1a4b26a2be2e6d"
# file="100cxbox/kicx6354.jpg"
# label="kicx6354"
# angle="0" # or 90
# description=""
# note that
# domgrep '/KimDaBa/images/image[options/option[@name="Keywords"]/value[@value="construction"]]/@*' ~/PIX/SL300RT/downcase/index.xml
# actually gets each attribute, but probably in file-order
# ee = elementtree.ElementTree.ElementTree(file=os.path.expanduser("~/PIX/SL300RT/downcase/index.xml"))
# img = ee.findall('images/image')[0]
# (ee.getiterator?)
# >>> img.keys()
# ['dayTo', 'secondFrom', 'yearFrom', 'angle', 'file', 'monthFrom', 'md5sum', 'yearTo', 'height', 'width', 'minuteFrom', 'hourFrom', 'monthTo', 'label', 'dayFrom', 'description']
# >>> img.find("options")
# <Element options at -482cceb4>
# img.find("options").find("option").keys()
# ['name']
# img.find("options").find("option").get("name")
# 'Keywords'
# >>> img.get("file")
# '100cxbox/kicx6300.jpg'
# >>> img.find("options").find("option/value").get("value")
# 'adventure'
# [f.get("value") for f in img.find("options").findall("option/value")]
# ['adventure', 'pouncing']
# [f.get("value") for f in img.findall("options/option/value")]
# ['adventure', 'pouncing']
def kimdaba_default_album():
"""Find the path to the default album kimdaba will start with"""
# could support cheap comments with an early .split("#",1)[0]
# but the kde files don't use them
args = dict(line.rstrip("\n").split("=",1)
for line in file(os.path.expanduser("~/.kde/share/config/kimdaba")))
return args["configfile"]
def parse(path):
return etree.ElementTree(file=path)
def select_images(kimdabaroot, wantedkeys, unwantedkeys):
results = []
for img in kimdabaroot.findall("images/image"):
thesekeys = wantedkeys.copy()
imgkeys = set([f.get("value") for f in img.findall("options/option/value")])
# remove the keys for this img; if anything is left,
# they weren't all satisfied
if not wantedkeys - imgkeys and not unwantedkeys & imgkeys:
print img.get("file"), imgkeys
results.append(img)
# add image to album
return results
# timg = [img for img in kimdabaroot.findall("images/image") if img.get("md5sum") == "26306475ed4af77aaab7a7102dff76b3"][0]
# print elementtree.ElementTree.tostring(timg.findall("options/option")[0])
# kws = timg.findall("options/option")[0]
# ES=elementtree.ElementTree.tostring
# print ES(kws.makeelement("value", dict(value="flickd")))
# kws.append(kws.makeelement("value", dict(value="flickd")))
# print ES(kws)
# kimdabaroot.write("/tmp/zot.xml", encoding="UTF-8")
def safe_replace(xpath, etree):
"""Safely replace a kimdaba index.xml file with a modified one"""
# write temporary
etree.write(xpath + "~")
# move original out of the way, for recovery
os.rename(xpath, xpath + ".bak")
# move temporary in to place
os.rename(xpath + "~", xpath)
def add_keyword(md5sum, value):
"""Add a keyword to an image for which we know the md5sum"""
kimdabaxml = kimdaba_default_album()
kimdabaroot = parse(kimdabaxml)
for img in kimdabaroot.findall("images/image"):
if img.get("md5sum") != md5sum: continue
print "found", img.get("file")
for optionset in img.findall("options/option"):
if optionset.get("name") == "Keywords":
optionset.append(optionset.makeelement("value",
dict(value=value)))
safe_replace(kimdabaxml, kimdabaroot)
return
raise Exception("didn't match anything, add_keyword failed!")
def add_property(md5sum, propname, propvalue):
"""Add/Change a property to an image for which we know the md5sum"""
kimdabaxml = kimdaba_default_album()
kimdabaroot = parse(kimdabaxml)
for img in kimdabaroot.findall("images/image"):
if img.get("md5sum") != md5sum: continue
print "found", img.get("file")
if img.get(propname) != propvalue:
img.set(propname, propvalue)
safe_replace(kimdabaxml, kimdabaroot)
return
raise Exception("didn't find matching image, add_property failed!")
def add_description(pathpart, desc):
"""Add/Change description for an image, by partial name; return md5sum"""
kimdabaxml = kimdaba_default_album()
kimdabaroot = parse(kimdabaxml)
for img in kimdabaroot.findall("images/image"):
# file="100cxbox/kicx6848.jpg", or now year/...
if img.get("file") == pathpart:
img.set("description", desc)
safe_replace(kimdabaxml, kimdabaroot)
return img.get("md5sum")
raise Exception("no images had path part %s, add_description failed" % pathpart)
def expand_keyword_groups(kimdabaroot, keywords):
"""Expand keywords that are group members"""
expansions = set()
for member in kimdabaroot.findall("member-groups/member"):
# '<member category="Keywords" group-name="Robot" member="Scooba" />\n '
# later, limit to member.get("category")
if member.get("member") in keywords:
expansions.add(member.get("group-name"))
return expansions
if __name__ == "__main__":
prog = sys.argv.pop(0)
# use optparse to do real processing here:
# --output=directory (to build album in)
# --size*=[full|NxM] (size of images to make, first=default)
# then the keys as already handled
wantedkeys = set()
unwantedkeys = set()
# unwanted start with a "-"
# consider maybe adding K: L: P: for categories, optionally...
for key in sys.argv:
if key.startswith("-"):
unwantedkeys.add(key[1:])
else:
wantedkeys.add(key)
kimdabaxml = kimdaba_default_album()
kimdabaroot = parse(kimdabaxml)
images = select_images(kimdabaroot, wantedkeys, unwantedkeys)
print len(images)