mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-11-04 05:10:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			744 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			744 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
/**********************************************************************
 | 
						|
* 
 | 
						|
*
 | 
						|
*
 | 
						|
**********************************************************************/
 | 
						|
 | 
						|
//var DEBUG = DEBUG != null ? DEBUG : true
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
* File storage (Extension API -- CEF/PhoneGap/...)
 | 
						|
*
 | 
						|
* XXX need to cleanup this section...
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
/********************************************************* Helpers ***/
 | 
						|
 | 
						|
// Report deferred progress
 | 
						|
//
 | 
						|
// This uses showStatus(...) and showErrorStatus(...) to report actions.
 | 
						|
//
 | 
						|
// Will use showErrorStatus(...) iff "Error" is the last argument of the
 | 
						|
// progress/notify action, removing it (string 'Error') from the arguments.
 | 
						|
//
 | 
						|
// Will return the original deferred.
 | 
						|
function statusNotify(prefix, loader, not_queued){
 | 
						|
	var report = not_queued == true ? showStatus : showStatusQ
 | 
						|
	if(loader == null){
 | 
						|
		loader = prefix
 | 
						|
		prefix = null
 | 
						|
	}
 | 
						|
	return loader
 | 
						|
		.progress(function(){
 | 
						|
			var args = Array.apply(null, arguments)
 | 
						|
			if(prefix != null && prefix != ''){
 | 
						|
				args.splice(0, 0, prefix)
 | 
						|
			}
 | 
						|
			if(args.indexOf('Error') >= 0){
 | 
						|
				args.pop()
 | 
						|
				return showErrorStatus(args.join(': '))
 | 
						|
			}
 | 
						|
			return report(args.join(': '))
 | 
						|
		})
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Bubble up actions in the deferred chain
 | 
						|
//
 | 
						|
// Will chain progress/notify and if only_progress is not set, also
 | 
						|
// done/resolve and fail/reject from "from" to "to" deferred objects.
 | 
						|
//
 | 
						|
// Will add prefix to the list of arguments of progress/notify and
 | 
						|
// fail/reject (if not disabled), unless it is set to null.
 | 
						|
//
 | 
						|
// Will return "from" object.
 | 
						|
function bubbleProgress(prefix, from, to, only_progress){
 | 
						|
	from
 | 
						|
		.progress(function(){ 
 | 
						|
			var args = Array.apply(null, arguments)
 | 
						|
			prefix != null && args.splice(0, 0, prefix)
 | 
						|
			to.notify.apply(to, args) 
 | 
						|
		})
 | 
						|
 | 
						|
	if(only_progress == null){
 | 
						|
		from
 | 
						|
			.done(function(){
 | 
						|
				var args = Array.apply(null, arguments)
 | 
						|
				to.resolve.apply(to, args) 
 | 
						|
			})
 | 
						|
			.fail(function(){
 | 
						|
				var args = Array.apply(null, arguments)
 | 
						|
				prefix != null && args.splice(0, 0, prefix)
 | 
						|
				to.reject.apply(to, args) 
 | 
						|
			})
 | 
						|
	}
 | 
						|
 | 
						|
	return from
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Semi-generic deferred file loader
 | 
						|
//
 | 
						|
// if pattern is given, then search for the latest (ordered last) file 
 | 
						|
// and load that.
 | 
						|
// else load the dfl file.
 | 
						|
//
 | 
						|
// if diff_pattern is given, then merge all matching files in order 
 | 
						|
// (first to last) with the loaded "main" file
 | 
						|
//
 | 
						|
// NOTE: this expects a file to be JSON.
 | 
						|
// NOTE: if diffs are available this expects the file to contain an object,
 | 
						|
// 		and will extend that object.
 | 
						|
// NOTE: if neither of dfl, pattern or diff_pattern are given, then this
 | 
						|
// 		is essentially the same as $.getJSON(...)
 | 
						|
// NOTE: this needs listDir(...) to search for latest versions of files.
 | 
						|
function loadLatestFile(path, dfl, pattern, diff_pattern){
 | 
						|
	var pparts = path.split(/[\/\\]/)
 | 
						|
	dfl = dfl == null ? pparts.pop() : dfl
 | 
						|
	//path = path == dfl ? '.' : path
 | 
						|
	path = pparts.join('/')
 | 
						|
 | 
						|
	var res = $.Deferred()
 | 
						|
	
 | 
						|
	if(dfl == ''){
 | 
						|
		return res.reject()
 | 
						|
	}
 | 
						|
 | 
						|
	// can't find diffs if can't list dirs...
 | 
						|
	if(window.listDir == null && (pattern != null || diff_pattern != null)){
 | 
						|
		res.notify('Unsupported', 'directory listing.')
 | 
						|
		return res.reject('listDir unsupported.')
 | 
						|
	}
 | 
						|
 | 
						|
	// find the latest...
 | 
						|
	if(pattern != null){
 | 
						|
		pattern = RegExp(pattern)
 | 
						|
		var file = $.map(listDir(path), function(e){ 
 | 
						|
			return pattern.test(e) ? e : null
 | 
						|
		}).sort().reverse()[0]
 | 
						|
	}
 | 
						|
	var file = file == null ? dfl : file
 | 
						|
	
 | 
						|
	var diff_data = {}
 | 
						|
	var diff = true
 | 
						|
 | 
						|
	// collect and merge diffs...
 | 
						|
	if(diff_pattern != null){
 | 
						|
		diff_pattern = RegExp(diff_pattern)
 | 
						|
		var diff_data = [diff_data]
 | 
						|
		var diffs_names = $.map(listDir(path), function(e){ 
 | 
						|
			return diff_pattern.test(e) ? e : null
 | 
						|
		}).sort()
 | 
						|
		diff = $.when.apply(null, $.map(diffs_names, function(e, i){
 | 
						|
					return $.getJSON(path +'/'+ e)
 | 
						|
						.done(function(data){
 | 
						|
							diff_data[i+1] = data
 | 
						|
							res.notify('Loaded', e)
 | 
						|
						})
 | 
						|
						.fail(function(){
 | 
						|
							// XXX should we kill the load here???
 | 
						|
							res.notify('Loading', e, 'Error')
 | 
						|
						})
 | 
						|
				}))
 | 
						|
			// NOTE: .then(...) handlers get different signature args 
 | 
						|
			// 		depending on the number of arguments to .when(...)...
 | 
						|
			.then(function(){
 | 
						|
				$.extend.apply(null, diff_data)
 | 
						|
				diff_data = diff_data[0]
 | 
						|
			})
 | 
						|
	} 
 | 
						|
 | 
						|
	// load the main file and merge the diff with it...
 | 
						|
	$.when(diff, $.getJSON(path +'/'+ file))
 | 
						|
		.done(function(_, json){
 | 
						|
			json = json[0]
 | 
						|
 | 
						|
			res.notify('Loaded', file)
 | 
						|
 | 
						|
			// merge diffs...
 | 
						|
			if(Object.keys(diff_data).length != 0){
 | 
						|
				$.extend(json, diff_data)
 | 
						|
				res.notify('Merged')
 | 
						|
			}
 | 
						|
 | 
						|
			res.resolve(json)
 | 
						|
		})
 | 
						|
		.fail(function(){
 | 
						|
			res.notify('Loading', file, 'Error')
 | 
						|
 | 
						|
			return res.reject(file)
 | 
						|
		})
 | 
						|
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Construct a ribbons hierarchy from the fav dirs structure
 | 
						|
//
 | 
						|
// NOTE: this depends on listDir(...)
 | 
						|
// NOTE: this assumes that images contain ALL the images...
 | 
						|
// NOTE: this assumes that all file names are unique...
 | 
						|
function ribbonsFromFavDirs(path, images, cmp){
 | 
						|
	path = path == null ? getBaseURL() : path
 | 
						|
	images = images == null ? IMAGES : images
 | 
						|
 | 
						|
	// build a reverse name-gid index for fast access...
 | 
						|
	var index = {}
 | 
						|
	var name
 | 
						|
	for(var gid in images){
 | 
						|
		name = images[gid].path.split('/').pop()
 | 
						|
		// XXX we assume that names are unique...
 | 
						|
		index[name] = gid
 | 
						|
	}
 | 
						|
 | 
						|
	var ribbons = []
 | 
						|
	// add the base row...
 | 
						|
	var base = Object.keys(images)
 | 
						|
	ribbons.push(base)
 | 
						|
 | 
						|
	var files = listDir(path)	
 | 
						|
	var cur_path = path
 | 
						|
	while(files.indexOf('fav') >= 0){
 | 
						|
		cur_path += '/fav'
 | 
						|
		files = listDir(cur_path)
 | 
						|
		ribbon = []
 | 
						|
		// collect the images...
 | 
						|
		$.each(files, function(i, e){
 | 
						|
			var _gid = index[e]
 | 
						|
			// skip files not in index...
 | 
						|
			// NOTE: we do not need to filter the files by name as we 
 | 
						|
			// 		trust the index...
 | 
						|
			if(_gid == null){
 | 
						|
				return 
 | 
						|
			}
 | 
						|
			// remove the found item from each of the below ribbons...
 | 
						|
			$.each(ribbons, function(i ,e){
 | 
						|
				if(e.indexOf(_gid) != -1){
 | 
						|
					e.splice(e.indexOf(_gid), 1)
 | 
						|
				}
 | 
						|
			})
 | 
						|
 | 
						|
			ribbon.push(_gid)
 | 
						|
		})
 | 
						|
		ribbons.push(ribbon)
 | 
						|
	}
 | 
						|
 | 
						|
	// remove empty ribbons and sort the rest...
 | 
						|
	ribbons = $.map(ribbons, function(e){ 
 | 
						|
		return e.length > 0 ? [cmp == null ? e : e.sort(cmp)] : null 
 | 
						|
	})
 | 
						|
 | 
						|
	return ribbons.reverse()
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************/
 | 
						|
 | 
						|
// Load images from file
 | 
						|
//
 | 
						|
// This will also merge all diff files.
 | 
						|
function loadFileImages(path, no_load_diffs){
 | 
						|
	no_load_diffs = window.listDir == null ? true : no_load_diffs 
 | 
						|
 | 
						|
	var res = $.Deferred()
 | 
						|
 | 
						|
	// default locations...
 | 
						|
	if(path == null){
 | 
						|
		var base = normalizePath(CACHE_DIR_VAR) 
 | 
						|
		var loader = loadLatestFile(base, 
 | 
						|
				IMAGES_FILE_DEFAULT, 
 | 
						|
				IMAGES_FILE_PATTERN, 
 | 
						|
				IMAGES_DIFF_FILE_PATTERN)
 | 
						|
	
 | 
						|
	// explicit base dir...
 | 
						|
	} else if(!/\.json$/i.test(path)) {
 | 
						|
		var base = normalizePath(path +'/'+ CACHE_DIR_VAR) 
 | 
						|
		var loader = loadLatestFile(base, 
 | 
						|
				IMAGES_FILE_DEFAULT, 
 | 
						|
				IMAGES_FILE_PATTERN, 
 | 
						|
				IMAGES_DIFF_FILE_PATTERN)
 | 
						|
 | 
						|
	// explicit path...
 | 
						|
	} else {
 | 
						|
		var loader = loadLatestFile(normalizePath(path))
 | 
						|
	}
 | 
						|
 | 
						|
	bubbleProgress('Images', loader, res)
 | 
						|
 | 
						|
	res.done(function(images){
 | 
						|
		IMAGES = images
 | 
						|
	})
 | 
						|
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Save current images list to file
 | 
						|
//
 | 
						|
// If not name is given this will merge all the diffs and save a "clean"
 | 
						|
// (full) images.json file. Also removing the diff files.
 | 
						|
//
 | 
						|
// NOTE: if an explicit name is given then this will not remove anything.
 | 
						|
// NOTE: this will use CACHE_DIR as the location if no name is given.
 | 
						|
function saveFileImages(name){
 | 
						|
	var remove_diffs = (name == null)
 | 
						|
	name = name == null ? normalizePath(CACHE_DIR_VAR +'/'+ Date.timeStamp()) : name
 | 
						|
 | 
						|
	if(window.dumpJSON == null){
 | 
						|
		showErrorStatus('Can\'t save to file.')
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// remove the diffs...
 | 
						|
	if(remove_diffs){
 | 
						|
		$.each($.map(listDir(normalizePath(CACHE_DIR_VAR)), function(e){ 
 | 
						|
				return IMAGES_DIFF_FILE_PATTERN.test(e) ? e : null
 | 
						|
			}), function(i, e){
 | 
						|
				showStatusQ('removeing:', e)
 | 
						|
				removeFile(normalizePath(CACHE_DIR_VAR +'/'+ e))
 | 
						|
			})
 | 
						|
		IMAGES_UPDATED = []
 | 
						|
	}
 | 
						|
 | 
						|
	// XXX use the pattern...
 | 
						|
	dumpJSON(name + '-images.json', IMAGES)
 | 
						|
	//DATA.image_file = normalizePath(name + '-images.json', null, 'relative')
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Load image marks form file
 | 
						|
function loadFileMarks(path){
 | 
						|
	var res = $.Deferred()
 | 
						|
	// default locations...
 | 
						|
	if(path == null){
 | 
						|
		var base = normalizePath(CACHE_DIR_VAR)
 | 
						|
		var loader = loadLatestFile(base, 
 | 
						|
				MARKED_FILE_DEFAULT, 
 | 
						|
				MARKED_FILE_PATTERN)
 | 
						|
	
 | 
						|
	// explicit path...
 | 
						|
	// XXX need to account for paths without a CACHE_DIR
 | 
						|
	} else {
 | 
						|
		path = normalizePath(path)
 | 
						|
		var base = path.split(CACHE_DIR)[0]
 | 
						|
		//base = normalizePath(path +'/'+ CACHE_DIR_VAR)
 | 
						|
		base = path +'/'+ CACHE_DIR
 | 
						|
 | 
						|
		// XXX is this correct???
 | 
						|
		var loader = loadLatestFile(base, 
 | 
						|
				path.split(base)[0], 
 | 
						|
				RegExp(path.split(base)[0]))
 | 
						|
	}
 | 
						|
 | 
						|
	bubbleProgress('Marks', loader, res)
 | 
						|
 | 
						|
	res.done(function(images){
 | 
						|
		MARKED = images
 | 
						|
	})
 | 
						|
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Save image marks to file
 | 
						|
function saveFileMarks(name){
 | 
						|
	name = name == null ? normalizePath(CACHE_DIR_VAR +'/'+ Date.timeStamp()) : name
 | 
						|
 | 
						|
	dumpJSON(name + '-marked.json', MARKED)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Load images, ribbons and marks from cache
 | 
						|
//
 | 
						|
// XXX add support for explicit filenames...
 | 
						|
function loadFileState(path, prefix){
 | 
						|
	prefix = prefix == null ? 'Data' : prefix
 | 
						|
	prefix = prefix === false ? null : prefix
 | 
						|
 | 
						|
	// XXX explicit data file path...
 | 
						|
	if(/\.json$/i.test(path)){
 | 
						|
		// XXX at this 
 | 
						|
		var base = path.split(CACHE_DIR)[0]
 | 
						|
		base = base == path ? '.' : base
 | 
						|
	} else {
 | 
						|
		var base = path.split(CACHE_DIR)[0]
 | 
						|
		base = base == path ? '.' : base
 | 
						|
	}
 | 
						|
 | 
						|
	var res = $.Deferred()
 | 
						|
 | 
						|
	bubbleProgress(prefix,
 | 
						|
			loadLatestFile(path, 
 | 
						|
				DATA_FILE_DEFAULT, 
 | 
						|
				DATA_FILE_PATTERN), res, true)
 | 
						|
		.done(function(json){
 | 
						|
			setBaseURL(base)
 | 
						|
 | 
						|
			// legacy format...
 | 
						|
			if(json.version == null){
 | 
						|
				json = convertDataGen1(json)
 | 
						|
				DATA = json.data
 | 
						|
				IMAGES = json.images
 | 
						|
				MARKED = []
 | 
						|
				reloadViewer()
 | 
						|
				res.resolve()
 | 
						|
 | 
						|
			// version 2.0
 | 
						|
			} else if(json.version == '2.0') {
 | 
						|
				DATA = json
 | 
						|
				$.when(
 | 
						|
						// XXX load config...
 | 
						|
						// load images...
 | 
						|
						bubbleProgress(prefix,
 | 
						|
							loadFileImages(base), res, true),
 | 
						|
							//loadFileImages(DATA.image_file != null ?
 | 
						|
							//		normalizePath(DATA.image_file, base) 
 | 
						|
							//		: null), res, true),
 | 
						|
						// load marks if available...
 | 
						|
						bubbleProgress(prefix,
 | 
						|
							loadFileMarks(), res, true))
 | 
						|
					.done(function(){
 | 
						|
						reloadViewer()
 | 
						|
						res.resolve()
 | 
						|
					})
 | 
						|
					// XXX fail???
 | 
						|
 | 
						|
			// unknown format...
 | 
						|
			} else {
 | 
						|
				res.reject('unknown format.')
 | 
						|
			}
 | 
						|
		})
 | 
						|
		.fail(function(){
 | 
						|
			res.reject('Loading', path, 'Error')
 | 
						|
		})
 | 
						|
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Save, ribbons and marks to cache
 | 
						|
//
 | 
						|
// NOTE: this will NOT save images, that operation must be explicitly 
 | 
						|
// 		performed by saveFileImages(...)
 | 
						|
function saveFileState(name, no_normalize_path){
 | 
						|
	name = name == null ? Date.timeStamp() : name
 | 
						|
 | 
						|
	if(!no_normalize_path){
 | 
						|
		name = normalizePath(CACHE_DIR_VAR +'/'+ name)
 | 
						|
 | 
						|
	// write .image_file only if saving data to a non-cache dir...
 | 
						|
	// XXX check if this is correct...
 | 
						|
	} else {
 | 
						|
		if(DATA.image_file == null){
 | 
						|
			DATA.image_file = name + '-images.json'
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	var data = getAllData()
 | 
						|
	data.current = DATA.current
 | 
						|
 | 
						|
	dumpJSON(name + '-data.json', data)
 | 
						|
	// XXX do we need to do this???
 | 
						|
	saveFileMarks(name)
 | 
						|
 | 
						|
	// save the updated images...
 | 
						|
	if(IMAGES_UPDATED.length > 0){
 | 
						|
		var updated = {}
 | 
						|
		$.each(IMAGES_UPDATED, function(i, e){
 | 
						|
			updated[e] = IMAGES[e]
 | 
						|
		})
 | 
						|
		dumpJSON(name + '-images-diff.json', updated)
 | 
						|
		IMAGES_UPDATED = []
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Load a directory as-is
 | 
						|
//
 | 
						|
// XXX check if we need to pass down sorting settings to the generators...
 | 
						|
function loadRawDir(path, no_preview_processing, prefix){
 | 
						|
	prefix = prefix == null ? 'Data' : prefix
 | 
						|
	prefix = prefix === false ? null : prefix
 | 
						|
 | 
						|
	var files = listDir(path)
 | 
						|
 | 
						|
	var res = $.Deferred()
 | 
						|
 | 
						|
	// filter images...
 | 
						|
	var image_paths = $.map(files, function(e){
 | 
						|
		return IMAGE_PATTERN.test(e) ? e : null
 | 
						|
	})
 | 
						|
 | 
						|
	if(image_paths.length == 0){
 | 
						|
		// no images in path...
 | 
						|
		res.notify(prefix, 'Load', path, 'Error')
 | 
						|
		return res.reject()
 | 
						|
	}
 | 
						|
 | 
						|
	setBaseURL(path)
 | 
						|
 | 
						|
	IMAGES = imagesFromUrls(image_paths)
 | 
						|
	res.notify(prefix, 'Loaded', 'Images.')
 | 
						|
	IMAGES_CREATED = true
 | 
						|
 | 
						|
	DATA = dataFromImages(IMAGES)
 | 
						|
	res.notify(prefix, 'Loaded', 'Data.')
 | 
						|
 | 
						|
	// XXX this will reload viewer...
 | 
						|
	//updateRibbonsFromFavDirs()
 | 
						|
	DATA.ribbons = ribbonsFromFavDirs(null, null, imageOrderCmp)
 | 
						|
	res.notify(prefix, 'Loaded', 'Fav dirs.')
 | 
						|
 | 
						|
	MARKED = []
 | 
						|
 | 
						|
	reloadViewer()
 | 
						|
 | 
						|
	// read orientation form files...
 | 
						|
	res.notify(prefix, 'Loading', 'Images orientation.')
 | 
						|
	var o = updateImagesOrientationQ()
 | 
						|
		.done(function(){
 | 
						|
			res.notify(prefix, 'Loaded', 'Images orientation.')
 | 
						|
		})
 | 
						|
 | 
						|
	// load/generate previews...
 | 
						|
	if(!no_preview_processing){
 | 
						|
		res.notify(prefix, 'Loading/Generating', 'Previews.')
 | 
						|
		var p = makeImagesPreviewsQ()
 | 
						|
			.done(function(){
 | 
						|
				res.notify(prefix, 'Loaded', 'Previews.')
 | 
						|
			})
 | 
						|
 | 
						|
	} else {
 | 
						|
		var p = 0
 | 
						|
	}
 | 
						|
 | 
						|
	// NOTE: we are not waiting for previews and orientation...
 | 
						|
	return res.resolve()
 | 
						|
 | 
						|
	/* XXX do we need to make everyone wait for previews and orientation???
 | 
						|
	$.when(o, p).done(function(){
 | 
						|
		res.resolve()
 | 
						|
	})
 | 
						|
	return res
 | 
						|
	*/
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Load a path
 | 
						|
//
 | 
						|
// This will try and do one of the following in order:
 | 
						|
// 	1) look for a cache and load it,
 | 
						|
// 	2) load data from within the directory
 | 
						|
// 	3) load a directory as-is
 | 
						|
// 		load fav dirs
 | 
						|
//
 | 
						|
// NOTE: this will create an images.json file in cache on opening an 
 | 
						|
// 		un-cached dir (XXX is this correct???)
 | 
						|
function loadDir(path, no_preview_processing, prefix){
 | 
						|
	prefix = prefix == null ? 'Data' : prefix
 | 
						|
	prefix = prefix === false ? null : prefix
 | 
						|
 | 
						|
	// stop all workers running on current image set before we 
 | 
						|
	// move to the next...
 | 
						|
	// XXX is this the correct sopot for this???
 | 
						|
	killAllWorkers()
 | 
						|
 | 
						|
	IMAGES_CREATED = false
 | 
						|
 | 
						|
	path = normalizePath(path)
 | 
						|
	var orig_path = path
 | 
						|
	var data
 | 
						|
 | 
						|
	var res = $.Deferred()
 | 
						|
 | 
						|
	res.notify(prefix, 'Loading', path)
 | 
						|
 | 
						|
	var files = listDir(path)
 | 
						|
 | 
						|
	if(files == null){
 | 
						|
		//showErrorStatus('No files in path: ' + path)
 | 
						|
		res.notify('load_error', path)
 | 
						|
		return res.reject()
 | 
						|
	}
 | 
						|
 | 
						|
	// see if there is a cache...
 | 
						|
	if(files.indexOf(CACHE_DIR) >= 0){
 | 
						|
		path = path +'/'+ CACHE_DIR
 | 
						|
	}
 | 
						|
 | 
						|
	bubbleProgress(prefix, 
 | 
						|
			loadFileState(path, false), res, true)
 | 
						|
		.done(function(){
 | 
						|
			res.resolve()
 | 
						|
		})
 | 
						|
		.fail(function(){
 | 
						|
			bubbleProgress('Raw directory', loadRawDir(orig_path, no_preview_processing), res)
 | 
						|
		})
 | 
						|
 | 
						|
	return res
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Load ribbon structure from fav directory tree
 | 
						|
//
 | 
						|
// XXX loads duplicate images....
 | 
						|
function updateRibbonsFromFavDirs(){
 | 
						|
	DATA.ribbons = ribbonsFromFavDirs(null, null, imageOrderCmp)
 | 
						|
	sortImagesByDate()
 | 
						|
	reloadViewer()
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Export current state to directory...
 | 
						|
//
 | 
						|
// XXX this copies the files in parallel, make it sync and sequential...
 | 
						|
// 		...reason is simple, if we stop the copy we need to end up with 
 | 
						|
// 		part of the files copied full rather than all partially...
 | 
						|
function exportTo(path, im_name, dir_name, size){
 | 
						|
	path = path == null ? BASE_URL : path
 | 
						|
	im_name = im_name == null ? '%f' : im_name
 | 
						|
	dir_name = dir_name == null ? 'fav' : dir_name
 | 
						|
	size = size == null ? 1000 : size
 | 
						|
 | 
						|
	// starting point...
 | 
						|
	//var deferred = $.Deferred().resolve()
 | 
						|
 | 
						|
	var base_path = path
 | 
						|
	path = normalizePath(path)
 | 
						|
 | 
						|
	var order = DATA.order
 | 
						|
	var Z = (('10e' + (order.length + '').length) * 1 + '').slice(2)
 | 
						|
 | 
						|
	// mainly used for file naming, gives us ability to number images 
 | 
						|
	// in the current selection...
 | 
						|
	var selection = []
 | 
						|
	$.each(DATA.ribbons, function(_, e){
 | 
						|
		selection = selection.concat(e)
 | 
						|
	})
 | 
						|
	selection.sort(imageOrderCmp)
 | 
						|
	var z = (('10e' + (selection.length + '').length) * 1 + '').slice(2)
 | 
						|
 | 
						|
	// go through ribbons...
 | 
						|
	for(var i=DATA.ribbons.length-1; i >= 0; i--){
 | 
						|
		var ribbon = DATA.ribbons[i]
 | 
						|
		// go through images...
 | 
						|
		for(var j=0; j < ribbon.length; j++){
 | 
						|
			var gid = ribbon[j]
 | 
						|
			// get correct preview...
 | 
						|
			var src = getBestPreview(gid, size).url
 | 
						|
			var orig = IMAGES[gid].path.split('/').pop()
 | 
						|
 | 
						|
			// XXX might be a good idea to combine this with docs as a 
 | 
						|
			// 		single mechanism...
 | 
						|
			// form image name...
 | 
						|
			var dest = im_name
 | 
						|
			// full filename...
 | 
						|
			dest = dest.replace('%f', orig)
 | 
						|
			// file name w.o. ext...
 | 
						|
			dest = dest.replace('%n', orig.split('.')[0])
 | 
						|
			// ext...
 | 
						|
			dest = dest.replace('%e', '.'+src.split('.').pop())
 | 
						|
			// marked status...
 | 
						|
			dest = dest.replace(/%\(([^)]*)\)m/, MARKED.indexOf(gid) >= 0 ? '$1' : '')
 | 
						|
			// gid...
 | 
						|
			dest = dest.replace('%gid', gid)
 | 
						|
			dest = dest.replace('%g', gid.slice(34))
 | 
						|
			// global order...
 | 
						|
			var o = order.indexOf(gid) + ''
 | 
						|
			dest = dest.replace('%I', (Z + o).slice(o.length))
 | 
						|
			// current order...
 | 
						|
			var o = selection.indexOf(gid) + ''
 | 
						|
			dest = dest.replace('%i', (z + o).slice(o.length))
 | 
						|
			// XXX Metadata...
 | 
						|
			// XXX
 | 
						|
 | 
						|
			dest = path +'/'+ dest
 | 
						|
 | 
						|
			// copy... 
 | 
						|
			copyFile(src, dest)
 | 
						|
		}
 | 
						|
 | 
						|
		path = normalizePath(path +'/'+ dir_name)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************/
 | 
						|
 | 
						|
// NOTE: this will overwrite current image orientation...
 | 
						|
//
 | 
						|
// XXX this depends on getImageOrientation(...)
 | 
						|
function updateImageOrientation(gid, no_update_loaded){
 | 
						|
	gid = gid == null ? getImageGID() : gid
 | 
						|
	var img = IMAGES[gid]
 | 
						|
 | 
						|
	if(img == null){
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	return getImageOrientation(normalizePath(img.path))
 | 
						|
		.done(function(o){
 | 
						|
			var o_o = img.orientation
 | 
						|
			var o_f = img.flipped
 | 
						|
 | 
						|
			img.orientation = o.orientation
 | 
						|
			img.flipped = o.flipped
 | 
						|
 | 
						|
			// mark image dirty...
 | 
						|
			if((o_o != o.orientation || o_f != o.flipped ) 
 | 
						|
					&& IMAGES_UPDATED.indexOf(gid) < 0){
 | 
						|
				IMAGES_UPDATED.push(gid)
 | 
						|
			}
 | 
						|
 | 
						|
			// update image if loaded...
 | 
						|
			if(!no_update_loaded){
 | 
						|
				var o = getImage(gid)
 | 
						|
				if(o.length > 0){
 | 
						|
					updateImage(o)
 | 
						|
				}
 | 
						|
			}
 | 
						|
		})
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
function updateImagesOrientation(gids, no_update_loaded){
 | 
						|
	gids = gids == null ? getClosestGIDs() : gids
 | 
						|
	var res = []
 | 
						|
 | 
						|
	$.each(gids, function(_, gid){
 | 
						|
		res.push(updateImageOrientation(gid, no_update_loaded))
 | 
						|
	})
 | 
						|
 | 
						|
	return $.when.apply(null, res)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// queued version of updateImagesOrientation(...)
 | 
						|
//
 | 
						|
function updateImagesOrientationQ(gids, no_update_loaded){
 | 
						|
	gids = gids == null ? getClosestGIDs() : gids
 | 
						|
 | 
						|
	var queue = getWorkerQueue('image_orientation_reader')
 | 
						|
 | 
						|
	var last = null
 | 
						|
 | 
						|
	// attach workers to queue...
 | 
						|
	$.each(gids, function(_, gid){
 | 
						|
		last = queue.enqueue(updateImageOrientation, gid, no_update_loaded)
 | 
						|
			.done(function(){ queue.notify(gid, 'done') })
 | 
						|
			.fail(function(){ queue.notify(gid, 'fail') })
 | 
						|
	})
 | 
						|
 | 
						|
	return queue
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
* vim:set ts=4 sw=4 :                                                */
 |