2013-06-07 00:56:43 +04:00
|
|
|
/**********************************************************************
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
//var DEBUG = DEBUG != null ? DEBUG : true
|
|
|
|
|
|
2013-12-15 19:25:09 +04:00
|
|
|
// Flag indicating a new image file was constructed...
|
|
|
|
|
// XXX do we need this?
|
|
|
|
|
var IMAGES_CREATED = false
|
|
|
|
|
|
2013-12-15 18:56:21 +04:00
|
|
|
var IMAGE_PATTERN = /.*\.(jpg|jpeg|png|gif)$/i
|
|
|
|
|
|
2013-12-14 05:07:57 +04:00
|
|
|
var FILE_LOADERS = []
|
2013-12-24 05:23:51 +04:00
|
|
|
var FILE_SAVERS = {}
|
|
|
|
|
var FILES_UPDATED = []
|
2013-12-14 05:07:57 +04:00
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
|
* File storage (Extension API -- CEF/PhoneGap/...)
|
|
|
|
|
*
|
|
|
|
|
* XXX need to cleanup this section...
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************* Helpers ***/
|
|
|
|
|
|
2014-01-20 10:24:49 +04:00
|
|
|
function makeBaseFilename(base, ext){
|
2014-01-20 09:40:36 +04:00
|
|
|
ext = ext == null ? CONFIG.json_ext : ext
|
|
|
|
|
|
2014-01-20 10:24:49 +04:00
|
|
|
return CONFIG.base_file_pattern
|
|
|
|
|
.replace('${BASE}', base)
|
|
|
|
|
.replace('${EXT}', ext)
|
2014-01-20 09:40:36 +04:00
|
|
|
}
|
|
|
|
|
function makeFilename(base, date, ext){
|
|
|
|
|
date = date == null ? Date.timeStamp() : date
|
|
|
|
|
ext = ext == null ? CONFIG.json_ext : ext
|
|
|
|
|
|
|
|
|
|
return CONFIG.file_pattern
|
|
|
|
|
.replace('${DATE}', date)
|
|
|
|
|
.replace('${BASE}', base)
|
|
|
|
|
.replace('${EXT}', ext)
|
|
|
|
|
}
|
|
|
|
|
function makeFilenamePattern(base, ext){
|
|
|
|
|
return RegExp(makeFilename(base, '^[0-9]*', ext)+'$')
|
|
|
|
|
}
|
2014-01-20 10:24:49 +04:00
|
|
|
|
2014-01-20 09:40:36 +04:00
|
|
|
function makeDiffFilename(base, date, diff, ext){
|
|
|
|
|
date = date == null ? Date.timeStamp() : date
|
|
|
|
|
diff = diff == null ? CONFIG.diff_suffix : diff
|
|
|
|
|
ext = ext == null ? CONFIG.json_ext : ext
|
|
|
|
|
|
|
|
|
|
return CONFIG.diff_file_pattern
|
|
|
|
|
.replace('${DATE}', date)
|
|
|
|
|
.replace('${BASE}', base)
|
|
|
|
|
.replace('${DIFF_SUFIX}', diff)
|
|
|
|
|
.replace('${EXT}', ext)
|
|
|
|
|
}
|
|
|
|
|
function makeDiffFilePattern(base, diff, ext){
|
|
|
|
|
return RegExp(makeDiffFilename(base, '^[0-9]*', ext)+'$')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
// 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.
|
2013-06-08 01:48:22 +04:00
|
|
|
function statusNotify(prefix, loader, not_queued){
|
2014-01-26 08:43:44 +04:00
|
|
|
not_queued = not_queued == null ? true : not_queued
|
2013-06-08 01:48:22 +04:00
|
|
|
var report = not_queued == true ? showStatus : showStatusQ
|
2013-06-07 00:56:43 +04:00
|
|
|
if(loader == null){
|
|
|
|
|
loader = prefix
|
|
|
|
|
prefix = null
|
|
|
|
|
}
|
|
|
|
|
return loader
|
|
|
|
|
.progress(function(){
|
2014-01-25 07:58:47 +04:00
|
|
|
var args = args2array(arguments)
|
|
|
|
|
|
|
|
|
|
var getter = args[args.length-1]
|
|
|
|
|
if(getter != null && getter.isResolved != null){
|
|
|
|
|
args.pop()
|
|
|
|
|
.done(function(){
|
|
|
|
|
report(args.join(': '))
|
|
|
|
|
})
|
|
|
|
|
.fail(function(){
|
2014-01-26 08:43:44 +04:00
|
|
|
showErrorStatus(args.join(': '))
|
2014-01-25 07:58:47 +04:00
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
if(prefix != null && prefix != ''){
|
|
|
|
|
args.splice(0, 0, prefix)
|
|
|
|
|
}
|
|
|
|
|
if(args.indexOf('Error') >= 0){
|
|
|
|
|
args.pop()
|
|
|
|
|
return showErrorStatus(args.join(': '))
|
|
|
|
|
}
|
2013-06-08 01:48:22 +04:00
|
|
|
return report(args.join(': '))
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-01-26 08:43:44 +04:00
|
|
|
// XXX
|
|
|
|
|
function statusProgress(msg, loader){
|
|
|
|
|
var progress = progressBar(msg)
|
|
|
|
|
var total = 0
|
|
|
|
|
var done = 0
|
|
|
|
|
|
|
|
|
|
return loader
|
|
|
|
|
.done(function(){
|
|
|
|
|
// XXX why does this close the progress bar right away???
|
|
|
|
|
closeProgressBar(progress)
|
|
|
|
|
})
|
|
|
|
|
.progress(function(){
|
|
|
|
|
var args = args2array(arguments)
|
|
|
|
|
var getter = args[args.length-1]
|
|
|
|
|
total += 1
|
|
|
|
|
|
|
|
|
|
// the getter is a deferred...
|
|
|
|
|
if(getter != null && getter.isResolved != null){
|
|
|
|
|
args.pop()
|
|
|
|
|
.always(function(){
|
|
|
|
|
done += 1
|
|
|
|
|
updateProgressBar(progress, done, total)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// no getter...
|
|
|
|
|
} else {
|
|
|
|
|
done += 1
|
|
|
|
|
updateProgressBar(progress, done, total)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
// 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){
|
2014-01-25 07:58:47 +04:00
|
|
|
only_progress = only_progress == null ? false : only_progress
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
from
|
|
|
|
|
.progress(function(){
|
2014-01-25 07:58:47 +04:00
|
|
|
var args = args2array(arguments)
|
2013-06-07 00:56:43 +04:00
|
|
|
prefix != null && args.splice(0, 0, prefix)
|
|
|
|
|
to.notify.apply(to, args)
|
|
|
|
|
})
|
|
|
|
|
|
2014-01-25 07:58:47 +04:00
|
|
|
if(!only_progress){
|
2013-06-07 00:56:43 +04:00
|
|
|
from
|
|
|
|
|
.done(function(){
|
2014-01-25 07:58:47 +04:00
|
|
|
var args = args2array(arguments)
|
2013-06-07 00:56:43 +04:00
|
|
|
to.resolve.apply(to, args)
|
|
|
|
|
})
|
|
|
|
|
.fail(function(){
|
2014-01-25 07:58:47 +04:00
|
|
|
var args = args2array(arguments)
|
2013-06-07 00:56:43 +04:00
|
|
|
prefix != null && args.splice(0, 0, prefix)
|
|
|
|
|
to.reject.apply(to, args)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return from
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-01-26 08:50:40 +04:00
|
|
|
// Semi-generic deferred JSON file loader
|
2013-06-07 00:56:43 +04:00
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
//
|
2013-10-14 18:14:51 +04:00
|
|
|
// if default_data is then not finding a file will not fail, instead the
|
|
|
|
|
// default_data will be the resolved data.
|
|
|
|
|
//
|
2013-06-14 13:16:27 +04:00
|
|
|
// NOTE: if diffs are available this expects the file to contain an object,
|
2014-01-26 08:50:40 +04:00
|
|
|
// and will extend ($.extend(..)) that object.
|
2013-06-07 00:56:43 +04:00
|
|
|
// 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.
|
2014-01-26 08:50:40 +04:00
|
|
|
function loadLatestJSONFile(path, dfl, pattern, diff_pattern, default_data){
|
2013-06-08 23:53:35 +04:00
|
|
|
var pparts = path.split(/[\/\\]/)
|
|
|
|
|
dfl = dfl == null ? pparts.pop() : dfl
|
|
|
|
|
//path = path == dfl ? '.' : path
|
|
|
|
|
path = pparts.join('/')
|
2013-06-07 00:56:43 +04:00
|
|
|
|
2014-01-25 07:58:47 +04:00
|
|
|
var tracker = $.Deferred()
|
2013-06-07 00:56:43 +04:00
|
|
|
|
2013-06-08 23:53:35 +04:00
|
|
|
if(dfl == ''){
|
2014-01-25 07:58:47 +04:00
|
|
|
return tracker.reject()
|
2013-06-08 23:53:35 +04:00
|
|
|
}
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
// can't find diffs if can't list dirs...
|
|
|
|
|
if(window.listDir == null && (pattern != null || diff_pattern != null)){
|
2014-01-25 07:58:47 +04:00
|
|
|
return tracker.reject('listDir unsupported.')
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
2014-01-27 19:02:00 +04:00
|
|
|
var file_list = null
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
// find the latest...
|
|
|
|
|
if(pattern != null){
|
2014-01-27 19:02:00 +04:00
|
|
|
file_list = listDir(path)
|
2013-06-07 00:56:43 +04:00
|
|
|
pattern = RegExp(pattern)
|
2014-01-27 19:02:00 +04:00
|
|
|
var file = $.map(file_list, function(e){
|
2013-06-07 00:56:43 +04:00
|
|
|
return pattern.test(e) ? e : null
|
|
|
|
|
}).sort().reverse()[0]
|
|
|
|
|
}
|
|
|
|
|
var file = file == null ? dfl : file
|
2014-01-02 08:44:40 +04:00
|
|
|
var base_date = file.split('-')[0]
|
|
|
|
|
base_date = base_date == file ? '' : base_date
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
var diff_data = {}
|
|
|
|
|
var diff = true
|
|
|
|
|
|
|
|
|
|
// collect and merge diffs...
|
|
|
|
|
if(diff_pattern != null){
|
2014-01-27 19:02:00 +04:00
|
|
|
file_list = file_list == null ? listDir(path) : file_list
|
2013-06-07 00:56:43 +04:00
|
|
|
diff_pattern = RegExp(diff_pattern)
|
|
|
|
|
var diff_data = [diff_data]
|
2014-01-27 19:02:00 +04:00
|
|
|
var diffs_names = $.map(file_list, function(e){
|
2014-01-02 08:44:40 +04:00
|
|
|
return diff_pattern.test(e) && e.split('-')[0] >= base_date ? e : null
|
2013-06-07 00:56:43 +04:00
|
|
|
}).sort()
|
|
|
|
|
diff = $.when.apply(null, $.map(diffs_names, function(e, i){
|
2014-01-25 07:58:47 +04:00
|
|
|
var getter = $.getJSON(path +'/'+ e)
|
2013-06-07 00:56:43 +04:00
|
|
|
.done(function(data){
|
2014-01-25 07:58:47 +04:00
|
|
|
// NOTE: we are not using push here so as to
|
|
|
|
|
// keep the sort order...
|
2013-06-07 00:56:43 +04:00
|
|
|
diff_data[i+1] = data
|
|
|
|
|
})
|
2014-01-26 08:43:44 +04:00
|
|
|
// XXX need to notify as early as possible but doing
|
|
|
|
|
// it outside this (see below) will notify BEFORE
|
|
|
|
|
// anyone's listening...
|
2014-01-25 07:58:47 +04:00
|
|
|
.always(function(){
|
|
|
|
|
tracker.notify(e, getter)
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
2014-01-25 07:58:47 +04:00
|
|
|
/*
|
|
|
|
|
// XXX the problem here is if we miss this, then there
|
|
|
|
|
// is no chance to get it back...
|
|
|
|
|
tracker.notify(e, getter)
|
|
|
|
|
*/
|
2014-01-26 08:43:44 +04:00
|
|
|
|
2014-01-25 07:58:47 +04:00
|
|
|
return getter
|
2013-06-07 00:56:43 +04:00
|
|
|
}))
|
2014-01-25 07:58:47 +04:00
|
|
|
// merge the diffs...
|
2013-06-07 00:56:43 +04:00
|
|
|
// 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...
|
2014-01-25 07:58:47 +04:00
|
|
|
var getter = $.getJSON(path +'/'+ file)
|
|
|
|
|
.always(function(){
|
|
|
|
|
tracker.notify(file, getter)
|
|
|
|
|
})
|
|
|
|
|
$.when(diff, getter)
|
2013-06-07 00:56:43 +04:00
|
|
|
.done(function(_, json){
|
|
|
|
|
json = json[0]
|
|
|
|
|
|
|
|
|
|
// merge diffs...
|
|
|
|
|
if(Object.keys(diff_data).length != 0){
|
|
|
|
|
$.extend(json, diff_data)
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-25 07:58:47 +04:00
|
|
|
tracker.resolve(json)
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
.fail(function(){
|
2013-10-14 18:14:51 +04:00
|
|
|
if(default_data != null){
|
2014-01-25 07:58:47 +04:00
|
|
|
tracker.resolve(default_data)
|
2013-10-14 18:14:51 +04:00
|
|
|
} else {
|
2014-01-25 07:58:47 +04:00
|
|
|
tracker.reject()
|
2013-10-14 18:14:51 +04:00
|
|
|
}
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
|
2014-01-25 07:58:47 +04:00
|
|
|
return tracker
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-01-20 10:24:49 +04:00
|
|
|
// NOTE: config change to name will not affect this...
|
|
|
|
|
function makeFileLoader(title, name, default_data, set_data, error, evt_name, skip_reg){
|
2014-01-20 09:40:36 +04:00
|
|
|
var _loader = function(path){
|
2014-01-20 10:24:49 +04:00
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
|
|
|
|
// NOTE: these are static!!
|
|
|
|
|
var file_dfl = makeBaseFilename(name)
|
|
|
|
|
var file_pattern = makeFilenamePattern(name)
|
|
|
|
|
|
|
|
|
|
// default locations...
|
|
|
|
|
if(path == null){
|
|
|
|
|
var base = normalizePath(CONFIG.cache_dir_var)
|
2014-01-26 08:50:40 +04:00
|
|
|
var loader = loadLatestJSONFile(base,
|
2014-01-20 10:24:49 +04:00
|
|
|
file_dfl,
|
|
|
|
|
file_pattern,
|
|
|
|
|
null,
|
|
|
|
|
default_data)
|
|
|
|
|
|
|
|
|
|
// explicit path...
|
|
|
|
|
// XXX need to account for paths without a CONFIG.cache_dir
|
|
|
|
|
} else {
|
|
|
|
|
path = normalizePath(path)
|
|
|
|
|
var base = path.split(CONFIG.cache_dir)[0]
|
|
|
|
|
//base = normalizePath(path +'/'+ CONFIG.cache_dir_var)
|
|
|
|
|
base = path +'/'+ CONFIG.cache_dir
|
|
|
|
|
|
|
|
|
|
// XXX is this correct???
|
2014-01-26 08:50:40 +04:00
|
|
|
var loader = loadLatestJSONFile(base,
|
2014-01-20 10:24:49 +04:00
|
|
|
path.split(base)[0],
|
|
|
|
|
RegExp(path.split(base)[0]),
|
|
|
|
|
null,
|
|
|
|
|
default_data)
|
|
|
|
|
}
|
2013-12-14 05:07:57 +04:00
|
|
|
|
2013-12-20 06:10:45 +04:00
|
|
|
res.done(set_data)
|
|
|
|
|
|
2014-01-20 10:24:49 +04:00
|
|
|
bubbleProgress(title, loader, res)
|
|
|
|
|
|
2013-12-28 08:57:11 +04:00
|
|
|
if(error != null){
|
|
|
|
|
res.fail(error)
|
|
|
|
|
}
|
2013-12-20 06:10:45 +04:00
|
|
|
if(evt_name != null){
|
|
|
|
|
res.done(function(){ $('.viewer').trigger(evt_name) })
|
|
|
|
|
}
|
2013-12-14 05:07:57 +04:00
|
|
|
return res
|
|
|
|
|
}
|
2013-12-14 06:58:13 +04:00
|
|
|
!skip_reg && FILE_LOADERS.push(_loader)
|
|
|
|
|
return _loader
|
2013-12-14 05:07:57 +04:00
|
|
|
}
|
2014-01-20 10:24:49 +04:00
|
|
|
|
|
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
// XXX make this check for updates -- no need to re-save if nothing
|
|
|
|
|
// changed...
|
2013-12-24 05:23:51 +04:00
|
|
|
function makeFileSaver(title, file_dfl, get_data, skip_reg){
|
2014-01-20 09:40:36 +04:00
|
|
|
var _saver = function(path, date){
|
|
|
|
|
path = path == null
|
|
|
|
|
? normalizePath(CONFIG.cache_dir_var +'/'+ makeFilename(file_dfl, date))
|
|
|
|
|
: path
|
2013-12-14 05:07:57 +04:00
|
|
|
|
2014-01-20 09:40:36 +04:00
|
|
|
dumpJSON(path, get_data())
|
2013-12-14 05:07:57 +04:00
|
|
|
}
|
2013-12-24 05:23:51 +04:00
|
|
|
if(!skip_reg){
|
|
|
|
|
FILE_SAVERS[title] = _saver
|
|
|
|
|
}
|
2013-12-14 06:58:13 +04:00
|
|
|
return _saver
|
2013-12-14 05:07:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-24 05:23:51 +04:00
|
|
|
// mark file type as updated...
|
|
|
|
|
function fileUpdated(name){
|
|
|
|
|
if(FILES_UPDATED.indexOf(name) < 0 && name in FILE_SAVERS){
|
|
|
|
|
FILES_UPDATED.push(name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
function runFileLoaders(prefix, res){
|
2013-12-25 03:47:29 +04:00
|
|
|
FILES_UPDATED = []
|
2013-12-14 06:07:22 +04:00
|
|
|
return $.when.apply(null, FILE_LOADERS.map(function(load){
|
|
|
|
|
return bubbleProgress(prefix, load(), res, true)
|
|
|
|
|
}))
|
|
|
|
|
}
|
2014-01-20 10:24:49 +04:00
|
|
|
|
|
|
|
|
|
2013-12-24 05:23:51 +04:00
|
|
|
// NOTE: if all is set, this will force save everything...
|
2013-12-14 06:07:22 +04:00
|
|
|
// XXX do we need bubbleProgress(..) here???
|
2014-01-20 09:40:36 +04:00
|
|
|
function runFileSavers(path, date, all){
|
2013-12-24 05:23:51 +04:00
|
|
|
var updated = FILES_UPDATED
|
|
|
|
|
FILES_UPDATED = []
|
|
|
|
|
for(var n in FILE_SAVERS){
|
|
|
|
|
if(all || updated.indexOf(n) >= 0){
|
|
|
|
|
showStatusQ('Saving: File:', n)
|
2014-01-20 09:40:36 +04:00
|
|
|
FILE_SAVERS[n](path, date)
|
2013-12-24 05:23:51 +04:00
|
|
|
}
|
|
|
|
|
}
|
2013-12-14 06:07:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 05:07:57 +04:00
|
|
|
|
2013-12-24 22:03:54 +04:00
|
|
|
/*********************************************************************/
|
|
|
|
|
// XXX should this be here or in data.js???
|
|
|
|
|
|
|
|
|
|
var saveFileData = makeFileSaver(
|
|
|
|
|
'Data',
|
2014-01-20 09:40:36 +04:00
|
|
|
CONFIG.data_file,
|
2013-12-24 22:03:54 +04:00
|
|
|
function(){
|
|
|
|
|
var data = getAllData()
|
|
|
|
|
data.current = DATA.current
|
|
|
|
|
return data
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
2013-12-26 03:57:32 +04:00
|
|
|
// NOTE: this will set the updated flag ONLY of out of cropped mode...
|
2013-12-24 22:03:54 +04:00
|
|
|
function dataUpdated(){
|
2013-12-26 03:57:32 +04:00
|
|
|
if(!isViewCropped()){
|
|
|
|
|
fileUpdated('Data')
|
2014-01-02 06:59:06 +04:00
|
|
|
$('.viewer').trigger('dataUpdated')
|
2013-12-26 03:57:32 +04:00
|
|
|
}
|
2013-12-24 22:03:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 05:07:57 +04:00
|
|
|
/*********************************************************************/
|
|
|
|
|
|
2013-06-08 18:28:10 +04:00
|
|
|
// Construct a ribbons hierarchy from the fav dirs structure
|
|
|
|
|
//
|
|
|
|
|
// NOTE: this depends on listDir(...)
|
|
|
|
|
// NOTE: this assumes that images contain ALL the images...
|
2013-06-08 20:04:27 +04:00
|
|
|
// NOTE: this assumes that all file names are unique...
|
2013-11-01 15:15:01 +04:00
|
|
|
function ribbonsFromFavDirs(path, images, cmp, dir_name){
|
2013-06-08 18:28:10 +04:00
|
|
|
path = path == null ? getBaseURL() : path
|
|
|
|
|
images = images == null ? IMAGES : images
|
2013-11-01 15:15:01 +04:00
|
|
|
dir_name = dir_name == null ? 'fav' : dir_name
|
2013-06-08 18:28:10 +04:00
|
|
|
|
|
|
|
|
// build a reverse name-gid index for fast access...
|
|
|
|
|
var index = {}
|
|
|
|
|
var name
|
|
|
|
|
for(var gid in images){
|
2013-10-18 05:03:11 +04:00
|
|
|
name = getImageFileName(gid)
|
2013-06-08 18:28:10 +04:00
|
|
|
// 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
|
2013-11-01 15:15:01 +04:00
|
|
|
while(files.indexOf(dir_name) >= 0){
|
|
|
|
|
cur_path += '/' + dir_name
|
2013-06-08 18:28:10 +04:00
|
|
|
files = listDir(cur_path)
|
|
|
|
|
ribbon = []
|
|
|
|
|
// collect the images...
|
|
|
|
|
$.each(files, function(i, e){
|
|
|
|
|
var _gid = index[e]
|
2013-06-08 20:04:27 +04:00
|
|
|
// 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
|
|
|
|
|
}
|
2013-06-08 18:28:10 +04:00
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
})
|
2013-06-08 20:04:27 +04:00
|
|
|
|
|
|
|
|
ribbon.push(_gid)
|
2013-06-08 18:28:10 +04:00
|
|
|
})
|
|
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
|
|
|
|
// 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){
|
2013-12-15 18:56:21 +04:00
|
|
|
var base = normalizePath(CONFIG.cache_dir_var)
|
2014-01-26 08:50:40 +04:00
|
|
|
var loader = loadLatestJSONFile(base,
|
2014-01-20 09:40:36 +04:00
|
|
|
makeBaseFilename(CONFIG.images_file),
|
|
|
|
|
makeFilenamePattern(CONFIG.images_file),
|
|
|
|
|
makeDiffFilePattern(CONFIG.images_file))
|
2013-06-07 00:56:43 +04:00
|
|
|
|
2013-06-09 02:44:20 +04:00
|
|
|
// explicit base dir...
|
|
|
|
|
} else if(!/\.json$/i.test(path)) {
|
2013-12-15 18:56:21 +04:00
|
|
|
var base = normalizePath(path +'/'+ CONFIG.cache_dir_var)
|
2014-01-26 08:50:40 +04:00
|
|
|
var loader = loadLatestJSONFile(base,
|
2014-01-20 09:40:36 +04:00
|
|
|
makeBaseFilename(CONFIG.images_file),
|
|
|
|
|
makeFilenamePattern(CONFIG.images_file),
|
|
|
|
|
makeDiffFilePattern(CONFIG.images_file))
|
2013-06-09 02:44:20 +04:00
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
// explicit path...
|
|
|
|
|
} else {
|
2014-01-26 08:50:40 +04:00
|
|
|
var loader = loadLatestJSONFile(normalizePath(path))
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bubbleProgress('Images', loader, res)
|
|
|
|
|
|
|
|
|
|
res.done(function(images){
|
|
|
|
|
IMAGES = images
|
2013-12-25 03:47:29 +04:00
|
|
|
IMAGES_UPDATED = []
|
2014-01-20 09:40:36 +04:00
|
|
|
IMAGES_CREATED = false
|
2013-12-15 05:42:22 +04:00
|
|
|
|
|
|
|
|
// XXX is this the correct spot to do this???
|
|
|
|
|
$('.viewer').trigger('imagesLoaded')
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Save current images list to file
|
|
|
|
|
//
|
2013-12-14 06:07:22 +04:00
|
|
|
// If no name is given this will merge all the diffs and save a "clean"
|
2013-06-07 00:56:43 +04:00
|
|
|
// (full) images.json file. Also removing the diff files.
|
|
|
|
|
//
|
2013-12-15 18:56:21 +04:00
|
|
|
// NOTE: this will use CONFIG.cache_dir as the location if no name is given.
|
2014-01-20 09:40:36 +04:00
|
|
|
function saveFileImages(name, date, remove_diffs){
|
2014-01-13 08:31:10 +04:00
|
|
|
remove_diffs = remove_diffs == null ? false : remove_diffs
|
2014-01-20 09:40:36 +04:00
|
|
|
name = name == null ? normalizePath(CONFIG.cache_dir_var +'/'+ makeFilename(CONFIG.images_file, date)) : name
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
if(window.dumpJSON == null){
|
|
|
|
|
showErrorStatus('Can\'t save to file.')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove the diffs...
|
|
|
|
|
if(remove_diffs){
|
2014-01-20 09:40:36 +04:00
|
|
|
var diff_pattern = makeDiffFilePattern(CONFIG.images_file)
|
2013-12-15 18:56:21 +04:00
|
|
|
$.each($.map(listDir(normalizePath(CONFIG.cache_dir_var)), function(e){
|
2014-01-20 09:40:36 +04:00
|
|
|
return diff_pattern.test(e) ? e : null
|
2013-06-07 00:56:43 +04:00
|
|
|
}), function(i, e){
|
2014-01-20 09:40:36 +04:00
|
|
|
showStatusQ('Removeing:', e)
|
2013-12-15 18:56:21 +04:00
|
|
|
removeFile(normalizePath(CONFIG.cache_dir_var +'/'+ e))
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-20 09:40:36 +04:00
|
|
|
dumpJSON(name, IMAGES)
|
|
|
|
|
|
|
|
|
|
IMAGES_UPDATED = []
|
|
|
|
|
IMAGES_CREATED = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function saveFileImagesDiff(name, date){
|
|
|
|
|
var path = normalizePath(CONFIG.cache_dir_var)
|
|
|
|
|
name = name == null
|
|
|
|
|
? normalizePath(path +'/'+ makeDiffFilename(CONFIG.images_file, date))
|
|
|
|
|
: name
|
|
|
|
|
|
|
|
|
|
var updated = {}
|
|
|
|
|
$.each(IMAGES_UPDATED, function(i, e){
|
|
|
|
|
updated[e] = IMAGES[e]
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dumpJSON(name, updated)
|
2014-01-20 10:24:49 +04:00
|
|
|
|
2014-01-20 09:40:36 +04:00
|
|
|
IMAGES_UPDATED = []
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
// Load images, ribbons and run registered load callbacks...
|
2013-06-07 00:56:43 +04:00
|
|
|
//
|
|
|
|
|
// 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
|
2013-12-15 18:56:21 +04:00
|
|
|
var base = path.split(CONFIG.cache_dir)[0]
|
2013-06-07 00:56:43 +04:00
|
|
|
base = base == path ? '.' : base
|
|
|
|
|
} else {
|
2013-12-15 18:56:21 +04:00
|
|
|
var base = path.split(CONFIG.cache_dir)[0]
|
2013-06-07 00:56:43 +04:00
|
|
|
base = base == path ? '.' : base
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
|
|
|
|
bubbleProgress(prefix,
|
2014-01-26 08:50:40 +04:00
|
|
|
loadLatestJSONFile(path,
|
2014-01-20 09:40:36 +04:00
|
|
|
makeBaseFilename(CONFIG.data_file),
|
|
|
|
|
makeFilenamePattern(CONFIG.data_file)), res, true)
|
2013-06-07 00:56:43 +04:00
|
|
|
.done(function(json){
|
2013-06-08 18:28:10 +04:00
|
|
|
setBaseURL(base)
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
// legacy format...
|
|
|
|
|
if(json.version == null){
|
|
|
|
|
json = convertDataGen1(json)
|
|
|
|
|
DATA = json.data
|
|
|
|
|
IMAGES = json.images
|
|
|
|
|
MARKED = []
|
|
|
|
|
reloadViewer()
|
|
|
|
|
res.resolve()
|
|
|
|
|
|
2013-12-20 06:10:45 +04:00
|
|
|
// version 2.*
|
2013-12-24 22:08:18 +04:00
|
|
|
} else if(/2\.[0-9]*/.test(json.version)) {
|
2013-06-07 00:56:43 +04:00
|
|
|
DATA = json
|
|
|
|
|
$.when(
|
|
|
|
|
// XXX load config...
|
2013-12-24 22:03:54 +04:00
|
|
|
|
|
|
|
|
// load current position...
|
2013-12-24 22:08:18 +04:00
|
|
|
// added on 2.2
|
2013-12-24 22:03:54 +04:00
|
|
|
bubbleProgress(prefix,
|
2014-01-26 08:50:40 +04:00
|
|
|
loadLatestJSONFile(path,
|
2014-01-20 09:40:36 +04:00
|
|
|
makeBaseFilename(CONFIG.current_file),
|
2013-12-24 22:03:54 +04:00
|
|
|
null,
|
|
|
|
|
null,
|
|
|
|
|
DATA.current), res, true)
|
|
|
|
|
.done(function(cur){
|
|
|
|
|
DATA.current = cur
|
|
|
|
|
}),
|
2013-06-07 00:56:43 +04:00
|
|
|
// load images...
|
|
|
|
|
bubbleProgress(prefix,
|
2013-06-09 02:44:20 +04:00
|
|
|
loadFileImages(base), res, true),
|
|
|
|
|
//loadFileImages(DATA.image_file != null ?
|
|
|
|
|
// normalizePath(DATA.image_file, base)
|
|
|
|
|
// : null), res, true),
|
2013-12-14 06:07:22 +04:00
|
|
|
// run registered loaders...
|
2013-12-24 22:08:18 +04:00
|
|
|
// added on 2.1
|
|
|
|
|
// XXX bubbleProgress???
|
2013-12-14 05:07:57 +04:00
|
|
|
runFileLoaders(prefix, res))
|
2013-06-07 00:56:43 +04:00
|
|
|
.done(function(){
|
2013-12-20 06:10:45 +04:00
|
|
|
$('.viewer').trigger('fileStateLoaded')
|
2013-06-07 00:56:43 +04:00
|
|
|
reloadViewer()
|
|
|
|
|
res.resolve()
|
|
|
|
|
})
|
|
|
|
|
// XXX fail???
|
|
|
|
|
|
|
|
|
|
// unknown format...
|
|
|
|
|
} else {
|
|
|
|
|
res.reject('unknown format.')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.fail(function(){
|
|
|
|
|
res.reject('Loading', path, 'Error')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
// Save, ribbons and run registered save callbacks...
|
2013-06-07 00:56:43 +04:00
|
|
|
//
|
|
|
|
|
// NOTE: this will NOT save images, that operation must be explicitly
|
|
|
|
|
// performed by saveFileImages(...)
|
2014-01-20 09:40:36 +04:00
|
|
|
//
|
|
|
|
|
// XXX do propper reporting...
|
|
|
|
|
// XXX check if name is needed and how it works...
|
2013-06-07 00:56:43 +04:00
|
|
|
function saveFileState(name, no_normalize_path){
|
2014-01-20 09:40:36 +04:00
|
|
|
var date = Date.timeStamp()
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
if(!no_normalize_path){
|
2013-12-24 22:03:54 +04:00
|
|
|
var path = normalizePath(CONFIG.cache_dir_var)
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
2014-01-20 09:40:36 +04:00
|
|
|
var cur_file = makeBaseFilename(CONFIG.current_file)
|
|
|
|
|
showStatusQ('Saving: File:', cur_file)
|
2013-12-24 22:03:54 +04:00
|
|
|
// allways update the current position...
|
2014-01-20 09:40:36 +04:00
|
|
|
dumpJSON(path +'/'+ cur_file, DATA.current)
|
|
|
|
|
|
|
|
|
|
// save created images...
|
|
|
|
|
if(IMAGES_CREATED){
|
|
|
|
|
showStatusQ('Saving: File: Images.')
|
|
|
|
|
saveFileImages(name, date)
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
// save the updated images...
|
2014-01-20 09:40:36 +04:00
|
|
|
} else if(IMAGES_UPDATED.length > 0){
|
|
|
|
|
showStatusQ('Saving: File: Images diff.')
|
|
|
|
|
saveFileImagesDiff(name, date)
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
2013-12-14 06:07:22 +04:00
|
|
|
|
2013-12-24 22:03:54 +04:00
|
|
|
// save the rest of the data...
|
2014-01-20 09:40:36 +04:00
|
|
|
runFileSavers(name, date)
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load a directory as-is
|
|
|
|
|
//
|
|
|
|
|
// XXX check if we need to pass down sorting settings to the generators...
|
2013-07-08 04:11:04 +04:00
|
|
|
function loadRawDir(path, no_preview_processing, prefix){
|
2013-06-07 00:56:43 +04:00
|
|
|
prefix = prefix == null ? 'Data' : prefix
|
|
|
|
|
prefix = prefix === false ? null : prefix
|
|
|
|
|
|
|
|
|
|
var files = listDir(path)
|
|
|
|
|
|
|
|
|
|
var res = $.Deferred()
|
|
|
|
|
|
2013-07-07 19:46:45 +04:00
|
|
|
// filter images...
|
2013-06-07 00:56:43 +04:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-08 18:28:10 +04:00
|
|
|
setBaseURL(path)
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
IMAGES = imagesFromUrls(image_paths)
|
|
|
|
|
res.notify(prefix, 'Loaded', 'Images.')
|
2013-06-14 13:16:27 +04:00
|
|
|
IMAGES_CREATED = true
|
2013-06-07 00:56:43 +04:00
|
|
|
|
|
|
|
|
DATA = dataFromImages(IMAGES)
|
|
|
|
|
res.notify(prefix, 'Loaded', 'Data.')
|
|
|
|
|
|
2013-07-08 04:11:04 +04:00
|
|
|
// XXX this will reload viewer...
|
|
|
|
|
//updateRibbonsFromFavDirs()
|
|
|
|
|
DATA.ribbons = ribbonsFromFavDirs(null, null, imageOrderCmp)
|
2013-06-07 00:56:43 +04:00
|
|
|
res.notify(prefix, 'Loaded', 'Fav dirs.')
|
|
|
|
|
|
|
|
|
|
MARKED = []
|
|
|
|
|
|
|
|
|
|
reloadViewer()
|
|
|
|
|
|
2013-07-08 05:43:54 +04:00
|
|
|
// read orientation form files...
|
2013-12-14 06:07:22 +04:00
|
|
|
res.notify(prefix, 'Loading', 'Images metadata.')
|
|
|
|
|
var o = $.when(
|
|
|
|
|
readImagesOrientationQ(),
|
|
|
|
|
readImagesDatesQ()
|
|
|
|
|
)
|
2013-07-08 04:11:04 +04:00
|
|
|
.done(function(){
|
2013-12-14 06:07:22 +04:00
|
|
|
res.notify(prefix, 'Loaded', 'Images metadata.')
|
2013-07-08 04:11:04 +04:00
|
|
|
})
|
|
|
|
|
|
2013-07-08 05:43:54 +04:00
|
|
|
// load/generate previews...
|
2013-07-08 04:11:04 +04:00
|
|
|
if(!no_preview_processing){
|
|
|
|
|
res.notify(prefix, 'Loading/Generating', 'Previews.')
|
|
|
|
|
var p = makeImagesPreviewsQ()
|
2014-01-23 06:56:17 +04:00
|
|
|
.depleted(function(){
|
2013-07-08 04:11:04 +04:00
|
|
|
res.notify(prefix, 'Loaded', 'Previews.')
|
|
|
|
|
})
|
2013-07-08 05:43:54 +04:00
|
|
|
|
2013-07-08 04:11:04 +04:00
|
|
|
} else {
|
|
|
|
|
var p = 0
|
|
|
|
|
}
|
2013-07-08 02:32:19 +04:00
|
|
|
|
2013-07-08 05:43:54 +04:00
|
|
|
// NOTE: we are not waiting for previews and orientation...
|
2013-06-07 00:56:43 +04:00
|
|
|
return res.resolve()
|
2013-07-08 05:43:54 +04:00
|
|
|
|
|
|
|
|
/* XXX do we need to make everyone wait for previews and orientation???
|
2013-07-08 04:11:04 +04:00
|
|
|
$.when(o, p).done(function(){
|
|
|
|
|
res.resolve()
|
|
|
|
|
})
|
|
|
|
|
return res
|
|
|
|
|
*/
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
//
|
2013-06-13 19:42:42 +04:00
|
|
|
// NOTE: this will create an images.json file in cache on opening an
|
|
|
|
|
// un-cached dir (XXX is this correct???)
|
2013-07-08 04:11:04 +04:00
|
|
|
function loadDir(path, no_preview_processing, prefix){
|
2013-06-07 00:56:43 +04:00
|
|
|
prefix = prefix == null ? 'Data' : prefix
|
|
|
|
|
prefix = prefix === false ? null : prefix
|
|
|
|
|
|
2013-07-14 20:53:30 +04:00
|
|
|
// stop all workers running on current image set before we
|
|
|
|
|
// move to the next...
|
2014-01-20 09:40:36 +04:00
|
|
|
// XXX is this the correct spot for this???
|
2013-07-14 20:53:30 +04:00
|
|
|
killAllWorkers()
|
|
|
|
|
|
2013-06-13 19:42:42 +04:00
|
|
|
IMAGES_CREATED = false
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
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...
|
2013-12-15 18:56:21 +04:00
|
|
|
if(files.indexOf(CONFIG.cache_dir) >= 0){
|
|
|
|
|
path = path +'/'+ CONFIG.cache_dir
|
2013-06-07 00:56:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bubbleProgress(prefix,
|
|
|
|
|
loadFileState(path, false), res, true)
|
|
|
|
|
.done(function(){
|
|
|
|
|
res.resolve()
|
|
|
|
|
})
|
|
|
|
|
.fail(function(){
|
2013-12-15 05:42:22 +04:00
|
|
|
bubbleProgress('Raw directory',
|
|
|
|
|
loadRawDir(orig_path, no_preview_processing), res)
|
2013-06-07 00:56:43 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load ribbon structure from fav directory tree
|
|
|
|
|
//
|
|
|
|
|
// XXX loads duplicate images....
|
|
|
|
|
function updateRibbonsFromFavDirs(){
|
|
|
|
|
DATA.ribbons = ribbonsFromFavDirs(null, null, imageOrderCmp)
|
|
|
|
|
sortImagesByDate()
|
|
|
|
|
reloadViewer()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-11-07 02:20:20 +04:00
|
|
|
function exportImageTo(gid, path, im_name, size){
|
|
|
|
|
path = path == null ? BASE_URL : path
|
|
|
|
|
im_name = im_name == null ? '%f' : im_name
|
|
|
|
|
size = size == null ? 1000 : size
|
|
|
|
|
|
|
|
|
|
// get correct preview...
|
|
|
|
|
var src = getBestPreview(gid, size).url
|
|
|
|
|
var orig = getImageFileName(gid)
|
|
|
|
|
|
|
|
|
|
// 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' : '')
|
2014-01-15 06:50:34 +04:00
|
|
|
// bookmarked status...
|
|
|
|
|
dest = dest.replace(/%\(([^)]*)\)b/, BOOKMARKS.indexOf(gid) >= 0 ? '$1' : '')
|
2013-11-07 02:20:20 +04:00
|
|
|
// gid...
|
|
|
|
|
dest = dest.replace('%gid', gid)
|
|
|
|
|
dest = dest.replace('%g', gid.slice(34))
|
|
|
|
|
|
|
|
|
|
dest = path +'/'+ dest
|
|
|
|
|
|
|
|
|
|
// copy...
|
|
|
|
|
// NOTE: the sad smily face here is here for JS compatibility ;)
|
2014-01-20 10:24:49 +04:00
|
|
|
return (function(src, dest){
|
|
|
|
|
return copyFile(src, dest)
|
2013-11-07 02:20:20 +04:00
|
|
|
.done(function(){
|
2014-01-21 06:19:33 +04:00
|
|
|
// XXX do we actually need this???
|
2013-11-07 02:20:20 +04:00
|
|
|
console.log(src, 'done.')
|
|
|
|
|
})
|
|
|
|
|
.fail(function(err){
|
2014-01-21 06:19:33 +04:00
|
|
|
// XXX do we actually need this???
|
2013-11-07 02:20:20 +04:00
|
|
|
console.warn(src, 'err:', err)
|
|
|
|
|
})
|
|
|
|
|
})(src, dest)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-21 16:58:33 +04:00
|
|
|
// Export current state to directory...
|
|
|
|
|
//
|
2013-07-01 18:25:33 +04:00
|
|
|
// 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...
|
2013-11-07 02:20:20 +04:00
|
|
|
function exportImagesTo(path, im_name, dir_name, size){
|
2013-06-21 16:58:33 +04:00
|
|
|
path = path == null ? BASE_URL : path
|
|
|
|
|
im_name = im_name == null ? '%f' : im_name
|
|
|
|
|
dir_name = dir_name == null ? 'fav' : dir_name
|
2013-06-21 17:23:09 +04:00
|
|
|
size = size == null ? 1000 : size
|
2013-06-21 16:58:33 +04:00
|
|
|
|
2014-01-21 06:19:33 +04:00
|
|
|
var res = $.Deferred()
|
2013-07-01 18:05:50 +04:00
|
|
|
|
2013-06-21 16:58:33 +04:00
|
|
|
var base_path = path
|
|
|
|
|
path = normalizePath(path)
|
|
|
|
|
|
|
|
|
|
var order = DATA.order
|
2013-07-01 18:25:33 +04:00
|
|
|
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)
|
2013-06-21 16:58:33 +04:00
|
|
|
|
2014-01-22 03:01:13 +04:00
|
|
|
// use an external pool...
|
2014-01-23 06:56:17 +04:00
|
|
|
//var pool = makeDeferredPool()
|
|
|
|
|
var pool = getWorkerQueue('Export previews', 64)
|
2014-01-20 20:57:56 +04:00
|
|
|
.depleted(function(){
|
|
|
|
|
showStatusQ('Export: done.')
|
|
|
|
|
res.resolve()
|
|
|
|
|
})
|
2014-01-20 10:24:49 +04:00
|
|
|
|
2013-06-21 16:58:33 +04:00
|
|
|
// 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]
|
|
|
|
|
|
2013-11-07 02:20:20 +04:00
|
|
|
// do global naming...
|
2013-06-21 16:58:33 +04:00
|
|
|
var dest = im_name
|
2013-07-01 18:25:33 +04:00
|
|
|
// global order...
|
2013-06-21 16:58:33 +04:00
|
|
|
var o = order.indexOf(gid) + ''
|
2013-07-01 18:25:33 +04:00
|
|
|
dest = dest.replace('%I', (Z + o).slice(o.length))
|
2013-07-03 01:44:03 +04:00
|
|
|
// current order...
|
2013-07-01 18:25:33 +04:00
|
|
|
var o = selection.indexOf(gid) + ''
|
2013-06-21 16:58:33 +04:00
|
|
|
dest = dest.replace('%i', (z + o).slice(o.length))
|
|
|
|
|
|
2014-01-22 03:01:13 +04:00
|
|
|
pool.enqueue(exportImageTo, gid, path, dest, size)
|
2013-06-21 16:58:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path = normalizePath(path +'/'+ dir_name)
|
|
|
|
|
}
|
2014-01-20 10:24:49 +04:00
|
|
|
|
2014-01-20 11:14:27 +04:00
|
|
|
return res
|
2013-06-21 16:58:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
/**********************************************************************
|
|
|
|
|
* Metadata readers...
|
|
|
|
|
*/
|
2013-07-08 01:59:30 +04:00
|
|
|
|
2013-07-08 04:11:04 +04:00
|
|
|
// NOTE: this will overwrite current image orientation...
|
|
|
|
|
//
|
2013-07-08 01:59:30 +04:00
|
|
|
// XXX this depends on getImageOrientation(...)
|
2013-12-14 06:07:22 +04:00
|
|
|
function readImageOrientation(gid, no_update_loaded){
|
2013-07-08 01:59:30 +04:00
|
|
|
gid = gid == null ? getImageGID() : gid
|
|
|
|
|
var img = IMAGES[gid]
|
|
|
|
|
|
2013-07-14 20:53:30 +04:00
|
|
|
if(img == null){
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-08 01:59:30 +04:00
|
|
|
return getImageOrientation(normalizePath(img.path))
|
|
|
|
|
.done(function(o){
|
2013-07-08 02:32:19 +04:00
|
|
|
var o_o = img.orientation
|
|
|
|
|
var o_f = img.flipped
|
|
|
|
|
|
2013-07-08 01:59:30 +04:00
|
|
|
img.orientation = o.orientation
|
|
|
|
|
img.flipped = o.flipped
|
|
|
|
|
|
2013-07-08 02:32:19 +04:00
|
|
|
// mark image dirty...
|
2013-12-15 03:38:15 +04:00
|
|
|
if(o_o != o.orientation || o_f != o.flipped){
|
|
|
|
|
imageUpdated(gid)
|
2013-07-08 02:32:19 +04:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:30:33 +04:00
|
|
|
// update image if loaded...
|
2013-07-08 01:59:30 +04:00
|
|
|
if(!no_update_loaded){
|
|
|
|
|
var o = getImage(gid)
|
|
|
|
|
if(o.length > 0){
|
|
|
|
|
updateImage(o)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2013-12-14 06:07:22 +04:00
|
|
|
function readImagesOrientation(gids, no_update_loaded){
|
2013-07-08 01:59:30 +04:00
|
|
|
gids = gids == null ? getClosestGIDs() : gids
|
|
|
|
|
var res = []
|
|
|
|
|
|
|
|
|
|
$.each(gids, function(_, gid){
|
2013-12-14 06:07:22 +04:00
|
|
|
res.push(readImageOrientation(gid, no_update_loaded))
|
2013-07-08 01:59:30 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return $.when.apply(null, res)
|
|
|
|
|
}
|
2013-12-14 06:07:22 +04:00
|
|
|
// queued version of readImagesOrientation(...)
|
2013-07-08 04:11:04 +04:00
|
|
|
//
|
2013-12-14 06:07:22 +04:00
|
|
|
function readImagesOrientationQ(gids, no_update_loaded){
|
2013-07-08 01:59:30 +04:00
|
|
|
gids = gids == null ? getClosestGIDs() : gids
|
|
|
|
|
|
2014-01-23 06:56:17 +04:00
|
|
|
var queue = getWorkerQueue('Read images orientation', 4)
|
2013-07-14 20:53:30 +04:00
|
|
|
|
2013-07-11 03:23:51 +04:00
|
|
|
var last = null
|
2013-07-11 02:46:21 +04:00
|
|
|
|
2013-07-11 04:12:56 +04:00
|
|
|
// attach workers to queue...
|
2013-07-08 01:59:30 +04:00
|
|
|
$.each(gids, function(_, gid){
|
2013-12-14 06:07:22 +04:00
|
|
|
last = queue.enqueue(readImageOrientation, gid, no_update_loaded)
|
2013-07-11 03:23:51 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return queue
|
2013-07-08 01:59:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-14 06:07:22 +04:00
|
|
|
function readImageDate(gid, images){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
var img = images[gid]
|
|
|
|
|
return getEXIFDate(normalizePath(img.path))
|
|
|
|
|
.done(function(date){
|
|
|
|
|
img.ctime = Date.fromTimeStamp(date).getTime()/1000
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
function readImagesDates(images){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
|
|
|
|
|
return $.when.apply(null, $.map(images, function(_, gid){
|
|
|
|
|
return readImageDate(gid, images)
|
|
|
|
|
.done(function(){
|
2013-12-15 03:38:15 +04:00
|
|
|
imageUpdated(gid)
|
2013-12-14 06:07:22 +04:00
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
function readImagesDatesQ(images){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
|
2014-01-23 06:56:17 +04:00
|
|
|
var queue = getWorkerQueue('Read images dates', 4)
|
2013-12-14 06:07:22 +04:00
|
|
|
|
|
|
|
|
$.each(images, function(gid, img){
|
|
|
|
|
queue.enqueue(readImageDate, gid, images)
|
|
|
|
|
.always(function(){
|
2013-12-15 03:38:15 +04:00
|
|
|
imageUpdated(gid)
|
2014-01-22 03:01:13 +04:00
|
|
|
//queue.notify(gid, 'done')
|
2013-12-14 06:07:22 +04:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return queue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// XXX deleting images is not sported, we need to explicitly re-save...
|
|
|
|
|
// XXX need to reload the viewer...
|
|
|
|
|
// XXX not tested...
|
|
|
|
|
function updateImageGID(gid, images, data){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
var img = images[gid]
|
|
|
|
|
return getEXIFGID(normalizePath(img.path))
|
|
|
|
|
.done(function(gid){
|
|
|
|
|
img.id = gid
|
|
|
|
|
// images...
|
|
|
|
|
images[gid] = images[key]
|
|
|
|
|
delete images[key]
|
2013-12-15 03:38:15 +04:00
|
|
|
imageUpdated(gid)
|
2013-12-14 06:07:22 +04:00
|
|
|
|
|
|
|
|
// data...
|
|
|
|
|
if(data != null){
|
|
|
|
|
// replace current...
|
|
|
|
|
if(data.current == key){
|
|
|
|
|
data.current = gid
|
|
|
|
|
}
|
|
|
|
|
// replace in order...
|
|
|
|
|
data.order[data.order.indexOf(key)] = gid
|
|
|
|
|
// replace in ribbons...
|
|
|
|
|
for(var i=0; i < data.ribbons; i++){
|
|
|
|
|
var r = data.ribbons[i]
|
|
|
|
|
var k = r.indexOf(key)
|
|
|
|
|
if(k >= 0){
|
|
|
|
|
r[k] = gid
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
function updateImagesGIDs(images, data){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
|
|
|
|
|
return $.when.apply(null, $.map(images, function(_, key){
|
|
|
|
|
return updateImageGID(key, images, data)
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
function updateImagesGIDsQ(images, data){
|
|
|
|
|
images = images == null ? IMAGES : images
|
|
|
|
|
|
2014-01-23 06:56:17 +04:00
|
|
|
var queue = getWorkerQueue('Update GIDs', 4)
|
2013-12-14 06:07:22 +04:00
|
|
|
|
|
|
|
|
$.each(images, function(_, key){
|
|
|
|
|
queue.enqueue(updateImageGID, key, images, data)
|
2014-01-22 03:01:13 +04:00
|
|
|
.always(function(){
|
|
|
|
|
//queue.notify(key, 'done')
|
|
|
|
|
})
|
2013-12-14 06:07:22 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return queue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-07-08 01:59:30 +04:00
|
|
|
|
2013-06-07 00:56:43 +04:00
|
|
|
/**********************************************************************
|
|
|
|
|
* vim:set ts=4 sw=4 : */
|