mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 02:40:08 +00:00
added progress indication to workers (STUB?)...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
389264f09d
commit
ba46bc3707
35
ui/TODO.otl
35
ui/TODO.otl
@ -109,23 +109,7 @@ Roadmap
|
|||||||
|
|
||||||
|
|
||||||
[_] 31% Gen 3 current todo
|
[_] 31% Gen 3 current todo
|
||||||
[_] 62% High priority
|
[_] 63% High priority
|
||||||
[_] Might be a good idea to use sparse arrays for things like marks...
|
|
||||||
| eliminate:
|
|
||||||
| - need for keeping things sorted all the time
|
|
||||||
| - speed-up access -- everything has the same index
|
|
||||||
| - speed-up modification -- just mirror all the operations
|
|
||||||
| - searching in more than one place
|
|
||||||
|
|
|
||||||
| introduce:
|
|
||||||
| - memory overhead - each array is always N elements
|
|
||||||
| - conversion on import, export and crop
|
|
||||||
| need to clear / insert all the nulls
|
|
||||||
|
|
|
||||||
| candidates:
|
|
||||||
| - marks
|
|
||||||
| - bookmarks
|
|
||||||
| - tags
|
|
||||||
[_] BUG: sorting breaks when at or near the end of a ribbon...
|
[_] BUG: sorting breaks when at or near the end of a ribbon...
|
||||||
|
|
|
|
||||||
| Race condition...
|
| Race condition...
|
||||||
@ -148,6 +132,8 @@ Roadmap
|
|||||||
| because there is nothing wrong with sorting itself, just the
|
| because there is nothing wrong with sorting itself, just the
|
||||||
| UI, the resulting state can be fixed by simply reloading the
|
| UI, the resulting state can be fixed by simply reloading the
|
||||||
| viewer (reloadViewer(true) or ctrl-alt-r)
|
| viewer (reloadViewer(true) or ctrl-alt-r)
|
||||||
|
|
|
||||||
|
| NOTE: appears to affect beginning of the ribbon too...
|
||||||
[_] BUG: sorting mis-aligns ribbons in some cases...
|
[_] BUG: sorting mis-aligns ribbons in some cases...
|
||||||
| Example:
|
| Example:
|
||||||
| oooo... --[reverse]-> ...oooo
|
| oooo... --[reverse]-> ...oooo
|
||||||
@ -560,6 +546,21 @@ Roadmap
|
|||||||
| drops to last placeholder
|
| drops to last placeholder
|
||||||
|
|
|
|
||||||
[_] single image mode transition (alpha-blend/fade/none)
|
[_] single image mode transition (alpha-blend/fade/none)
|
||||||
|
[X] Might be a good idea to use sparse arrays for things like marks...
|
||||||
|
| eliminate:
|
||||||
|
| - need for keeping things sorted all the time
|
||||||
|
| - speed-up access -- everything has the same index
|
||||||
|
| - speed-up modification -- just mirror all the operations
|
||||||
|
| - searching in more than one place
|
||||||
|
|
|
||||||
|
| introduce:
|
||||||
|
| - conversion on import, export and crop
|
||||||
|
| need to clear / insert all the nulls
|
||||||
|
|
|
||||||
|
| candidates:
|
||||||
|
| - marks
|
||||||
|
| - bookmarks
|
||||||
|
| - tags
|
||||||
[X] crop/filter/search dialog...
|
[X] crop/filter/search dialog...
|
||||||
| make a number of fields each accepting a filter -- string/regexp
|
| make a number of fields each accepting a filter -- string/regexp
|
||||||
[X] Q: how do we mark unsorted sections in base ribbon after aligning?
|
[X] Q: how do we mark unsorted sections in base ribbon after aligning?
|
||||||
|
|||||||
@ -364,14 +364,14 @@ if(window.CEF_dumpJSON != null){
|
|||||||
window.makeImagesPreviewsQ = function(gids, sizes, mode){
|
window.makeImagesPreviewsQ = function(gids, sizes, mode){
|
||||||
gids = gids == null ? getClosestGIDs() : gids
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
|
|
||||||
var queue = getWorkerQueue('preview_generator')
|
var queue = getWorkerQueue('Generate previews', 4)
|
||||||
|
|
||||||
// attach the workers to the queue...
|
// attach the workers to the queue...
|
||||||
$.each(gids, function(_, gid){
|
$.each(gids, function(_, gid){
|
||||||
queue.enqueue(null, makeImagePreviews, gid, sizes, mode)
|
queue.enqueue(makeImagePreviews, gid, sizes, mode)
|
||||||
// XXX do we need to report seporate previews???
|
// XXX do we need to report seporate previews???
|
||||||
//.progress(function(state){ queue.notify(state) })
|
//.progress(function(state){ queue.notify(state) })
|
||||||
.always(function(){ queue.notify(gid, 'done') })
|
.always(function(){ console.log(gid, 'done') })
|
||||||
})
|
})
|
||||||
|
|
||||||
return queue
|
return queue
|
||||||
|
|||||||
11
ui/files.js
11
ui/files.js
@ -684,7 +684,7 @@ function loadRawDir(path, no_preview_processing, prefix){
|
|||||||
if(!no_preview_processing){
|
if(!no_preview_processing){
|
||||||
res.notify(prefix, 'Loading/Generating', 'Previews.')
|
res.notify(prefix, 'Loading/Generating', 'Previews.')
|
||||||
var p = makeImagesPreviewsQ()
|
var p = makeImagesPreviewsQ()
|
||||||
.done(function(){
|
.depleted(function(){
|
||||||
res.notify(prefix, 'Loaded', 'Previews.')
|
res.notify(prefix, 'Loaded', 'Previews.')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -844,7 +844,8 @@ function exportImagesTo(path, im_name, dir_name, size){
|
|||||||
var z = (('10e' + (selection.length + '').length) * 1 + '').slice(2)
|
var z = (('10e' + (selection.length + '').length) * 1 + '').slice(2)
|
||||||
|
|
||||||
// use an external pool...
|
// use an external pool...
|
||||||
var pool = makeDeferredPool()
|
//var pool = makeDeferredPool()
|
||||||
|
var pool = getWorkerQueue('Export previews', 64)
|
||||||
.depleted(function(){
|
.depleted(function(){
|
||||||
showStatusQ('Export: done.')
|
showStatusQ('Export: done.')
|
||||||
res.resolve()
|
res.resolve()
|
||||||
@ -929,7 +930,7 @@ function readImagesOrientation(gids, no_update_loaded){
|
|||||||
function readImagesOrientationQ(gids, no_update_loaded){
|
function readImagesOrientationQ(gids, no_update_loaded){
|
||||||
gids = gids == null ? getClosestGIDs() : gids
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
|
|
||||||
var queue = getWorkerQueue('image_orientation_reader')
|
var queue = getWorkerQueue('Read images orientation', 4)
|
||||||
|
|
||||||
var last = null
|
var last = null
|
||||||
|
|
||||||
@ -963,7 +964,7 @@ function readImagesDates(images){
|
|||||||
function readImagesDatesQ(images){
|
function readImagesDatesQ(images){
|
||||||
images = images == null ? IMAGES : images
|
images = images == null ? IMAGES : images
|
||||||
|
|
||||||
var queue = getWorkerQueue('date_reader')
|
var queue = getWorkerQueue('Read images dates', 4)
|
||||||
|
|
||||||
$.each(images, function(gid, img){
|
$.each(images, function(gid, img){
|
||||||
queue.enqueue(readImageDate, gid, images)
|
queue.enqueue(readImageDate, gid, images)
|
||||||
@ -1020,7 +1021,7 @@ function updateImagesGIDs(images, data){
|
|||||||
function updateImagesGIDsQ(images, data){
|
function updateImagesGIDsQ(images, data){
|
||||||
images = images == null ? IMAGES : images
|
images = images == null ? IMAGES : images
|
||||||
|
|
||||||
var queue = getWorkerQueue('gid_updater')
|
var queue = getWorkerQueue('Update GIDs', 4)
|
||||||
|
|
||||||
$.each(images, function(_, key){
|
$.each(images, function(_, key){
|
||||||
queue.enqueue(updateImageGID, key, images, data)
|
queue.enqueue(updateImageGID, key, images, data)
|
||||||
|
|||||||
@ -79,7 +79,10 @@ var KEYBOARD_CONFIG = {
|
|||||||
},
|
},
|
||||||
F5: doc('Full reload viewer',
|
F5: doc('Full reload viewer',
|
||||||
function(){
|
function(){
|
||||||
|
killAllWorkers()
|
||||||
|
.done(function(){
|
||||||
reload()
|
reload()
|
||||||
|
})
|
||||||
return false
|
return false
|
||||||
}),
|
}),
|
||||||
F12: doc('Show devTools',
|
F12: doc('Show devTools',
|
||||||
|
|||||||
@ -1141,6 +1141,64 @@ button:hover {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
/*************************************************** Progress bars ***/
|
||||||
|
progress {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
progress::-webkit-progress-bar {
|
||||||
|
background: transparent;
|
||||||
|
border: solid 1px gray;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 1px;
|
||||||
|
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2) inset;
|
||||||
|
}
|
||||||
|
progress::-webkit-progress-value {
|
||||||
|
background: yellow;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: -1px -1px 5px -2px rgba(0, 0, 0, 0.8) inset;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
progress:not(value)::-webkit-progress-bar {
|
||||||
|
background: transparent;
|
||||||
|
background-image:
|
||||||
|
-webkit-linear-gradient(-45deg, transparent 33%, rgba(0,0,0,0.2) 33%,
|
||||||
|
rgba(0,0,0,0.2) 66%, transparent 66%),
|
||||||
|
-webkit-linear-gradient(left, yellow, orange, yellow);
|
||||||
|
background-size: 50px 50px;
|
||||||
|
|
||||||
|
-webkit-animation: animate-progress 5s linear infinite;
|
||||||
|
animation: animate-progress 5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes animate-progress {
|
||||||
|
100% {
|
||||||
|
background-position: -100% 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes animate-progress {
|
||||||
|
100% {
|
||||||
|
background-position: -100% 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
.progress-container {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.progress-container:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
color: silver;
|
||||||
|
font-size: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.progress-bar progress {
|
||||||
|
display: block;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
/********************************************** Mode: single image ***/
|
/********************************************** Mode: single image ***/
|
||||||
.single-image-mode.viewer .ribbon {
|
.single-image-mode.viewer .ribbon {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|||||||
@ -1186,6 +1186,71 @@ button:hover {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************** Progress bars ***/
|
||||||
|
progress {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
progress::-webkit-progress-bar {
|
||||||
|
background: transparent;
|
||||||
|
border: solid 1px gray;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 1px;
|
||||||
|
box-shadow: 0px 2px 5px rgba(0,0,0,0.2) inset;
|
||||||
|
}
|
||||||
|
progress::-webkit-progress-value {
|
||||||
|
background: yellow;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: -1px -1px 5px -2px rgba(0,0,0,0.8) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
progress:not(value)::-webkit-progress-bar {
|
||||||
|
background: transparent;
|
||||||
|
background-image:
|
||||||
|
-webkit-linear-gradient(-45deg, transparent 33%, rgba(0,0,0,0.2) 33%,
|
||||||
|
rgba(0,0,0,0.2) 66%, transparent 66%),
|
||||||
|
-webkit-linear-gradient(left, yellow, orange, yellow);
|
||||||
|
background-size: 50px 50px;
|
||||||
|
|
||||||
|
-webkit-animation: animate-progress 5s linear infinite;
|
||||||
|
animation: animate-progress 5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes animate-progress {
|
||||||
|
100% {
|
||||||
|
background-position: -100% 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes animate-progress {
|
||||||
|
100% {
|
||||||
|
background-position: -100% 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.progress-container:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
color: silver;
|
||||||
|
font-size: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.progress-bar progress {
|
||||||
|
display: block;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************** Mode: single image ***/
|
/********************************************** Mode: single image ***/
|
||||||
|
|
||||||
.single-image-mode.viewer .ribbon {
|
.single-image-mode.viewer .ribbon {
|
||||||
|
|||||||
@ -628,7 +628,6 @@ jQuery.fn.sortChildren = function(func){
|
|||||||
// Register a progress handler.
|
// Register a progress handler.
|
||||||
// The handler is called after each worker is done and will get
|
// The handler is called after each worker is done and will get
|
||||||
// passed:
|
// passed:
|
||||||
// - pool
|
|
||||||
// - workers done count
|
// - workers done count
|
||||||
// - workers total count
|
// - workers total count
|
||||||
// NOTE: the total number of workers can change as new workers
|
// NOTE: the total number of workers can change as new workers
|
||||||
@ -638,7 +637,6 @@ jQuery.fn.sortChildren = function(func){
|
|||||||
// Register a worker fail handler.
|
// Register a worker fail handler.
|
||||||
// The handler is called when a worker goes into the fail state.
|
// The handler is called when a worker goes into the fail state.
|
||||||
// This will get passed:
|
// This will get passed:
|
||||||
// - pool
|
|
||||||
// - workers done count
|
// - workers done count
|
||||||
// - workers total count
|
// - workers total count
|
||||||
// NOTE: this will not stop the execution of other handlers.
|
// NOTE: this will not stop the execution of other handlers.
|
||||||
@ -698,7 +696,7 @@ function makeDeferredPool(size, paused){
|
|||||||
var i = pool.indexOf(worker)
|
var i = pool.indexOf(worker)
|
||||||
|
|
||||||
Pool._progress_handlers.forEach(function(func){
|
Pool._progress_handlers.forEach(function(func){
|
||||||
func(worker, pool.length - pool.len(), pool.length + queue.length)
|
func(pool.length - pool.len(), pool.length + queue.length)
|
||||||
})
|
})
|
||||||
|
|
||||||
// remove self from queue...
|
// remove self from queue...
|
||||||
@ -715,7 +713,7 @@ function makeDeferredPool(size, paused){
|
|||||||
// if pool is empty fire the pause event...
|
// if pool is empty fire the pause event...
|
||||||
if(pool.len() == 0){
|
if(pool.len() == 0){
|
||||||
Pool._pause_handlers.forEach(function(func){
|
Pool._pause_handlers.forEach(function(func){
|
||||||
func(that)
|
func()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -730,12 +728,13 @@ function makeDeferredPool(size, paused){
|
|||||||
|
|
||||||
// empty queue AND empty pool mean we are done...
|
// empty queue AND empty pool mean we are done...
|
||||||
} else if(pool.len() == 0){
|
} else if(pool.len() == 0){
|
||||||
|
var l = pool.length
|
||||||
// NOTE: potential race condition -- something can be
|
// NOTE: potential race condition -- something can be
|
||||||
// pushed to pool just before it's "compacted"...
|
// pushed to pool just before it's "compacted"...
|
||||||
pool.length = 0
|
pool.length = 0
|
||||||
|
|
||||||
that._deplete_handlers.forEach(function(func){
|
that._deplete_handlers.forEach(function(func){
|
||||||
func(that)
|
func(l)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,7 +743,7 @@ function makeDeferredPool(size, paused){
|
|||||||
})
|
})
|
||||||
.fail(function(){
|
.fail(function(){
|
||||||
Pool._fail_handlers.forEach(function(func){
|
Pool._fail_handlers.forEach(function(func){
|
||||||
func(that, pool.length - pool.len(), pool.length + queue.length)
|
func(pool.length - pool.len(), pool.length + queue.length)
|
||||||
})
|
})
|
||||||
deferred.reject.apply(deferred, arguments)
|
deferred.reject.apply(deferred, arguments)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -16,16 +16,61 @@ var WORKERS = {}
|
|||||||
|
|
||||||
// get/create a named worker queue...
|
// get/create a named worker queue...
|
||||||
//
|
//
|
||||||
// XXX rename this to task-related.... (???)
|
// XXX rename this to something task-related.... (???)
|
||||||
function getWorkerQueue(name, pool_size, no_auto_start){
|
function getWorkerQueue(name, pool_size, no_auto_start, no_progress){
|
||||||
// XXX 1 is the default for compatibility...
|
// XXX 1 is the default for compatibility...
|
||||||
pool_size = pool_size == null ? 1 : pool_size
|
pool_size = pool_size == null ? 1 : pool_size
|
||||||
|
|
||||||
|
// XXX experimental -- STUB...
|
||||||
|
if(!no_progress){
|
||||||
|
var container = $('.progress-container')
|
||||||
|
if(container.length == 0){
|
||||||
|
container = $('<div class="progress-container"/>')
|
||||||
|
.appendTo($('.viewer'))
|
||||||
|
}
|
||||||
|
var progress = $('<div class="progress-bar">'+name+'</div>')
|
||||||
|
.appendTo(container)
|
||||||
|
var progress_state = $('<span class="state"/>')
|
||||||
|
.appendTo(progress)
|
||||||
|
var progress_bar = $('<progress id="'+name+'"/>')
|
||||||
|
.appendTo(progress)
|
||||||
|
|
||||||
|
// XXX for some reason without this, here the progress handlers
|
||||||
|
// later lose context...
|
||||||
|
progress = $(progress[0])
|
||||||
|
progress_bar = $(progress_bar[0])
|
||||||
|
}
|
||||||
|
|
||||||
// create a new worker queue...
|
// create a new worker queue...
|
||||||
if(WORKERS[name] == null){
|
if(WORKERS[name] == null){
|
||||||
var queue = makeDeferredPool(pool_size, no_auto_start)
|
var queue = makeDeferredPool(pool_size, no_auto_start)
|
||||||
WORKERS[name] = queue
|
WORKERS[name] = queue
|
||||||
|
|
||||||
|
// XXX experimental...
|
||||||
|
if(!no_progress){
|
||||||
|
queue
|
||||||
|
.progress(function(done, total){
|
||||||
|
progress_bar
|
||||||
|
.attr({
|
||||||
|
value: done,
|
||||||
|
max: total
|
||||||
|
})
|
||||||
|
progress_state
|
||||||
|
.text(' ('+done+' of '+total+')')
|
||||||
|
})
|
||||||
|
.depleted(function(done){
|
||||||
|
progress_bar
|
||||||
|
.attr('value', done)
|
||||||
|
progress_state
|
||||||
|
.text(' (done)')
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
progress
|
||||||
|
.remove()
|
||||||
|
}, 1500)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// return existing worker queue...
|
// return existing worker queue...
|
||||||
} else {
|
} else {
|
||||||
var queue = WORKERS[name]
|
var queue = WORKERS[name]
|
||||||
@ -35,15 +80,35 @@ function getWorkerQueue(name, pool_size, no_auto_start){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// kill all worker queues...
|
// Kill all worker queues...
|
||||||
|
//
|
||||||
|
// Returns a deffered object that will get resolved when all workers are
|
||||||
|
// actually stopped...
|
||||||
function killAllWorkers(){
|
function killAllWorkers(){
|
||||||
for(var k in WORKERS){
|
var res = $.Deferred()
|
||||||
|
var w = []
|
||||||
|
Object.keys(WORKERS).forEach(function(k){
|
||||||
if(WORKERS[k].isRunning()){
|
if(WORKERS[k].isRunning()){
|
||||||
|
var wd = $.Deferred()
|
||||||
|
w.push(wd)
|
||||||
|
WORKERS[k]
|
||||||
|
.depleted(function(){
|
||||||
console.log('Worker: Stopped:', k)
|
console.log('Worker: Stopped:', k)
|
||||||
|
wd.resolve()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
WORKERS[k].dropQueue()
|
WORKERS[k]
|
||||||
}
|
.dropQueue()
|
||||||
|
})
|
||||||
WORKERS = {}
|
WORKERS = {}
|
||||||
|
|
||||||
|
$.when.apply(null, w)
|
||||||
|
.done(function(){
|
||||||
|
console.log('Worker: All workers stopped.')
|
||||||
|
res.resolve()
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user