From 4e44480c1fcb70d8c6e8dde1225faed51a9fdbe1 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 7 Dec 2014 16:58:06 +0300 Subject: [PATCH] added bulk data tags import/export from/to images + some plyfils... Signed-off-by: Alex A. Naanou --- ui (gen4)/data.js | 150 +++++++++++++++++++++++++++++++++++++- ui (gen4)/lib/features.js | 3 +- ui (gen4)/lib/jli.js | 34 +++++++++ 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js index 3d597f90..6d89bb4b 100755 --- a/ui (gen4)/data.js +++ b/ui (gen4)/data.js @@ -231,7 +231,7 @@ var DataPrototype = { } gids.forEach(function(e){ - i = order.indexOf(e) + var i = order.indexOf(e) if(i >= 0){ var o = target[i] // save overwritten target items if keep_target_items @@ -2284,6 +2284,154 @@ var DataWithTagsPrototype = { // ....is there a way not to say DataPrototype here??? __gid_lists: DataPrototype.__gid_lists.concat(['tags']), + + // Load tags from images... + // + // Merge image tags to data... + // .tagsFromImages(images) + // -> data + // + // Load image tags to data dropping any changes in data... + // .tagsFromImages(images, 'reset') + // -> data + // + // XXX should this be here??? + // XXX this depend on image structure... + tagsFromImages: function(images, mode){ + if(mode == 'reset'){ + this.tags = {} + } + for(var gid in images){ + var img = images[gid] + if(img.tags != null){ + this.tag(img.tags, gid) + } + } + return this + .sortTags() + }, + + // Transfer tags to images... + // + // Merge data tags to images... + // .tagsToImages(images) + // .tagsToImages(images, true) + // .tagsToImages(images, 'merge') + // -> data + // + // Merge data tags to images without buffering... + // .tagsToImages(images, 'unbuffered') + // -> data + // + // Reset image tags from data... + // .tagsToImages(images, 'rest') + // -> data + // + // XXX should this be here??? + // XXX this depend on image structure... + // XXX should this use image API for creating images??? + tagsToImages: function(images, mode, updated){ + mode = mode || 'merge' + updated = updated || [] + + // mark gid as updated... + var _updated = function(gid){ + if(updated != null && updated.indexOf(gid) < 0){ + updated.push(gid) + } + } + // get or create an image with tags... + // XXX should this use image API for creating??? + var _get = function(images, gid){ + var img = images[gid] + // create a new image... + if(img == null){ + img = images[gid] = {} + _updated(gid) + } + + var tags = img.tags + // no prior tags... + if(tags == null){ + tags = img.tags = [] + _updated(gid) + } + + return img + } + + // buffered mode... + // - uses more memory + // + one write mer image + if(mode != 'unbuffered'){ + // build the buffer... + var buffer = {} + this.tagsToImages(buffer, 'unbuffered') + + // reset mode... + if(mode == 'reset'){ + // iterate through all the gids (both images and buffer/data) + for(var gid in Object.keys(images) + .concat(Object.keys(buffer)) + .unique()){ + // no tags / remove... + if(buffer[gid] == null || buffer[gid].tags.length == 0){ + // the image exists and has tags... + if(images[gid] != null && images[gid].tags != null){ + delete images[gid].tags + _updated(gid) + } + + // tags / set... + } else { + var img = _get(images, gid) + var before = img.tags.slice() + + img.tags = buffer[gid].tags + + // check if we actually changed anything... + if(!before.setCmp(img.tags)){ + _updated(gid) + } + } + } + + // merge mode... + } else { + for(var gid in buffer){ + var img = _get(images, gid) + var l = img.tags.length + img.tags = img.tags.concat(buffer[gid].tags).unique() + // we are updated iff length changed... + // NOTE: this is true as we are not removing anything + // thus the length can only increase if changes are + // made... + if(l != img.tags.length){ + _updated(gid) + } + } + } + + // unbuffered (brain-dead) mode... + // + no extra memory + // - multiple writes per image (one per tag) + } else { + var tagset = this.tags + for(var tag in tagset){ + tagset[tag].forEach(function(gid){ + var img = _get(images, gid) + + if(img.tags.indexOf(tag) < 0){ + img.tags.push(tag) + _updated(gid) + } + }) + } + } + return this + }, + + // NOTE: this is here only to make the tags mutable... crop: function(){ var crop = DataWithTagsPrototype.__proto__.crop.apply(this, arguments) diff --git a/ui (gen4)/lib/features.js b/ui (gen4)/lib/features.js index b04044e2..a434dd4c 100755 --- a/ui (gen4)/lib/features.js +++ b/ui (gen4)/lib/features.js @@ -222,7 +222,8 @@ module.FeatureSet = { var l = lst.length lst = lst // remove duplicates, keeping only the first occurance... - .filter(function(e, i, l){ return l.indexOf(e) == i }) + //.filter(function(e, i, l){ return l.indexOf(e) == i }) + .unique() // remove undefined features... .filter(function(e){ return that[e] != null }) // build the sort table: [ , , ] diff --git a/ui (gen4)/lib/jli.js b/ui (gen4)/lib/jli.js index c74a733d..e957b4a8 100755 --- a/ui (gen4)/lib/jli.js +++ b/ui (gen4)/lib/jli.js @@ -1335,6 +1335,40 @@ Array.prototype.compact = function(){ } +// return an array with duplicate elements removed... +// +Array.prototype.unique = function(){ + return this.filter(function(e, i, a){ return a.indexOf(e) == i }) +} + + +// Compare two arrays... +// +Array.prototype.cmp = function(other){ + if(this === other){ + return true + } + if(this.length != other.length){ + return false + } + for(var i=0; i