diff --git a/ui/data.js b/ui/data.js index d39f61d0..e7ae5f00 100755 --- a/ui/data.js +++ b/ui/data.js @@ -262,24 +262,23 @@ function cmp(a, b, get){ // NOTE: this expects gids... function imageDateCmp(a, b, get, data){ data = data == null ? IMAGES : data - if(get == null){ - return data[b].ctime - data[a].ctime - } else { - return data[get(b)].ctime - data[get(a)].ctime + if(get != null){ + a = get(a) + b = get(b) } + return data[b].ctime - data[a].ctime } // NOTE: this expects gids... function imageNameCmp(a, b, get, data){ data = data == null ? IMAGES : data - if(get == null){ - a = data[a].path.split('/').pop() - b = data[b].path.split('/').pop() - } else { - a = data[get(a)].path.split('/').pop() - b = data[get(b)].path.split('/').pop() + if(get != null){ + a = get(a) + b = get(b) } + a = data[a].path.split('/').pop() + b = data[b].path.split('/').pop() if(a == b){ return 0 } else if(a < b){ @@ -290,14 +289,87 @@ function imageNameCmp(a, b, get, data){ } +// Get the first sequence of numbers in the file name... +function getImageNameSeq(gid, data){ + data = data == null ? IMAGES : data + var n = data[gid].path.split('/').pop() + var r = /([0-9]+)/m.exec(n) + return r == null ? n : parseInt(r[1]) +} + +// Get the first sequence of numbers in the file name but only if it is +// at the filename start... +function getImageNameLeadingSeq(gid, data){ + data = data == null ? IMAGES : data + var n = data[gid].path.split('/').pop() + var r = /^([0-9]+)/g.exec(n) + return r == null ? n : parseInt(r[1]) +} + + +// Compare images by sequence number (in filename) or by filename +// +// Examples: +// "1 file name", "012-file", "file 123 name", "DSC_1234" +// +// NOTE: if there are more than one sequence numbers in a filename then +// only the first is considered. +// NOTE: images with sequence number always precede images with plain +// filenames... +function imageSeqOrNameCmp(a, b, get, data, get_seq){ + data = data == null ? IMAGES : data + get_seq = get_seq == null ? getImageNameSeq : get_seq + if(get != null){ + a = get(a) + b = get(b) + } + + var aa = get_seq(a, data) + var bb = get_seq(b, data) + + // special case: seq, name + if(typeof(aa) == typeof(123) && typeof(bb) == typeof('str')){ return -1 } + // special case: name, seq + if(typeof(aa) == typeof('str') && typeof(bb) == typeof(123)){ return +1 } + + // get the names if there are no sequence numbers... + // NOTE: at this point both a and b are either numbers or NaN's... + a = isNaN(aa) ? data[a].path.split('/').pop() : aa + b = isNaN(bb) ? data[b].path.split('/').pop() : bb + + // do the actual comparison + if(a == b){ + return 0 + } else if(a < b){ + return -1 + } else { + return +1 + } +} + +// Sort images XP-style +// +// This will consider sequence numbers if they are at the start of the +// filename. +// +// Examples: +// "1 file name", "012-file" +// +// NOTE: images with sequence number always precede images with plain +// filenames... +function imageXPStyleFileNameCmp(a, b, get, data){ + return imageSeqOrNameCmp(a, b, get, data, getImageNameLeadingSeq) +} + + // NOTE: this expects gids... function imageOrderCmp(a, b, get, data){ data = data == null ? DATA : data - if(get == null){ - return data.order.indexOf(a) - data.order.indexOf(b) - } else { - return data.order.indexOf(get(a)) - data.order.indexOf(get(b)) + if(get != null){ + a = get(a) + b = get(b) } + return data.order.indexOf(a) - data.order.indexOf(b) } @@ -1785,6 +1857,12 @@ function sortImagesByDate(reverse){ function sortImagesByFileName(reverse){ return sortImages(imageNameCmp, reverse) } +function sortImagesByFileSeqOrName(reverse){ + return sortImages(imageSeqOrNameCmp, reverse) +} +function sortImagesByFileNameXPStyle(reverse){ + return sortImages(imageXPStyleFileNameCmp, reverse) +} // Sort images by name while taking into account sequence overflows @@ -1793,7 +1871,9 @@ function sortImagesByFileName(reverse){ // *9999 and then resets to *0001... // // For this to be applicable: -// - filenames must comply with /....[0-9]{4}/ +// - ALL filenames must contain a sequence number +// XXX do we need to make this more strict? +// ...for example make name.split() equal for all files // - the total number of files in sequence is < 10K // XXX a simplification... // there could be more than 10K images but then we will need to @@ -1805,10 +1885,12 @@ function sortImagesByFileName(reverse){ // number of files in set // XXX a simplification... // +// NOTE: at this pint the gap size must be above proximity*10 // NOTE: if any of the above conditions is not applicable this will -// essentially revert to sortImagesByFileName(...) +// essentially revert to sortImagesByFileSeqOrName(...) // NOTE: this will cut at the largest gap between sequence numbers. // +// XXX it would be a good idea to account for folder name sequencing... // XXX it's also a good idea to write an image serial number sort... // XXX is this overcomplicated??? // @@ -1816,54 +1898,50 @@ function sortImagesByFileName(reverse){ // ever know it's here, if we replace it with the thee line dumb // sortImagesByFileName(...) then things get "annoying" every 10K // images :) -function sortImagesByNameWithSeqOverflow(reverse, proximity){ +function sortImagesByFileNameSeqWithOverflow(reverse, proximity){ proximity = proximity == null ? 10 : proximity // prepare to sort and check names... // NOTE: we do not usually have a filename seq 0000... if(DATA.order.length < 9999){ - var pattern = /....[0-9]{4}[a-z]?(\....[.])?/ var need_to_fix = true function cmp(a, b){ if(need_to_fix){ - // check filename compliance... - var aa = pattern.test(IMAGES[a].path.split('/').pop()) - var bb = pattern.test(IMAGES[b].path.split('/').pop()) - if(!aa && !bb){ + if(typeof(getImageNameSeq(a)) == typeof('str') + || typeof(getImageNameSeq(b)) == typeof('str')){ need_to_fix = false } } - return imageNameCmp(a, b) - } - function getSeq(gid){ - return parseInt(IMAGES[gid].path.split('/').pop().slice(4)) + return imageSeqOrNameCmp(a, b) } // revert to normal sort my name... - // XXX this is not needed but will make things faster... } else { + // XXX make this more cleaver -- split the set into 10K chunks and + // sort the chunks too... return sortImagesByFileName(reverse) } DATA.order.sort(cmp) + // find and fix the gap... if(need_to_fix // check if first and last are close to 0001 and 9999 resp. - && getSeq(DATA.order[0]) <= proximity - && getSeq(DATA.order[DATA.order.length-1]) >= 9999-proximity){ + && getImageNameSeq(DATA.order[0]) <= proximity + && getImageNameSeq(DATA.order[DATA.order.length-1]) >= 9999-proximity){ // find the largest gap position... var pos = null var gap = 0 for(var i=1; i proximity){ + if(gap > proximity*10){ DATA.order = DATA.order.splice(pos).concat(DATA.order) } } @@ -1875,11 +1953,6 @@ function sortImagesByNameWithSeqOverflow(reverse, proximity){ } -// Set the default filename sort... -// XXX is this the correct way to do this??? -var sortImagesByName = sortImagesByNameWithSeqOverflow - - /************************************************** Manual sorting ***/ diff --git a/ui/layout.css b/ui/layout.css index bf11de12..f1299a84 100644 --- a/ui/layout.css +++ b/ui/layout.css @@ -1173,6 +1173,9 @@ button:hover { .overlay-block .dialog table tr td:last-child { color: silver; } +.overlay-block .dialog .choice .item { + text-align: left; +} /************************************************************ Help ***/ /* XXX make this more generic, and not just for the keyboard... */ /* this is for sliding stuff */ diff --git a/ui/layout.less b/ui/layout.less index e44f1dea..a5b46ebe 100755 --- a/ui/layout.less +++ b/ui/layout.less @@ -1217,6 +1217,10 @@ button:hover { color: silver; } +.overlay-block .dialog .choice .item { + text-align: left; +} + /************************************************************ Help ***/ diff --git a/ui/ui.js b/ui/ui.js index 4b7b71c6..adbb0600 100755 --- a/ui/ui.js +++ b/ui/ui.js @@ -978,9 +978,16 @@ function sortImagesDialog(message){ cfg = {} cfg[message] = [ 'Date (ascending)', - 'Name (ascending)', - 'Date (decending)', - 'Name (decending)' + 'Date (descending)', + + 'Sequence number (ascending)', + 'Sequence number (descending)', + + 'Sequence number with overflow (ascending)', + 'Sequence number with overflow (descending)', + + 'File name (ascending)', + 'File name (descending)' ] formDialog(null, '', @@ -990,10 +997,20 @@ function sortImagesDialog(message){ .done(function(res){ res = res[message] - if(/Date/.test(res)){ + if(/Date/i.test(res)){ var method = sortImagesByDate + + } else if(/File name/i.test(res)){ + var method = sortImagesByFileNameXPStyle + + } else if(/Sequence/i.test(res) && !/with overflow/.test(res)){ + var method = sortImagesByFileSeqOrName + + } else if(/Sequence/i.test(res) && /with overflow/.test(res)){ + var method = sortImagesByFileNameSeqWithOverflow + } else { - var method = sortImagesByName + var method = sortImagesByFileName } if(/\(ascending\)/.test(res)){ var reverse = null