mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +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
|
||||
[_] 62% 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
|
||||
[_] 63% High priority
|
||||
[_] BUG: sorting breaks when at or near the end of a ribbon...
|
||||
|
|
||||
| Race condition...
|
||||
@ -148,6 +132,8 @@ Roadmap
|
||||
| because there is nothing wrong with sorting itself, just the
|
||||
| UI, the resulting state can be fixed by simply reloading the
|
||||
| viewer (reloadViewer(true) or ctrl-alt-r)
|
||||
|
|
||||
| NOTE: appears to affect beginning of the ribbon too...
|
||||
[_] BUG: sorting mis-aligns ribbons in some cases...
|
||||
| Example:
|
||||
| oooo... --[reverse]-> ...oooo
|
||||
@ -560,6 +546,21 @@ Roadmap
|
||||
| drops to last placeholder
|
||||
|
|
||||
[_] 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...
|
||||
| make a number of fields each accepting a filter -- string/regexp
|
||||
[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){
|
||||
gids = gids == null ? getClosestGIDs() : gids
|
||||
|
||||
var queue = getWorkerQueue('preview_generator')
|
||||
var queue = getWorkerQueue('Generate previews', 4)
|
||||
|
||||
// attach the workers to the queue...
|
||||
$.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???
|
||||
//.progress(function(state){ queue.notify(state) })
|
||||
.always(function(){ queue.notify(gid, 'done') })
|
||||
.always(function(){ console.log(gid, 'done') })
|
||||
})
|
||||
|
||||
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){
|
||||
res.notify(prefix, 'Loading/Generating', 'Previews.')
|
||||
var p = makeImagesPreviewsQ()
|
||||
.done(function(){
|
||||
.depleted(function(){
|
||||
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)
|
||||
|
||||
// use an external pool...
|
||||
var pool = makeDeferredPool()
|
||||
//var pool = makeDeferredPool()
|
||||
var pool = getWorkerQueue('Export previews', 64)
|
||||
.depleted(function(){
|
||||
showStatusQ('Export: done.')
|
||||
res.resolve()
|
||||
@ -929,7 +930,7 @@ function readImagesOrientation(gids, no_update_loaded){
|
||||
function readImagesOrientationQ(gids, no_update_loaded){
|
||||
gids = gids == null ? getClosestGIDs() : gids
|
||||
|
||||
var queue = getWorkerQueue('image_orientation_reader')
|
||||
var queue = getWorkerQueue('Read images orientation', 4)
|
||||
|
||||
var last = null
|
||||
|
||||
@ -963,7 +964,7 @@ function readImagesDates(images){
|
||||
function readImagesDatesQ(images){
|
||||
images = images == null ? IMAGES : images
|
||||
|
||||
var queue = getWorkerQueue('date_reader')
|
||||
var queue = getWorkerQueue('Read images dates', 4)
|
||||
|
||||
$.each(images, function(gid, img){
|
||||
queue.enqueue(readImageDate, gid, images)
|
||||
@ -1020,7 +1021,7 @@ function updateImagesGIDs(images, data){
|
||||
function updateImagesGIDsQ(images, data){
|
||||
images = images == null ? IMAGES : images
|
||||
|
||||
var queue = getWorkerQueue('gid_updater')
|
||||
var queue = getWorkerQueue('Update GIDs', 4)
|
||||
|
||||
$.each(images, function(_, key){
|
||||
queue.enqueue(updateImageGID, key, images, data)
|
||||
|
||||
@ -79,7 +79,10 @@ var KEYBOARD_CONFIG = {
|
||||
},
|
||||
F5: doc('Full reload viewer',
|
||||
function(){
|
||||
reload()
|
||||
killAllWorkers()
|
||||
.done(function(){
|
||||
reload()
|
||||
})
|
||||
return false
|
||||
}),
|
||||
F12: doc('Show devTools',
|
||||
|
||||
@ -1141,6 +1141,64 @@ button:hover {
|
||||
font-size: 14px;
|
||||
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 ***/
|
||||
.single-image-mode.viewer .ribbon {
|
||||
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 ***/
|
||||
|
||||
.single-image-mode.viewer .ribbon {
|
||||
|
||||
@ -628,7 +628,6 @@ jQuery.fn.sortChildren = function(func){
|
||||
// Register a progress handler.
|
||||
// The handler is called after each worker is done and will get
|
||||
// passed:
|
||||
// - pool
|
||||
// - workers done count
|
||||
// - workers total count
|
||||
// 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.
|
||||
// The handler is called when a worker goes into the fail state.
|
||||
// This will get passed:
|
||||
// - pool
|
||||
// - workers done count
|
||||
// - workers total count
|
||||
// NOTE: this will not stop the execution of other handlers.
|
||||
@ -698,7 +696,7 @@ function makeDeferredPool(size, paused){
|
||||
var i = pool.indexOf(worker)
|
||||
|
||||
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...
|
||||
@ -715,7 +713,7 @@ function makeDeferredPool(size, paused){
|
||||
// if pool is empty fire the pause event...
|
||||
if(pool.len() == 0){
|
||||
Pool._pause_handlers.forEach(function(func){
|
||||
func(that)
|
||||
func()
|
||||
})
|
||||
}
|
||||
return
|
||||
@ -730,12 +728,13 @@ function makeDeferredPool(size, paused){
|
||||
|
||||
// empty queue AND empty pool mean we are done...
|
||||
} else if(pool.len() == 0){
|
||||
var l = pool.length
|
||||
// NOTE: potential race condition -- something can be
|
||||
// pushed to pool just before it's "compacted"...
|
||||
pool.length = 0
|
||||
|
||||
that._deplete_handlers.forEach(function(func){
|
||||
func(that)
|
||||
func(l)
|
||||
})
|
||||
}
|
||||
|
||||
@ -744,7 +743,7 @@ function makeDeferredPool(size, paused){
|
||||
})
|
||||
.fail(function(){
|
||||
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)
|
||||
})
|
||||
|
||||
@ -16,16 +16,61 @@ var WORKERS = {}
|
||||
|
||||
// get/create a named worker queue...
|
||||
//
|
||||
// XXX rename this to task-related.... (???)
|
||||
function getWorkerQueue(name, pool_size, no_auto_start){
|
||||
// XXX rename this to something task-related.... (???)
|
||||
function getWorkerQueue(name, pool_size, no_auto_start, no_progress){
|
||||
// XXX 1 is the default for compatibility...
|
||||
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...
|
||||
if(WORKERS[name] == null){
|
||||
var queue = makeDeferredPool(pool_size, no_auto_start)
|
||||
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...
|
||||
} else {
|
||||
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(){
|
||||
for(var k in WORKERS){
|
||||
var res = $.Deferred()
|
||||
var w = []
|
||||
Object.keys(WORKERS).forEach(function(k){
|
||||
if(WORKERS[k].isRunning()){
|
||||
console.log('Worker: Stopped:', k)
|
||||
var wd = $.Deferred()
|
||||
w.push(wd)
|
||||
WORKERS[k]
|
||||
.depleted(function(){
|
||||
console.log('Worker: Stopped:', k)
|
||||
wd.resolve()
|
||||
})
|
||||
}
|
||||
WORKERS[k].dropQueue()
|
||||
}
|
||||
WORKERS[k]
|
||||
.dropQueue()
|
||||
})
|
||||
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