#!/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)